diff --git a/BUILD.gn b/BUILD.gn index 10c1bd16f5ba4a3fc97067b6061b52928f6b83e4..fbbfe4760bc54ece6c9e6d01728eaaf190f776bf 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -33,7 +33,10 @@ group("ark_js_host_linux_tools_packages") { "//ark/js_runtime/ecmascript/js_vm:ark_js_vm(${host_toolchain})", ] if (is_standard_system) { - deps += [ "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer(${host_toolchain})" ] + deps += [ + "//ark/js_runtime/ecmascript/compiler:ark_stub_opt(${host_toolchain})", + "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer(${host_toolchain})", + ] } } } @@ -352,6 +355,7 @@ ecma_source = [ "ecmascript/snapshot/mem/slot_bit.cpp", "ecmascript/snapshot/mem/snapshot.cpp", "ecmascript/snapshot/mem/snapshot_serialize.cpp", + "ecmascript/stub_module.cpp", "ecmascript/tagged_dictionary.cpp", "ecmascript/template_string.cpp", "ecmascript/vmstat/caller_stat.cpp", diff --git a/ecmascript/compiler/BUILD.gn b/ecmascript/compiler/BUILD.gn index 4d29631c0471c49d749ad954ddfda304bdacc28a..8b32d8264e8eb1b208835d650d3aef6051a0e4ed 100644 --- a/ecmascript/compiler/BUILD.gn +++ b/ecmascript/compiler/BUILD.gn @@ -15,8 +15,8 @@ import("//ark/js_runtime/js_runtime_config.gni") import("//build/ohos.gni") action("build_llvm_libs") { - script = "build_llvm.sh" - sources = [ "//ark/js_runtime/ecmascript/compiler/build_llvm.sh" ] + script = "compile_llvm_lib.sh" + sources = [ "//ark/js_runtime/ecmascript/compiler/compile_llvm_lib.sh" ] outputs = [ "${root_out_dir}/llvm" ] } @@ -42,15 +42,15 @@ ohos_shared_library("libark_jsoptimizer") { sources = [ "circuit.cpp", "circuit_builder.cpp", - "circuit_visualizer.cpp", - "fastpath_optimizer.cpp", + "fast_stub.cpp", "gate.cpp", + "llvm_codegen.cpp", "llvm_ir_builder.cpp", - "llvm_mcjit_compiler.cpp", + "llvm_mcjit_engine.cpp", "llvm_stackmap_parse.cpp", "scheduler.cpp", - "stub_interface.cpp", - "stub_optimizer.cpp", + "stub.cpp", + "stub_descriptor.cpp", "type.cpp", "verifier.cpp", ] @@ -141,3 +141,30 @@ ohos_shared_library("libark_jsoptimizer") { relative_install_dir = "ark" subsystem_name = "ark" } + +ohos_executable("ark_stub_opt") { + sources = [ "stub_aot_compiler.cpp" ] + + configs = [ + ":include_llvm", + ":ark_jsruntime_compiler_config", + "//ark/js_runtime:ark_jsruntime_public_config", + "$ark_root/runtime:arkruntime_public_config", + ] + + deps = [ + "$ark_root/libpandabase:libarkbase", + "//ark/js_runtime:libark_jsruntime", + "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer", + ] + + if (!is_standard_system) { + deps += [ "$ark_root/runtime:libarkruntime" ] + } + + part_name = "ark_js_runtime" + install_enable = false + + output_name = "ark_stub_opt" + subsystem_name = "ark" +} diff --git a/ecmascript/compiler/circuit_builder.cpp b/ecmascript/compiler/circuit_builder.cpp index 307edc8b58f54d21d4812127c83b2083c8cccafe..171f51f0da5c600e11ebdae06a67bfd565c5a4df 100644 --- a/ecmascript/compiler/circuit_builder.cpp +++ b/ecmascript/compiler/circuit_builder.cpp @@ -301,7 +301,7 @@ OpCode CircuitBuilder::GetCallOpCodeFromMachineType(MachineType type) } } -AddrShift CircuitBuilder::NewCallGate(StubInterfaceDescriptor *descriptor, AddrShift target, +AddrShift CircuitBuilder::NewCallGate(StubDescriptor *descriptor, AddrShift target, std::initializer_list args) { std::vector inputs; @@ -316,7 +316,7 @@ AddrShift CircuitBuilder::NewCallGate(StubInterfaceDescriptor *descriptor, AddrS return circuit_->NewGate(opcode, args.size() + 1, inputs, TypeCode::JS_ANY); } -AddrShift CircuitBuilder::NewCallGate(StubInterfaceDescriptor *descriptor, AddrShift target, AddrShift depend, +AddrShift CircuitBuilder::NewCallGate(StubDescriptor *descriptor, AddrShift target, AddrShift depend, std::initializer_list args) { std::vector inputs; @@ -329,10 +329,10 @@ AddrShift CircuitBuilder::NewCallGate(StubInterfaceDescriptor *descriptor, AddrS return circuit_->NewGate(opcode, args.size() + 1, inputs, TypeCode::JS_ANY); } -AddrShift CircuitBuilder::NewCallRuntimeGate(StubInterfaceDescriptor *descriptor, AddrShift thread, AddrShift target, +AddrShift CircuitBuilder::NewCallRuntimeGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, std::initializer_list args) { - ASSERT(descriptor->GetStubKind() == StubInterfaceDescriptor::RUNTIME_STUB); + ASSERT(descriptor->GetStubKind() == StubDescriptor::RUNTIME_STUB); std::vector inputs; auto dependEntry = Circuit::GetCircuitRoot(OpCode(OpCode::DEPEND_ENTRY)); inputs.push_back(dependEntry); @@ -346,10 +346,10 @@ AddrShift CircuitBuilder::NewCallRuntimeGate(StubInterfaceDescriptor *descriptor return circuit_->NewGate(opcode, args.size() + 2, inputs, TypeCode::JS_ANY); } -AddrShift CircuitBuilder::NewCallRuntimeGate(StubInterfaceDescriptor *descriptor, AddrShift thread, AddrShift target, +AddrShift CircuitBuilder::NewCallRuntimeGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, AddrShift depend, std::initializer_list args) { - ASSERT(descriptor->GetStubKind() == StubInterfaceDescriptor::RUNTIME_STUB); + ASSERT(descriptor->GetStubKind() == StubDescriptor::RUNTIME_STUB); std::vector inputs; inputs.push_back(depend); inputs.push_back(target); diff --git a/ecmascript/compiler/circuit_builder.h b/ecmascript/compiler/circuit_builder.h index 35e3c473934d9b6c1d9f66f4067e8137c03d7900..db8fb140632412dc36ddf3c6dcf30643d612945c 100644 --- a/ecmascript/compiler/circuit_builder.h +++ b/ecmascript/compiler/circuit_builder.h @@ -19,7 +19,7 @@ #include "ecmascript/compiler/circuit.h" #include "ecmascript/compiler/gate.h" #include "ecmascript/compiler/machine_type.h" -#include "ecmascript/compiler/stub_interface.h" +#include "ecmascript/compiler/stub_descriptor.h" namespace kungfu { class CircuitBuilder { @@ -55,12 +55,12 @@ public: AddrShift NewArithMeticGate(OpCode opcode, AddrShift value); AddrShift NewLogicGate(OpCode opcode, AddrShift left, AddrShift right); AddrShift NewLogicGate(OpCode opcode, AddrShift value); - AddrShift NewCallGate(StubInterfaceDescriptor *descriptor, AddrShift target, std::initializer_list args); - AddrShift NewCallGate(StubInterfaceDescriptor *descriptor, AddrShift target, AddrShift depend, + AddrShift NewCallGate(StubDescriptor *descriptor, AddrShift target, std::initializer_list args); + AddrShift NewCallGate(StubDescriptor *descriptor, AddrShift target, AddrShift depend, std::initializer_list args); - AddrShift NewCallRuntimeGate(StubInterfaceDescriptor *descriptor, AddrShift thread, AddrShift target, + AddrShift NewCallRuntimeGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, std::initializer_list args); - AddrShift NewCallRuntimeGate(StubInterfaceDescriptor *descriptor, AddrShift thread, AddrShift target, + AddrShift NewCallRuntimeGate(StubDescriptor *descriptor, AddrShift thread, AddrShift target, AddrShift depend, std::initializer_list args); static OpCode GetLoadOpCodeFromMachineType(MachineType type); static OpCode GetStoreOpCodeFromMachineType(MachineType type); diff --git a/ecmascript/compiler/circuit_visualizer.h b/ecmascript/compiler/code_generator.h similarity index 45% rename from ecmascript/compiler/circuit_visualizer.h rename to ecmascript/compiler/code_generator.h index b968082360213bff6fc2dc0c17bcaae7ac6b3632..10ffe6f5c5bd79792c653a6c0dc2fe02a636d3e9 100644 --- a/ecmascript/compiler/circuit_visualizer.h +++ b/ecmascript/compiler/code_generator.h @@ -1,50 +1,43 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ECMASCRIPT_COMPILER_CIRCUIT_VISUALIZER_H -#define ECMASCRIPT_COMPILER_CIRCUIT_VISUALIZER_H - -#include -#include -#include -#include -#include "circuit.h" -#include "gate.h" - -namespace kungfu { -#ifndef NDEBUG -// This class dump graph in graphviz format -// Option: --compiler-graph-visualizer - -class CircuitVisualizer { -public: - explicit CircuitVisualizer(Circuit *graph) : graph_(graph) {} - - void CreateDumpFile(const char *file_name); - void DumpDFG(); - void PrintGate(Gate *node, int depth); - ~CircuitVisualizer() = default; -private: - void PrintGateVisit(Gate *node, std::ostream &os, int depth, int indentation = 0); - void PrintSingleGate(Gate *node, std::ostream &os); - Circuit *graph_; - std::ofstream dump_output_{nullptr}; - const char *pass_name_{nullptr}; - std::map node_info_; -}; -#endif -} // namespace kungfu - -#endif \ No newline at end of file +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMASCRIPT_COMPILER_CODE_GENERATOR_H +#define ECMASCRIPT_COMPILER_CODE_GENERATOR_H + +#include "circuit.h" + +namespace kungfu { +using ControlFlowGraph = std::vector>; +class CodeGeneratorImpl { +public: + CodeGeneratorImpl() = default; + virtual ~CodeGeneratorImpl() = default; + virtual void GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, int index) = 0; +}; + +class CodeGenerator { +public: + explicit CodeGenerator(CodeGeneratorImpl *impl) : impl_(impl) {} + ~CodeGenerator() = default; + void Run(Circuit *circuit, const ControlFlowGraph &graph, int index) + { + impl_->GenerateCodeForStub(circuit, graph, index); + } + +private: + CodeGeneratorImpl *impl_; +}; +} // namespace kungfu +#endif // ECMASCRIPT_COMPILER_CODE_GENERATOR_H \ No newline at end of file diff --git a/ecmascript/compiler/compile_llvm_lib.sh b/ecmascript/compiler/compile_llvm_lib.sh new file mode 100755 index 0000000000000000000000000000000000000000..58c117ed66e0976cb4030519ac5fe03035dd3bf9 --- /dev/null +++ b/ecmascript/compiler/compile_llvm_lib.sh @@ -0,0 +1,46 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e +echo "++++++++++++++++++++++++++++++++++" +echo "build llvm" +#date +%F ' '%H:%M:%S +#echo $@ + +BIN_PATH=$(cd $(dirname $0);pwd) +JSRUNTIME_HOME=$(dirname $(dirname ${BIN_PATH})) +BASE_HOME=${JSRUNTIME_HOME}/../../ + +echo ${BIN_PATH} +echo ${BASE_HOME} + +if [ ! -d ${BASE_HOME}/third_party/llvm-project ]; then + dd if=/dev/zero of=/tmp/mem.swap bs=1M count=4096 + git clone https://gitee.com/github-repos/llvm-project.git +fi + +cd ${BASE_HOME}/third_party/llvm-project +if [ ! -d "build" ];then + mkdir build && cd build + cmake -GNinja -DCMAKE_BUILD_TYPE=Release ../llvm + ninja +else + cd build + if [ ! -d "lib" ]; then + rm -rf * + cmake -GNinja -DCMAKE_BUILD_TYPE=Release ../llvm + ninja + fi +fi + +echo "++++++++++++++++++++++++++++++++++" \ No newline at end of file diff --git a/ecmascript/compiler/fast_stub.cpp b/ecmascript/compiler/fast_stub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..86ac7a834023b28c01564b7f099c6fb30e592c8c --- /dev/null +++ b/ecmascript/compiler/fast_stub.cpp @@ -0,0 +1,655 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fast_stub.h" +#include "ecmascript/base/number_helper.h" +#include "ecmascript/js_array.h" +#include "ecmascript/message_string.h" +#include "ecmascript/tagged_hash_table-inl.h" +#include "llvm_ir_builder.h" + +namespace kungfu { +using namespace panda::ecmascript; +void FastArrayLoadElementStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + AddrShift aVal = Int64Argument(0); + AddrShift indexVal = Int32Argument(1); + + // load a.length + AddrShift lengthOffset = GetInteger32Constant(JSArray::GetArrayLengthOffset()); + if (PtrValueCode() == ValueCode::INT64) { + lengthOffset = SExtInt32ToInt64(lengthOffset); + } else if (PtrValueCode() == ValueCode::INT32) { + aVal = TruncInt64ToInt32(aVal); + } + AddrShift taggedLength = Load(MachineType::TAGGED_TYPE, aVal, lengthOffset); + + AddrShift intLength = TaggedCastToInt32(taggedLength); + // if index < length + Label ifTrue(env); + Label ifFalse(env); + Branch(Int32LessThan(indexVal, intLength), &ifTrue, &ifFalse); + Bind(&ifTrue); + Return(LoadFromObject(MachineType::TAGGED_TYPE, aVal, indexVal)); + Bind(&ifFalse); + Return(GetUndefinedConstant()); +} + +void FastAddStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + AddrShift x = Int64Argument(0); + AddrShift y = Int64Argument(1); + DEFVARIABLE(intX, MachineType::INT32_TYPE, 0); + DEFVARIABLE(intY, MachineType::INT32_TYPE, 0); + DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); + DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); + Label xIsNumber(env); + Label xNotNumberOryNotNumber(env); + Label xIsNumberAndyIsNumber(env); + Label xIsDoubleAndyIsDouble(env); + Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber); + Bind(&xIsNumber); + { + Label yIsNumber(env); + // if right.IsNumber() + Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber); + Bind(&yIsNumber); + { + Label xIsInt(env); + Label xNotInt(env); + Branch(TaggedIsInt(x), &xIsInt, &xNotInt); + Bind(&xIsInt); + { + intX = TaggedCastToInt32(x); + doubleX = CastInt32ToFloat64(*intX); + Jump(&xIsNumberAndyIsNumber); + } + Bind(&xNotInt); + { + doubleX = TaggedCastToDouble(x); + Jump(&xIsNumberAndyIsNumber); + } + } + } + Bind(&xNotNumberOryNotNumber); + Return(GetHoleConstant()); + Label yIsInt(env); + Label yNotInt(env); + Bind(&xIsNumberAndyIsNumber); + { + Branch(TaggedIsInt(y), &yIsInt, &yNotInt); + Bind(&yIsInt); + { + intY = TaggedCastToInt32(y); + doubleY = CastInt32ToFloat64(*intY); + Jump(&xIsDoubleAndyIsDouble); + } + Bind(&yNotInt); + { + doubleY = TaggedCastToDouble(y); + Jump(&xIsDoubleAndyIsDouble); + } + } + Bind(&xIsDoubleAndyIsDouble); + doubleX = DoubleAdd(*doubleX, *doubleY); + Return(DoubleBuildTagged(*doubleX)); +} + +void FastSubStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + AddrShift x = Int64Argument(0); + AddrShift y = Int64Argument(1); + DEFVARIABLE(intX, MachineType::INT32_TYPE, 0); + DEFVARIABLE(intY, MachineType::INT32_TYPE, 0); + DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); + DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); + Label xIsNumber(env); + Label xNotNumberOryNotNumber(env); + Label xNotIntOryNotInt(env); + Label xIsIntAndyIsInt(env); + // if x is number + Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber); + Bind(&xIsNumber); + { + Label yIsNumber(env); + // if y is number + Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber); + { + Bind(&yIsNumber); + { + Label xIsInt(env); + Label xNotInt(env); + Branch(TaggedIsInt(x), &xIsInt, &xNotInt); + Bind(&xIsInt); + { + intX = TaggedCastToInt32(x); + Label yIsInt(env); + Label yNotInt(env); + Branch(TaggedIsInt(y), &yIsInt, &yNotInt); + Bind(&yIsInt); + { + intY = TaggedCastToInt32(y); + intX = Int32Sub(*intX, *intY); + Jump(&xIsIntAndyIsInt); + } + Bind(&yNotInt); + { + doubleY = TaggedCastToDouble(y); + doubleX = CastInt32ToFloat64(*intX); + Jump(&xNotIntOryNotInt); + } + } + Bind(&xNotInt); + { + Label yIsInt(env); + Label yNotInt(env); + doubleX = TaggedCastToDouble(x); + Branch(TaggedIsInt(y), &yIsInt, &yNotInt); + Bind(&yIsInt); + { + intY = TaggedCastToInt32(y); + doubleY = CastInt32ToFloat64(*intY); + Jump(&xNotIntOryNotInt); + } + Bind(&yNotInt); + { + doubleY = TaggedCastToDouble(y); + Jump(&xNotIntOryNotInt); + } + } + } + } + } + Bind(&xNotNumberOryNotNumber); + Return(GetHoleConstant()); + Bind(&xNotIntOryNotInt); + doubleX = DoubleSub(*doubleX, *doubleY); + Return(DoubleBuildTagged(*doubleX)); + Bind(&xIsIntAndyIsInt); + Return(IntBuildTagged(*intX)); +} + +void FastMulStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + AddrShift x = Int64Argument(0); + AddrShift y = Int64Argument(1); + DEFVARIABLE(intX, MachineType::INT32_TYPE, 0); + DEFVARIABLE(intY, MachineType::INT32_TYPE, 0); + DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); + DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); + Label xIsNumber(env); + Label xNotNumberOryNotNumber(env); + Label xIsNumberAndyIsNumber(env); + Label xIsDoubleAndyIsDouble(env); + Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber); + Bind(&xIsNumber); + { + Label yIsNumber(env); + // if right.IsNumber() + Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber); + Bind(&yIsNumber); + { + Label xIsInt(env); + Label xNotInt(env); + Branch(TaggedIsInt(x), &xIsInt, &xNotInt); + Bind(&xIsInt); + { + intX = TaggedCastToInt32(x); + doubleX = CastInt32ToFloat64(*intX); + Jump(&xIsNumberAndyIsNumber); + } + Bind(&xNotInt); + { + doubleX = TaggedCastToDouble(x); + Jump(&xIsNumberAndyIsNumber); + } + } + } + Bind(&xNotNumberOryNotNumber); + Return(GetHoleConstant()); + Label yIsInt(env); + Label yNotInt(env); + Bind(&xIsNumberAndyIsNumber); + { + Branch(TaggedIsInt(y), &yIsInt, &yNotInt); + Bind(&yIsInt); + { + intY = TaggedCastToInt32(y); + doubleY = CastInt32ToFloat64(*intY); + Jump(&xIsDoubleAndyIsDouble); + } + Bind(&yNotInt); + { + doubleY = TaggedCastToDouble(y); + Jump(&xIsDoubleAndyIsDouble); + } + } + Bind(&xIsDoubleAndyIsDouble); + doubleX = DoubleMul(*doubleX, *doubleY); + Return(DoubleBuildTagged(*doubleX)); +} + +void FastDivStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + AddrShift x = Int64Argument(0); + AddrShift y = Int64Argument(1); + DEFVARIABLE(intX, MachineType::INT32_TYPE, 0); + DEFVARIABLE(intY, MachineType::INT32_TYPE, 0); + DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); + DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); + Label xIsNumber(env); + Label xNotNumberOryNotNumber(env); + Label xIsNumberAndyIsNumber(env); + Label xIsDoubleAndyIsDouble(env); + Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber); + Bind(&xIsNumber); + { + Label yIsNumber(env); + // if right.IsNumber() + Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber); + Bind(&yIsNumber); + { + Label xIsInt(env); + Label xNotInt(env); + Branch(TaggedIsInt(x), &xIsInt, &xNotInt); + Bind(&xIsInt); + { + intX = TaggedCastToInt32(x); + doubleX = CastInt32ToFloat64(*intX); + Jump(&xIsNumberAndyIsNumber); + } + Bind(&xNotInt); + { + doubleX = TaggedCastToDouble(x); + Jump(&xIsNumberAndyIsNumber); + } + } + } + Bind(&xNotNumberOryNotNumber); + Return(GetHoleConstant()); + Label yIsInt(env); + Label yNotInt(env); + Bind(&xIsNumberAndyIsNumber); + Branch(TaggedIsInt(y), &yIsInt, &yNotInt); + Bind(&yIsInt); + { + intY = TaggedCastToInt32(y); + doubleY = CastInt32ToFloat64(*intY); + Jump(&xIsDoubleAndyIsDouble); + } + Bind(&yNotInt); + { + doubleY = TaggedCastToDouble(y); + Jump(&xIsDoubleAndyIsDouble); + } + Bind(&xIsDoubleAndyIsDouble); + { + Label divisorIsZero(env); + Label divisorNotZero(env); + Branch(DoubleEqual(*doubleY, GetDoubleConstant(0.0)), &divisorIsZero, &divisorNotZero); + Bind(&divisorIsZero); + { + Label xIsZeroOrNan(env); + Label xNeiZeroOrNan(env); + Label xIsZero(env); + Label xNotZero(env); + // dLeft == 0.0 || std::isnan(dLeft) + Branch(DoubleEqual(*doubleX, GetDoubleConstant(0.0)), &xIsZero, &xNotZero); + Bind(&xIsZero); + Jump(&xIsZeroOrNan); + Bind(&xNotZero); + { + Label xIsNan(env); + Label xNotNan(env); + Branch(DoubleIsNAN(*doubleX), &xIsNan, &xNotNan); + Bind(&xIsNan); + Jump(&xIsZeroOrNan); + Bind(&xNotNan); + Jump(&xNeiZeroOrNan); + } + Bind(&xIsZeroOrNan); + Return(DoubleBuildTagged(GetDoubleConstant(base::NAN_VALUE))); + Bind(&xNeiZeroOrNan); + { + AddrShift intXTmp = CastDoubleToInt64(*doubleX); + AddrShift intYtmp = CastDoubleToInt64(*doubleY); + intXTmp = Word64And(Word64Xor(intXTmp, intYtmp), GetWord64Constant(base::DOUBLE_SIGN_MASK)); + intXTmp = Word64Xor(intXTmp, CastDoubleToInt64(GetDoubleConstant(base::POSITIVE_INFINITY))); + doubleX = CastInt64ToFloat64(intXTmp); + Return(DoubleBuildTagged(*doubleX)); + } + } + Bind(&divisorNotZero); + { + doubleX = DoubleDiv(*doubleX, *doubleY); + Return(DoubleBuildTagged(*doubleX)); + } + } +} + +void FastFindOwnElementStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + AddrShift thread = PtrArgument(0); + AddrShift obj = PtrArgument(1); + AddrShift index = Int32Argument(2); // 2: 3rd parameter - index + + Label notDict(env); + Label isDict(env); + Label invalidValue(env); + Label end(env); + AddrShift elements = Load(POINTER_TYPE, obj, GetPtrConstant(JSObject::ELEMENTS_OFFSET)); + + Branch(IsDictionaryMode(elements), &isDict, ¬Dict); + Bind(¬Dict); + { + Label outOfArray(env); + Label notOutOfArray(env); + AddrShift arrayLength = Load(UINT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); + Branch(Int32LessThanOrEqual(arrayLength, index), &outOfArray, ¬OutOfArray); + Bind(&outOfArray); + Jump(&invalidValue); + Bind(¬OutOfArray); + { + AddrShift offset = PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(JSTaggedValue::TaggedTypeSize())); + AddrShift dataIndex = PtrAdd(offset, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); + AddrShift value = Load(TAGGED_TYPE, elements, dataIndex); + Label isHole1(env); + Label notHole1(env); + Branch(TaggedIsHole(value), &isHole1, ¬Hole1); + Bind(&isHole1); + Jump(&invalidValue); + Bind(¬Hole1); + Return(value); + } + Bind(&invalidValue); + Return(GetHoleConstant()); + } + // IsDictionary + Bind(&isDict); + { + AddrShift taggedIndex = IntBuildTagged(index); + AddrShift entry = FindElementFromNumberDictionary(thread, elements, taggedIndex); + Label notNegtiveOne(env); + Label negtiveOne(env); + Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), ¬NegtiveOne, &negtiveOne); + Bind(¬NegtiveOne); + { + Return(GetValueFromDictionary(elements, entry)); + } + Bind(&negtiveOne); + Jump(&end); + } + Bind(&end); + Return(GetHoleConstant()); +} + +void FastGetElementStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + AddrShift thread = PtrArgument(0); + AddrShift receiver = Int64Argument(1); + AddrShift index = Int64Argument(2); // 2: 3rd parameter - index + Label isHole(env); + Label notHole(env); + Label loopHead(env); + Label loopEnd(env); + Label afterLoop(env); + Label notHeapObj(env); + + Jump(&loopHead); + LoopBegin(&loopHead); + AddrShift objPtr = ChangeInt64ToPointer(receiver); + auto findOwnElementDescriptor = GET_STUBDESCRIPTOR(FindOwnElement); + AddrShift callFindOwnElementVal = + CallStub(findOwnElementDescriptor, GetWord64Constant(FAST_STUB_ID(FindOwnElement)), {thread, objPtr, index}); + Branch(TaggedIsHole(callFindOwnElementVal), &isHole, ¬Hole); + Bind(¬Hole); + Return(callFindOwnElementVal); + Bind(&isHole); + receiver = Load(TAGGED_TYPE, LoadHClass(objPtr), GetPtrConstant(JSHClass::PROTOTYPE_OFFSET)); + Branch(TaggedIsHeapObject(receiver), &loopEnd, ¬HeapObj); + Bind(¬HeapObj); + Return(GetUndefinedConstant()); + Bind(&loopEnd); + LoopEnd(&loopHead); +} + +void FastFindOwnElement2Stub::GenerateCircuit() +{ + auto env = GetEnvironment(); + AddrShift thread = PtrArgument(0); + AddrShift elements = PtrArgument(1); + AddrShift index = Int32Argument(2); // 2 : 3rd parameter + AddrShift isDict = Int32Argument(3); // 3 : 4th parameter + AddrShift attr = PtrArgument(4); // 4 : 5th parameter + AddrShift indexOrEntry = PtrArgument(5); // 5 : 6rd parameter + isDict = ZExtInt1ToInt32(isDict); + Label notDictionary(env); + Label isDictionary(env); + Label end(env); + Branch(Word32Equal(isDict, GetInteger32Constant(0)), ¬Dictionary, &isDictionary); + Bind(¬Dictionary); + { + AddrShift elementsLength = + Load(UINT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); + Label outOfElements(env); + Label notOutOfElements(env); + Branch(Int32LessThanOrEqual(elementsLength, index), &outOfElements, ¬OutOfElements); + Bind(&outOfElements); + { + Return(GetHoleConstant()); + } + Bind(¬OutOfElements); + { + AddrShift value = GetValueFromTaggedArray(elements, index); + Label isHole(env); + Label notHole(env); + Branch(TaggedIsHole(value), &isHole, ¬Hole); + Bind(&isHole); + Jump(&end); + Bind(¬Hole); + { + Store(UINT32_TYPE, attr, GetPtrConstant(0), + GetInteger32Constant(PropertyAttributes::GetDefaultAttributes())); + Store(UINT32_TYPE, indexOrEntry, GetPtrConstant(0), index); + Return(value); + } + } + } + Bind(&isDictionary); + { + AddrShift entry = FindElementFromNumberDictionary(thread, elements, IntBuildTagged(index)); + Label notNegtiveOne(env); + Label negtiveOne(env); + Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), ¬NegtiveOne, &negtiveOne); + Bind(¬NegtiveOne); + { + Store(UINT32_TYPE, attr, GetPtrConstant(0), GetAttributesFromDictionary(elements, entry)); + Store(UINT32_TYPE, indexOrEntry, GetPtrConstant(0), entry); + Return(GetValueFromDictionary(elements, entry)); + } + Bind(&negtiveOne); + Jump(&end); + } + Bind(&end); + Return(GetHoleConstant()); +} + +void FastSetElementStub::GenerateCircuit() +{ + auto env = GetEnvironment(); + AddrShift thread = PtrArgument(0); + AddrShift receiver = PtrArgument(1); + DEFVARIABLE(holder, MachineType::TAGGED_POINTER_TYPE, receiver); + AddrShift index = Int32Argument(2); // 2 : 3rd argument + AddrShift value = Int64Argument(3); // 3 : 4th argument + AddrShift mayThrow = Int32Argument(4); // 4 : 5th argument + DEFVARIABLE(onPrototype, MachineType::BOOL_TYPE, FalseConstant()); + + AddrShift pattr = Alloca(static_cast(MachineRep::K_WORD32)); + AddrShift pindexOrEntry = Alloca(static_cast(MachineRep::K_WORD32)); + Label loopHead(env); + Jump(&loopHead); + LoopBegin(&loopHead); + { + AddrShift elements = GetElements(*holder); + AddrShift isDictionary = IsDictionaryMode(elements); + StubDescriptor *findOwnElemnt2 = GET_STUBDESCRIPTOR(FindOwnElement2); + AddrShift val = CallStub(findOwnElemnt2, GetWord64Constant(FAST_STUB_ID(FindOwnElement2)), + {thread, elements, index, isDictionary, pattr, pindexOrEntry}); + Label notHole(env); + Label isHole(env); + Branch(TaggedIsNotHole(val), ¬Hole, &isHole); + Bind(¬Hole); + { + Label isOnProtoType(env); + Label notOnProtoType(env); + Label afterOnProtoType(env); + Branch(*onPrototype, &isOnProtoType, ¬OnProtoType); + Bind(¬OnProtoType); + Jump(&afterOnProtoType); + Bind(&isOnProtoType); + { + Label isExtensible(env); + Label notExtensible(env); + Label nextExtensible(env); + Branch(IsExtensible(receiver), &isExtensible, ¬Extensible); + Bind(&isExtensible); + Jump(&nextExtensible); + Bind(¬Extensible); + { + Label isThrow(env); + Label notThrow(env); + Branch(Word32NotEqual(mayThrow, GetInteger32Constant(0)), &isThrow, ¬Throw); + Bind(&isThrow); + ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible), FalseConstant()); + Bind(¬Throw); + Return(FalseConstant()); + } + Bind(&nextExtensible); + StubDescriptor *addElementInternal = GET_STUBDESCRIPTOR(AddElementInternal); + Return(CallRuntime(addElementInternal, thread, GetWord64Constant(FAST_STUB_ID(AddElementInternal)), + {thread, receiver, index, value, + GetInteger32Constant(PropertyAttributes::GetDefaultAttributes())})); + } + Bind(&afterOnProtoType); + { + AddrShift attr = Load(INT32_TYPE, pattr); + Label isAccessor(env); + Label notAccessor(env); + Branch(IsAcesscor(attr), &isAccessor, ¬Accessor); + Bind(¬Accessor); + { + Label isWritable(env); + Label notWritable(env); + Branch(IsWritable(attr), &isWritable, ¬Writable); + Bind(&isWritable); + { + AddrShift elements = GetElements(receiver); + Label isDict(env); + Label notDict(env); + AddrShift indexOrEntry = Load(INT32_TYPE, pindexOrEntry); + Branch(isDictionary, &isDict, ¬Dict); + Bind(¬Dict); + { + StoreElement(elements, indexOrEntry, value); + UpdateRepresention(LoadHClass(receiver), value); + Return(TrueConstant()); + } + Bind(&isDict); + { + UpdateValueAndAttributes(elements, indexOrEntry, value, attr); + Return(TrueConstant()); + } + } + Bind(¬Writable); + { + Label isThrow(env); + Label notThrow(env); + Branch(Word32NotEqual(mayThrow, GetInteger32Constant(0)), &isThrow, ¬Throw); + Bind(&isThrow); + ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetReadOnlyProperty), FalseConstant()); + Bind(¬Throw); + Return(FalseConstant()); + } + } + Bind(&isAccessor); + { + StubDescriptor *callsetter = GET_STUBDESCRIPTOR(CallSetter); + AddrShift setter = GetSetterFromAccessor(val); + Return(CallRuntime(callsetter, thread, GetWord64Constant(FAST_STUB_ID(CallSetter)), + {thread, setter, receiver, value, TruncInt32ToInt1(mayThrow)})); + } + } + } + Bind(&isHole); + { + // holder equals to + holder = GetPrototypeFromHClass(LoadHClass(*holder)); + Label isHeapObj(env); + Label notHeapObj(env); + Branch(TaggedIsObject(*holder), &isHeapObj, ¬HeapObj); + Bind(¬HeapObj); + { + Label isExtensible(env); + Label notExtensible(env); + Label nextExtensible(env); + Branch(IsExtensible(receiver), &isExtensible, ¬Extensible); + Bind(&isExtensible); + Jump(&nextExtensible); + Bind(¬Extensible); + { + Label isThrow(env); + Label notThrow(env); + Branch(Word32NotEqual(mayThrow, GetInteger32Constant(0)), &isThrow, ¬Throw); + Bind(&isThrow); + ThrowTypeAndReturn(thread, GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible), FalseConstant()); + Bind(¬Throw); + Return(FalseConstant()); + } + Bind(&nextExtensible); + { + StubDescriptor *addElementInternal = GET_STUBDESCRIPTOR(AddElementInternal); + Return(CallRuntime(addElementInternal, thread, GetWord64Constant(FAST_STUB_ID(AddElementInternal)), + {thread, receiver, index, value, + GetInteger32Constant(PropertyAttributes::GetDefaultAttributes())})); + } + } + Bind(&isHeapObj); + { + Label isJsProxy(env); + Label notJsProxy(env); + Branch(IsJsProxy(*holder), &isJsProxy, ¬JsProxy); + Bind(&isJsProxy); + { + StubDescriptor *setProperty = GET_STUBDESCRIPTOR(JSProxySetProperty); + Return(CallRuntime( + setProperty, thread, GetWord64Constant(FAST_STUB_ID(JSProxySetProperty)), + {thread, *holder, IntBuildTagged(index), value, receiver, TruncInt32ToInt1(mayThrow)})); + } + Bind(¬JsProxy); + onPrototype = TrueConstant(); + } + } + } + LoopEnd(&loopHead); +} +} // namespace kungfu \ No newline at end of file diff --git a/ecmascript/compiler/fast_stub.h b/ecmascript/compiler/fast_stub.h new file mode 100644 index 0000000000000000000000000000000000000000..7982183207828ca0544bee0aab03404d0edfca00 --- /dev/null +++ b/ecmascript/compiler/fast_stub.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMASCRIPT_COMPILER_FASTPATH_STUB_H +#define ECMASCRIPT_COMPILER_FASTPATH_STUB_H + +#include "ecmascript/compiler/fast_stub_define.h" +#include "ecmascript/compiler/stub.h" + +namespace kungfu { +class FastArrayLoadElementStub : public Stub { +public: + // 2 : 2 means argument counts + explicit FastArrayLoadElementStub(Circuit *circuit) : Stub("FastArrayLoadElement", 2, circuit) {} + ~FastArrayLoadElementStub() = default; + NO_MOVE_SEMANTIC(FastArrayLoadElementStub); + NO_COPY_SEMANTIC(FastArrayLoadElementStub); + void GenerateCircuit() override; +}; + +class FastAddStub : public Stub { +public: + // 2 : 2 means argument counts + explicit FastAddStub(Circuit *circuit) : Stub("FastAdd", 2, circuit) {} + ~FastAddStub() = default; + NO_MOVE_SEMANTIC(FastAddStub); + NO_COPY_SEMANTIC(FastAddStub); + void GenerateCircuit() override; +}; + +class FastSubStub : public Stub { +public: + // 2 : 2 means argument counts + explicit FastSubStub(Circuit *circuit) : Stub("FastSub", 2, circuit) {} + ~FastSubStub() = default; + NO_MOVE_SEMANTIC(FastSubStub); + NO_COPY_SEMANTIC(FastSubStub); + void GenerateCircuit() override; +}; + +class FastMulStub : public Stub { +public: + // 2 : 2 means argument counts + explicit FastMulStub(Circuit *circuit) : Stub("FastMul", 2, circuit) {} + ~FastMulStub() = default; + NO_MOVE_SEMANTIC(FastMulStub); + NO_COPY_SEMANTIC(FastMulStub); + void GenerateCircuit() override; +}; + +class FastDivStub : public Stub { +public: + // 2 : 2 means argument counts + explicit FastDivStub(Circuit *circuit) : Stub("FastDiv", 2, circuit) {} + ~FastDivStub() = default; + NO_MOVE_SEMANTIC(FastDivStub); + NO_COPY_SEMANTIC(FastDivStub); + void GenerateCircuit() override; +}; + +class FastFindOwnElementStub : public Stub { +public: + // 3 : 3 means argument counts + explicit FastFindOwnElementStub(Circuit *circuit) : Stub("FastFindOwnElement", 3, circuit) {} + ~FastFindOwnElementStub() = default; + NO_MOVE_SEMANTIC(FastFindOwnElementStub); + NO_COPY_SEMANTIC(FastFindOwnElementStub); + void GenerateCircuit() override; +}; + +class FastGetElementStub : public Stub { +public: + // 3 : 3 means argument counts + explicit FastGetElementStub(Circuit *circuit) : Stub("FastGetElement", 3, circuit) {} + ~FastGetElementStub() = default; + NO_MOVE_SEMANTIC(FastGetElementStub); + NO_COPY_SEMANTIC(FastGetElementStub); + void GenerateCircuit() override; +}; + +class FastFindOwnElement2Stub : public Stub { +public: + // 6 : 6 means argument counts + explicit FastFindOwnElement2Stub(Circuit *circuit) : Stub("FastFindOwnElement2", 6, circuit) {} + ~FastFindOwnElement2Stub() = default; + NO_MOVE_SEMANTIC(FastFindOwnElement2Stub); + NO_COPY_SEMANTIC(FastFindOwnElement2Stub); + void GenerateCircuit() override; +}; + +class FastSetElementStub : public Stub { +public: + // 5 : 5 means argument counts + explicit FastSetElementStub(Circuit *circuit) : Stub("FastSetElement", 5, circuit) {} + ~FastSetElementStub() = default; + NO_MOVE_SEMANTIC(FastSetElementStub); + NO_COPY_SEMANTIC(FastSetElementStub); + void GenerateCircuit() override; +}; +} // namespace kungfu +#endif // ECMASCRIPT_COMPILER_FASTPATH_STUB_H \ No newline at end of file diff --git a/ecmascript/compiler/fast_stub_define.h b/ecmascript/compiler/fast_stub_define.h index 9dbc8ab846fc7c2d1f2eace4e65f4a4c2df5287f..e56ce3cd0cb22be60761dc0bb20a23562d012c75 100644 --- a/ecmascript/compiler/fast_stub_define.h +++ b/ecmascript/compiler/fast_stub_define.h @@ -20,7 +20,9 @@ namespace kungfu { // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define EXTERNAL_RUNTIMESTUB_LIST(V) \ V(AddElementInternal, 5) \ - V(CallSetter, 2) \ + V(CallSetter, 4) \ + V(CallGetter, 4) \ + V(AccessorGetter, 4) \ V(ThrowTypeError, 2) \ V(JSProxySetProperty, 6) \ V(GetHash32, 2) @@ -66,5 +68,8 @@ enum CallStubId { #undef DEF_FAST_STUB CALL_STUB_MAXCOUNT = EXTERN_RUNTIME_STUB_MAXCOUNT, }; + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define FAST_STUB_ID(name) kungfu::CallStubId::NAME_##name } // namespace kungfu #endif // ECMASCRIPT_COMPILER_FASTSTUB_DEFINE_H \ No newline at end of file diff --git a/ecmascript/compiler/fastpath_optimizer.h b/ecmascript/compiler/fastpath_optimizer.h deleted file mode 100644 index bf61207024cb64dc120da1095be43aea0d771772..0000000000000000000000000000000000000000 --- a/ecmascript/compiler/fastpath_optimizer.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ECMASCRIPT_COMPILER_FASTPATH_OPTIMIZER_H -#define ECMASCRIPT_COMPILER_FASTPATH_OPTIMIZER_H - -#include "ecmascript/compiler/fast_stub_define.h" -#include "ecmascript/compiler/stub_optimizer.h" - -namespace kungfu { -class FastArrayLoadElementOptimizer : public StubOptimizer { -public: - explicit FastArrayLoadElementOptimizer(Environment *env) : StubOptimizer(env) {} - ~FastArrayLoadElementOptimizer() = default; - NO_MOVE_SEMANTIC(FastArrayLoadElementOptimizer); - NO_COPY_SEMANTIC(FastArrayLoadElementOptimizer); - void GenerateCircuit() override; - uint8_t *AllocMachineCode() - { - static constexpr int PROT = PROT_READ | PROT_WRITE | PROT_EXEC; // NOLINT(hicpp-signed-bitwise) - static constexpr int FLAGS = MAP_ANONYMOUS | MAP_SHARED; // NOLINT(hicpp-signed-bitwise) - auto machineCode = static_cast(mmap(nullptr, MAX_MACHINE_CODE_SIZE, PROT, FLAGS, -1, 0)); - return machineCode; - } - void FreeMachineCode(uint8_t *machineCode) - { - munmap(machineCode, MAX_MACHINE_CODE_SIZE); - } - -private: - const size_t MAX_MACHINE_CODE_SIZE = (1U << 20U); -}; - -class FastRuntimeStubs { -public: - static FastRuntimeStubs &GetInstance() - { - static FastRuntimeStubs instance; - return instance; - } - enum FastRuntimeStubId { -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define FAST_RUNTIME_STUB_ID(name, counter) ID_##name, - FAST_RUNTIME_STUB_LIST(FAST_RUNTIME_STUB_ID) -#undef FAST_RUNTIME_STUB_ID - FAST_STUB_MAXNUMBER, - }; - - void GenerateFastRuntimeStubs(); - -private: - FastRuntimeStubs(); - ~FastRuntimeStubs(); - NO_MOVE_SEMANTIC(FastRuntimeStubs); - NO_COPY_SEMANTIC(FastRuntimeStubs); - std::array fastRuntimeEnvs_; - std::array fastRuntimeOptimizers_; -}; -} // namespace kungfu -#endif // ECMASCRIPT_COMPILER_FASTPATH_OPTIMIZER_H \ No newline at end of file diff --git a/ecmascript/compiler/fastpath_optimizer.cpp b/ecmascript/compiler/llvm_codegen.cpp similarity index 30% rename from ecmascript/compiler/fastpath_optimizer.cpp rename to ecmascript/compiler/llvm_codegen.cpp index 65ffd6a44912add99992bd9855921a49f6d38e07..f58bef33abafa3372e9b0865dffeefa0f2ccee83 100644 --- a/ecmascript/compiler/fastpath_optimizer.cpp +++ b/ecmascript/compiler/llvm_codegen.cpp @@ -1,56 +1,54 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ecmascript/compiler/fastpath_optimizer.h" -#include "ecmascript/js_array.h" -#include "ecmascript/tagged_hash_table-inl.h" - -namespace kungfu { -void FastArrayLoadElementOptimizer::GenerateCircuit() -{ - auto env = GetEnvironment(); - AddrShift aVal = Int64Argument(0); - AddrShift indexVal = Int32Argument(1); - - // load a.length - AddrShift lengthOffset = GetInteger32Constant(panda::ecmascript::JSArray::GetArrayLengthOffset()); - if (PtrValueCode() == ValueCode::INT64) { - lengthOffset = SExtInt32ToInt64(lengthOffset); - } else if (PtrValueCode() == ValueCode::INT32) { - aVal = TruncInt64ToInt32(aVal); - } - AddrShift taggegLength = Load(MachineType::TAGGED_TYPE, aVal, lengthOffset); - - AddrShift intLength = TaggedCastToInt32(taggegLength); - // if index < length - StubOptimizerLabel ifTrue(env); - StubOptimizerLabel ifFalse(env); - Branch(Int32LessThan(indexVal, intLength), &ifTrue, &ifFalse); - Bind(&ifTrue); - Return(LoadFromObject(MachineType::TAGGED_TYPE, aVal, indexVal)); - Bind(&ifFalse); - Return(GetUndefinedConstant()); -} - -FastRuntimeStubs::FastRuntimeStubs() - : fastRuntimeEnvs_{ -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define FAST_RUNTIME_STUB_ENV(name, arguments) Environment(#name, arguments), - FAST_RUNTIME_STUB_LIST(FAST_RUNTIME_STUB_ENV) -#undef FAST_RUNTIME_STUB_ENV - }, fastRuntimeOptimizers_{new FastArrayLoadElementOptimizer(&fastRuntimeEnvs_[1])} -{ -} -} // namespace kungfu \ No newline at end of file +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "llvm_codegen.h" +#include "ecmascript/object_factory.h" +#include "stub_descriptor.h" + +using namespace panda::ecmascript; +namespace kungfu { +void LLVMCodeGeneratorImpl::GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, int index) +{ + auto function = module_->GetStubFunction(index); + + LLVMIRBuilder builder(&graph, circuit, module_, function); + builder.Build(); +} + +void LLVMModuleAssembler::AssembleModule() +{ + assembler_.Run(); +} + +void LLVMModuleAssembler::CopyAssembleCodeToModule(StubModule *module) +{ + auto codeBuff = reinterpret_cast
(assembler_.GetCodeBuffer()); + auto engine = assembler_.GetEngine(); + for (int i = 0; i < FAST_STUB_MAXCOUNT; i++) { + auto stubfunction = stubmodule_->GetStubFunction(i); + if (stubfunction != nullptr) { + Address stubEntry = reinterpret_cast
(LLVMGetPointerToGlobal(engine, stubfunction)); + module->SetStubEntry(i, stubEntry - codeBuff); + } + } + + auto codeSize = assembler_.GetCodeSize(); + + MachineCode *code = reinterpret_cast(new char(sizeof(MachineCode) + codeSize)); + code->SetInstructionSizeInBytes(nullptr, JSTaggedValue(codeSize), SKIP_BARRIER); + code->SetData(reinterpret_cast(codeBuff), codeSize); + module->SetCode(code); +} +} // namespace kungfu diff --git a/ecmascript/compiler/llvm_codegen.h b/ecmascript/compiler/llvm_codegen.h new file mode 100644 index 0000000000000000000000000000000000000000..f55463005b7d77852781413f352afa22d68b9784 --- /dev/null +++ b/ecmascript/compiler/llvm_codegen.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMASCRIPT_COMPILER_LLVM_CODEGEN_H +#define ECMASCRIPT_COMPILER_LLVM_CODEGEN_H + +#include "code_generator.h" +#include "ecmascript/compiler/llvm_ir_builder.h" +#include "ecmascript/compiler/llvm_mcjit_engine.h" +#include "ecmascript/js_thread.h" +#include "ecmascript/stub_module.h" +#include "llvm-c/Types.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Support/Host.h" + +namespace kungfu { +class LLVMCodeGeneratorImpl : public CodeGeneratorImpl { +public: + explicit LLVMCodeGeneratorImpl(LLVMStubModule *module) : module_(module) {} + ~LLVMCodeGeneratorImpl() = default; + void GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, int index) override; + +private: + LLVMStubModule *module_; +}; + +class LLVMModuleAssembler { +public: + explicit LLVMModuleAssembler(LLVMStubModule *module) : stubmodule_(module), assembler_(module->GetModule()) {} + void AssembleModule(); + void CopyAssembleCodeToModule(panda::ecmascript::StubModule *module); + +private: + LLVMStubModule *stubmodule_; + LLVMAssembler assembler_; +}; +} // namespace kungfu +#endif // ECMASCRIPT_COMPILER_LLVM_CODEGEN_H \ No newline at end of file diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 22fa5a9adb66fb4d6652e2aeaae98271d045fca6..4d9d7489de7ac9c3085fdfe3d1e679f770df6988 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -18,14 +18,14 @@ #include #include "ecmascript/compiler/circuit.h" -#include "ecmascript/compiler/fastpath_optimizer.h" +#include "ecmascript/compiler/fast_stub.h" #include "ecmascript/compiler/gate.h" -#include "ecmascript/compiler/stub_interface.h" +#include "ecmascript/compiler/stub_descriptor.h" #include "ecmascript/js_array.h" #include "ecmascript/js_thread.h" #include "llvm/IR/Instructions.h" #include "llvm/Support/Host.h" -#include "llvm_mcjit_compiler.h" +#include "llvm_mcjit_engine.h" #include "securec.h" #include "utils/logger.h" @@ -56,6 +56,17 @@ LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule bbIdMapBb_.clear(); } +LLVMIRBuilder::LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, + LLVMStubModule *module, LLVMValueRef function) + : schedule_(schedule), circuit_(circuit), module_(module->GetModule()), + function_(function), stubModule_(module) +{ + LLVMSetTarget(module_, "x86_64-unknown-linux-gnu"); + builder_ = LLVMCreateBuilder(); + context_ = LLVMGetGlobalContext(); + bbIdMapBb_.clear(); +} + int LLVMIRBuilder::FindBasicBlock(AddrShift gate) const { for (size_t bbIdx = 0; bbIdx < schedule_->size(); bbIdx++) { @@ -360,9 +371,12 @@ void LLVMIRBuilder::Build() VisitStore(gate, MachineRep::K_WORD64, ins[2], ins[1]); // 2:baseAddr gate, 1:data gate break; } - case OpCode::INT32_TO_FLOAT64: // no break, fall through + case OpCode::INT32_TO_FLOAT64: { + VisitCastInt32ToDouble(gate, ins[0]); + break; + } case OpCode::INT64_TO_FLOAT64: { - VisitCastIntToDouble(gate, ins[0]); + VisitCastInt64ToDouble(gate, ins[0]); break; } case OpCode::FLOAT64_TO_INT64: { @@ -554,11 +568,13 @@ void LLVMIRBuilder::VisitCall(AddrShift gate, const std::vector &inLi { int paraStartIndex = 2; int index = circuit_->GetBitField(inList[1]); - LLVMValueRef callee = reinterpret_cast(FastStubs::GetInstance().GetFastStub(index)); - StubInterfaceDescriptor *callee_descriptor = FastStubs::GetInstance().GetStubDescriptor(index); + ASSERT(stubModule_ != nullptr); + LLVMValueRef callee; + StubDescriptor *callee_descriptor = FastStubDescriptors::GetInstance().GetStubDescriptor(index); // runtime case - if (callee_descriptor->GetStubKind() == StubInterfaceDescriptor::RUNTIME_STUB) { - LLVMTypeRef rtfuncType = reinterpret_cast(FastStubs::GetInstance().GetRunTimeLLVMType(index)); + if (callee_descriptor->GetStubKind() == StubDescriptor::CallStubKind::RUNTIME_STUB) { + LLVMTypeRef rtfuncType = stubModule_->GetExternalFunctionType(index); + LLVMDumpType(rtfuncType); LLVMTypeRef rtfuncTypePtr = LLVMPointerType(rtfuncType, 0); LLVMValueRef thread = g_values[inList[2]]; // 2 : 2 means skip two input gates (target thread ) LLVMValueRef rtoffset = LLVMConstInt(LLVMInt64Type(), @@ -575,6 +591,8 @@ void LLVMIRBuilder::VisitCall(AddrShift gate, const std::vector &inLi std::cout << std::endl; LLVMDumpValue(callee); paraStartIndex += 1; + } else { + callee = stubModule_->GetStubFunction(index); } // 16 : params limit LLVMValueRef params[16]; @@ -1031,7 +1049,7 @@ void LLVMIRBuilder::VisitCastIntXToIntY(AddrShift gate, AddrShift e1, MachineRep LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } -void LLVMIRBuilder::VisitCastIntToDouble(AddrShift gate, AddrShift e1) const +void LLVMIRBuilder::VisitCastInt32ToDouble(AddrShift gate, AddrShift e1) const { LOG_ECMA(INFO) << "int cast2 double gate:" << gate; LLVMValueRef e1Value = g_values[e1]; @@ -1041,13 +1059,87 @@ void LLVMIRBuilder::VisitCastIntToDouble(AddrShift gate, AddrShift e1) const LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } +void LLVMIRBuilder::VisitCastInt64ToDouble(AddrShift gate, AddrShift e1) const +{ + LOG_ECMA(INFO) << "int cast2 double gate:" << gate; + LLVMValueRef e1Value = g_values[e1]; + LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); + LLVMValueRef result = LLVMBuildBitCast(builder_, e1Value, LLVMDoubleType(), ""); + g_values[gate] = result; + LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); +} + void LLVMIRBuilder::VisitCastDoubleToInt(AddrShift gate, AddrShift e1) const { LOG_ECMA(INFO) << "double cast2 int gate:" << gate; LLVMValueRef e1Value = g_values[e1]; LOG_ECMA(INFO) << "operand 0: " << LLVMPrintValueToString(e1Value); - LLVMValueRef result = LLVMBuildFPToSI(builder_, e1Value, LLVMInt64Type(), ""); + LLVMValueRef result = LLVMBuildBitCast(builder_, e1Value, LLVMInt64Type(), ""); g_values[gate] = result; LOG_ECMA(INFO) << "result: " << LLVMPrintValueToString(result); } + +LLVMStubModule::LLVMStubModule(const char *name) +{ + module_ = LLVMModuleCreateWithName("fast_stubs"); +#ifdef PANDA_TARGET_AMD64 + LLVMSetTarget(module_, "x86_64-unknown-linux-gnu"); +#endif +} + +void LLVMStubModule::Initialize() +{ + uint32_t i; + for (i = 0; i < FAST_STUB_MAXCOUNT; i++) { + auto stubDescriptor = FastStubDescriptors::GetInstance().GetStubDescriptor(i); + if (!stubDescriptor->GetName().empty()) { + stubFunctions_[i] = GetLLVMFunctionByStubDescriptor(stubDescriptor); + } + } + for (i = 0; i < MAX_EXTERNAL_FUNCTION_COUNT; i++) { + auto externalDescriptor = FastStubDescriptors::GetInstance().GetStubDescriptor(i + EXTERNAL_FUNCTION_OFFSET); + if (!externalDescriptor->GetName().empty()) { + externalFuctionType_[i] = GetLLVMFunctionTypeStubDescriptor(externalDescriptor); + } + } +} + +LLVMValueRef LLVMStubModule::GetLLVMFunctionByStubDescriptor(StubDescriptor *stubDescriptor) +{ + auto funcType = GetLLVMFunctionTypeStubDescriptor(stubDescriptor); + return LLVMAddFunction(module_, stubDescriptor->GetName().c_str(), funcType); +} + +LLVMTypeRef LLVMStubModule::GetLLVMFunctionTypeStubDescriptor(StubDescriptor *stubDescriptor) +{ + LLVMTypeRef returnType = ConvertLLVMTypeFromMachineType(stubDescriptor->GetReturnType()); + std::vector paramTys; + auto paramCount = stubDescriptor->GetParametersCount(); + for (int i = 0; i < paramCount; i++) { + auto paramsType = stubDescriptor->GetParametersType(); + paramTys.push_back(ConvertLLVMTypeFromMachineType(paramsType[i])); + } + auto functype = LLVMFunctionType(returnType, paramTys.data(), paramCount, 0); + LLVMDumpType(functype); + return functype; +} + +LLVMTypeRef LLVMStubModule::ConvertLLVMTypeFromMachineType(MachineType type) +{ + static std::map machineTypeMap = { + {MachineType::NONE_TYPE, LLVMVoidType()}, + {MachineType::BOOL_TYPE, LLVMInt1Type()}, + {MachineType::INT8_TYPE, LLVMInt8Type()}, + {MachineType::INT16_TYPE, LLVMInt16Type()}, + {MachineType::INT32_TYPE, LLVMInt32Type()}, + {MachineType::INT64_TYPE, LLVMInt64Type()}, + {MachineType::UINT8_TYPE, LLVMInt8Type()}, + {MachineType::UINT16_TYPE, LLVMInt16Type()}, + {MachineType::UINT32_TYPE, LLVMInt32Type()}, + {MachineType::UINT64_TYPE, LLVMInt64Type()}, + {MachineType::FLOAT32_TYPE, LLVMFloatType()}, + {MachineType::FLOAT64_TYPE, LLVMDoubleType()}, + }; + return machineTypeMap[type]; +} } // namespace kungfu diff --git a/ecmascript/compiler/llvm_ir_builder.h b/ecmascript/compiler/llvm_ir_builder.h index ca6f1dd0850a2d3d987952b4526fe0dc7edb4ff9..7d479ba9a494ebfb2320764384b1d4a679b2623b 100644 --- a/ecmascript/compiler/llvm_ir_builder.h +++ b/ecmascript/compiler/llvm_ir_builder.h @@ -22,6 +22,7 @@ #include #include "ecmascript/compiler/circuit.h" +#include "ecmascript/compiler/stub_descriptor.h" #include "ecmascript/compiler/gate.h" #include "llvm-c/Core.h" #include "llvm-c/Types.h" @@ -78,11 +79,12 @@ public: } } ~BasicBlock() = default; + private: - std::vector predecessors_{}; - std::vector successors_{}; - int id_{-1}; - void *impl_{nullptr}; + std::vector predecessors_ {}; + std::vector successors_ {}; + int id_ {-1}; + void *impl_ {nullptr}; }; struct NotMergedPhiDesc { @@ -100,14 +102,52 @@ struct LLVMTFBuilderBasicBlockImpl { std::vector not_merged_phis; }; -class LLVMIRBuilder { +class LLVMStubModule { public: - LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit); - LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, LLVMModuleRef module, - LLVMValueRef function); + explicit LLVMStubModule(const char *name); + ~LLVMStubModule() = default; + + void Initialize(); + + LLVMModuleRef GetModule() const + { + return module_; + } + + LLVMTypeRef GetExternalFunctionType(int index) const + { + ASSERT(index < MAX_EXTERNAL_FUNCTION_COUNT); + return externalFuctionType_[index - EXTERNAL_FUNCTION_OFFSET]; + } + LLVMValueRef GetStubFunction(int index) + { + ASSERT(index < FAST_STUB_MAXCOUNT); + return stubFunctions_[index]; + } + +private: + LLVMValueRef GetLLVMFunctionByStubDescriptor(StubDescriptor *stubDescriptor); + LLVMTypeRef GetLLVMFunctionTypeStubDescriptor(StubDescriptor *stubDescriptor); + LLVMTypeRef ConvertLLVMTypeFromMachineType(MachineType type); + static constexpr uint32_t MAX_EXTERNAL_FUNCTION_COUNT = + kungfu::EXTERN_RUNTIME_STUB_MAXCOUNT - kungfu::EXTERNAL_RUNTIME_STUB_BEGIN - 1; + static constexpr uint32_t EXTERNAL_FUNCTION_OFFSET = kungfu::EXTERNAL_RUNTIME_STUB_BEGIN + 1; + std::array stubFunctions_ {nullptr}; + std::array externalFuctionType_ {nullptr}; + LLVMModuleRef module_; +}; + +class LLVMIRBuilder { +public: + explicit LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit); + explicit LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, + LLVMModuleRef module, LLVMValueRef function); + explicit LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, + LLVMStubModule *module, LLVMValueRef function); void Build(); ~LLVMIRBuilder() = default; + private: void VisitCall(AddrShift gate, const std::vector &inList); void VisitAlloca(AddrShift gate); @@ -142,7 +182,8 @@ private: void VisitPhi(AddrShift gate, const std::vector &srcGates, MachineRep rep); void VisitReturn(AddrShift gate, AddrShift popCount, const std::vector &operands) const; void VisitCastIntXToIntY(AddrShift gate, AddrShift e1, MachineRep rep) const; - void VisitCastIntToDouble(AddrShift gate, AddrShift e1) const; + void VisitCastInt32ToDouble(AddrShift gate, AddrShift e1) const; + void VisitCastInt64ToDouble(AddrShift gate, AddrShift e1) const; void VisitCastDoubleToInt(AddrShift gate, AddrShift e1) const; void VisitCastInt64ToPointer(AddrShift gate, AddrShift e1) const; @@ -174,6 +215,7 @@ private: BasicBlockMap bbIdMapBb_; std::vector phiRebuildWorklist_; + LLVMStubModule *stubModule_ {nullptr}; }; -#endif -} // namespace kungfu \ No newline at end of file +} // namespace kungfu +#endif // PANDA_RUNTIME_ECMASCRIPT_COMPILER_LLVM_IR_BUILDER_H \ No newline at end of file diff --git a/ecmascript/compiler/llvm_mcjit_compiler.cpp b/ecmascript/compiler/llvm_mcjit_engine.cpp similarity index 78% rename from ecmascript/compiler/llvm_mcjit_compiler.cpp rename to ecmascript/compiler/llvm_mcjit_engine.cpp index 2eaa1f75a3f9ba926ad1e1875f7520df2ad717c8..cacc2213e46cd3345765c89a03314e41012633f2 100644 --- a/ecmascript/compiler/llvm_mcjit_compiler.cpp +++ b/ecmascript/compiler/llvm_mcjit_engine.cpp @@ -13,12 +13,12 @@ * limitations under the License. */ -#include "ecmascript/compiler/llvm_mcjit_compiler.h" +#include "llvm_mcjit_engine.h" #include #include "llvm/IR/LegacyPassManager.h" #include "llvm/ADT/APInt.h" -#include "llvm/IR/Verifier.h" +#include "llvm/CodeGen/BuiltinGCs.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/IR/Argument.h" @@ -31,44 +31,42 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" -#include "llvm/CodeGen/BuiltinGCs.h" +#include "llvm/IR/Verifier.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/Transforms/Scalar.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Host.h" #include "llvm/Support/TargetSelect.h" #include "llvm-c/Analysis.h" #include "llvm-c/Core.h" +#include "llvm-c/Disassembler.h" +#include "llvm-c/DisassemblerTypes.h" #include "llvm-c/Target.h" #include "llvm-c/Transforms/PassManagerBuilder.h" #include "llvm-c/Transforms/Scalar.h" -#include "llvm/CodeGen/BuiltinGCs.h" - -#include "llvm/Transforms/Scalar.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Host.h" -#include "llvm-c/Disassembler.h" -#include "llvm-c/DisassemblerTypes.h" -#include "llvm/IRReader/IRReader.h" - namespace kungfu { -static uint8_t *RoundTripAllocateCodeSection(void *object, uintptr_t size, unsigned alignment, unsigned sectionID, - const char *sectionName) +static uint8_t *RoundTripAllocateCodeSection(void *object, uintptr_t size, [[maybe_unused]] unsigned alignment, + [[maybe_unused]] unsigned sectionID, const char *sectionName) { std::cout << "RoundTripAllocateCodeSection object " << object << " - " << std::endl; - struct CompilerState& state = *static_cast(object); + struct CodeInfo& state = *static_cast(object); uint8_t *addr = state.AllocaCodeSection(size, sectionName); std::cout << "RoundTripAllocateCodeSection addr:" << std::hex << reinterpret_cast(addr) << addr << " size:0x" << size << " +" << std::endl; return addr; } -static uint8_t *RoundTripAllocateDataSection(void *object, uintptr_t size, unsigned alignment, unsigned sectionID, - const char *sectionName, LLVMBool isReadOnly) +static uint8_t *RoundTripAllocateDataSection(void *object, uintptr_t size, [[maybe_unused]] unsigned alignment, + [[maybe_unused]] unsigned sectionID, const char *sectionName, + [[maybe_unused]] LLVMBool isReadOnly) { - struct CompilerState& state = *static_cast(object); + struct CodeInfo& state = *static_cast(object); return state.AllocaDataSection(size, sectionName); } -static LLVMBool RoundTripFinalizeMemory(void *object, char **errMsg) +static LLVMBool RoundTripFinalizeMemory(void *object, [[maybe_unused]] char **errMsg) { std::cout << "RoundTripFinalizeMemory object " << object << " - " << std::endl; return 0; @@ -77,18 +75,18 @@ static LLVMBool RoundTripFinalizeMemory(void *object, char **errMsg) static void RoundTripDestroy(void *object) { std::cout << "RoundTripDestroy object " << object << " - " << std::endl; - delete static_cast(object); + delete static_cast(object); } -void LLVMMCJITCompiler::UseRoundTripSectionMemoryManager() +void LLVMAssembler::UseRoundTripSectionMemoryManager() { auto sectionMemoryManager = std::make_unique(); options_.MCJMM = - LLVMCreateSimpleMCJITMemoryManager(&compilerState_, RoundTripAllocateCodeSection, + LLVMCreateSimpleMCJITMemoryManager(&codeInfo_, RoundTripAllocateCodeSection, RoundTripAllocateDataSection, RoundTripFinalizeMemory, RoundTripDestroy); } -bool LLVMMCJITCompiler::BuildMCJITEngine() +bool LLVMAssembler::BuildMCJITEngine() { std::cout << " BuildMCJITEngine - " << std::endl; LLVMBool ret = LLVMCreateMCJITCompilerForModule(&engine_, module_, &options_, sizeof(options_), &error_); @@ -101,7 +99,7 @@ bool LLVMMCJITCompiler::BuildMCJITEngine() return true; } -void LLVMMCJITCompiler::BuildAndRunPasses() const +void LLVMAssembler::BuildAndRunPasses() const { std::cout << "BuildAndRunPasses - " << std::endl; LLVMPassManagerRef pass = LLVMCreatePassManager(); @@ -114,14 +112,14 @@ void LLVMMCJITCompiler::BuildAndRunPasses() const std::cout << "BuildAndRunPasses + " << std::endl; } -LLVMMCJITCompiler::LLVMMCJITCompiler(LLVMModuleRef module): module_(module), engine_(nullptr), +LLVMAssembler::LLVMAssembler(LLVMModuleRef module): module_(module), engine_(nullptr), hostTriple_(""), error_(nullptr) { Initialize(); InitMember(); } -LLVMMCJITCompiler::~LLVMMCJITCompiler() +LLVMAssembler::~LLVMAssembler() { module_ = nullptr; engine_ = nullptr; @@ -129,7 +127,7 @@ LLVMMCJITCompiler::~LLVMMCJITCompiler() error_ = nullptr; } -void LLVMMCJITCompiler::Run() +void LLVMAssembler::Run() { UseRoundTripSectionMemoryManager(); if (!BuildMCJITEngine()) { @@ -138,7 +136,7 @@ void LLVMMCJITCompiler::Run() BuildAndRunPasses(); } -void LLVMMCJITCompiler::Initialize() +void LLVMAssembler::Initialize() { #if defined(PANDA_TARGET_AMD64) LLVMInitializeX86TargetInfo(); @@ -156,18 +154,19 @@ void LLVMMCJITCompiler::Initialize() options_.NoFramePointerElim = true; } -static const char *SymbolLookupCallback(void *disInfo, uint64_t referenceValue, uint64_t *referenceType, - uint64_t referencePC, const char **referenceName) +static const char *SymbolLookupCallback([[maybe_unused]] void *disInfo, [[maybe_unused]] uint64_t referenceValue, + uint64_t *referenceType, [[maybe_unused]]uint64_t referencePC, + [[maybe_unused]] const char **referenceName) { *referenceType = LLVMDisassembler_ReferenceType_InOut_None; return nullptr; } -void LLVMMCJITCompiler::Disassemble(std::map addr2name) const +void LLVMAssembler::Disassemble(std::map addr2name) const { LLVMDisasmContextRef dcr = LLVMCreateDisasm("x86_64-unknown-linux-gnu", nullptr, 0, nullptr, SymbolLookupCallback); std::cout << "========================================================================" << std::endl; - for (auto it : compilerState_.GetCodeInfo()) { + for (auto it : codeInfo_.GetCodeInfo()) { uint8_t *byteSp; uintptr_t numBytes; byteSp = it.first; @@ -190,7 +189,7 @@ void LLVMMCJITCompiler::Disassemble(std::map addr2name) c if (addr2name.find(addr) != addr2name.end()) { std::cout << addr2name[addr].c_str() << ":" << std::endl; } - fprintf(stderr, "%08x: %08x %s\n", pc, *reinterpret_cast(byteSp), outString); + (void)fprintf(stderr, "%08x: %08x %s\n", pc, *reinterpret_cast(byteSp), outString); pc += InstSize; byteSp += InstSize; numBytes -= InstSize; @@ -199,7 +198,7 @@ void LLVMMCJITCompiler::Disassemble(std::map addr2name) c std::cout << "========================================================================" << std::endl; } -void LLVMMCJITCompiler::InitMember() +void LLVMAssembler::InitMember() { if (module_ == nullptr) { module_ = LLVMModuleCreateWithName("simple_module"); diff --git a/ecmascript/compiler/llvm_mcjit_compiler.h b/ecmascript/compiler/llvm_mcjit_engine.h similarity index 73% rename from ecmascript/compiler/llvm_mcjit_compiler.h rename to ecmascript/compiler/llvm_mcjit_engine.h index b8c38782c634e951735b0c40827b4c5e89e74bf7..3eaafb206b59a784256b55d05f8687304a4e758c 100644 --- a/ecmascript/compiler/llvm_mcjit_compiler.h +++ b/ecmascript/compiler/llvm_mcjit_engine.h @@ -13,8 +13,8 @@ * limitations under the License. */ -#ifndef ECMASCRIPT_COMPILER_LLVM_MCJINT_COMPILER_H -#define ECMASCRIPT_COMPILER_LLVM_MCJINT_COMPILER_H +#ifndef ECMASCRIPT_COMPILER_LLVM_MCJINT_ENGINE_H +#define ECMASCRIPT_COMPILER_LLVM_MCJINT_ENGINE_H #include #include @@ -34,42 +34,43 @@ #include "llvm-c/Transforms/Scalar.h" namespace kungfu { -using ByteBuffer = std::vector; -using BufferList = std::list; -using StringList = std::list; -struct CompilerState { - CompilerState(): machineCode(nullptr), codeBufferPos(0), stackMapsSection_(nullptr) +struct CodeInfo { + using ByteBuffer = std::vector; + using BufferList = std::list; + using StringList = std::list; + CodeInfo() : machineCode(nullptr), codeBufferPos(0), stackMapsSection_(nullptr) { Reset(); static constexpr int prot = PROT_READ | PROT_WRITE | PROT_EXEC; // NOLINT(hicpp-signed-bitwise) static constexpr int flags = MAP_ANONYMOUS | MAP_SHARED; // NOLINT(hicpp-signed-bitwise) machineCode = static_cast(mmap(nullptr, MAX_MACHINE_CODE_SIZE, prot, flags, -1, 0)); + std::cerr << std::hex << "machineCode : " << reinterpret_cast(machineCode) << std::endl; } - ~CompilerState() + ~CodeInfo() { Reset(); munmap(machineCode, MAX_MACHINE_CODE_SIZE); } - uint8_t* AllocaCodeSection(uintptr_t size, const char* sectionName) + uint8_t *AllocaCodeSection(uintptr_t size, const char *sectionName) { uint8_t *addr = nullptr; if (codeBufferPos + size > MAX_MACHINE_CODE_SIZE) { - std::cerr << std::hex << "AllocaCodeSection failed alloc codeBufferPos:" << codeBufferPos << " size:" - << size << " larger MAX_MACHINE_CODE_SIZE:" << MAX_MACHINE_CODE_SIZE << std::endl; + std::cerr << std::hex << "AllocaCodeSection failed alloc codeBufferPos:" << codeBufferPos + << " size:" << size << " larger MAX_MACHINE_CODE_SIZE:" << MAX_MACHINE_CODE_SIZE << std::endl; return nullptr; } std::cout << "AllocaCodeSection size:" << size << std::endl; std::vector codeBuffer(machineCode[codeBufferPos], size); std::cout << " codeBuffer size: " << codeBuffer.size() << std::endl; - codeBufferPos += size; codeSectionNames_.push_back(sectionName); addr = machineCode + codeBufferPos; std::cout << "AllocaCodeSection addr:" << std::hex << reinterpret_cast(addr) << std::endl; codeInfo_.push_back({addr, size}); + codeBufferPos += size; return addr; } - uint8_t* AllocaDataSection(uintptr_t size, const char* sectionName) + uint8_t *AllocaDataSection(uintptr_t size, const char *sectionName) { uint8_t *addr = nullptr; dataSectionList_.push_back(std::vector()); @@ -92,30 +93,42 @@ struct CompilerState { codeSectionNames_.clear(); codeBufferPos = 0; } - uint8_t* GetStackMapsSection() const + + uint8_t *GetStackMapsSection() const { return stackMapsSection_; } std::vector> GetCodeInfo() const { - return codeInfo_; + return codeInfo_; } + + int GetCodeSize() const + { + return codeBufferPos; + } + + uint8_t *GetCodeBuff() const + { + return machineCode; + } + private: BufferList dataSectionList_ {}; StringList dataSectionNames_ {}; StringList codeSectionNames_ {}; uint8_t *machineCode; - const size_t MAX_MACHINE_CODE_SIZE = (1 << 20); // 1M + const size_t MAX_MACHINE_CODE_SIZE = (1 << 20); // 1M int codeBufferPos = 0; /* for asssembler */ std::vector> codeInfo_ {}; /* stack map */ - uint8_t* stackMapsSection_ {nullptr}; + uint8_t *stackMapsSection_ {nullptr}; }; -class LLVMMCJITCompiler { +class LLVMAssembler { public: - explicit LLVMMCJITCompiler(LLVMModuleRef module); - virtual ~LLVMMCJITCompiler(); + explicit LLVMAssembler(LLVMModuleRef module); + virtual ~LLVMAssembler(); void Run(); const LLVMExecutionEngineRef &GetEngine() { @@ -124,7 +137,16 @@ public: void Disassemble(std::map addr2name = std::map()) const; uint8_t *GetStackMapsSection() const { - return compilerState_.GetStackMapsSection(); + return codeInfo_.GetStackMapsSection(); + } + + int GetCodeSize() const + { + return codeInfo_.GetCodeSize(); + } + uint8_t *GetCodeBuffer() const + { + return codeInfo_.GetCodeBuff(); } private: @@ -140,8 +162,7 @@ private: LLVMExecutionEngineRef engine_; std::string hostTriple_; char *error_; - struct CompilerState compilerState_; + struct CodeInfo codeInfo_; }; - -#endif } // namespace kungfu +#endif // ECMASCRIPT_COMPILER_LLVM_MCJINT_ENGINE_H diff --git a/ecmascript/compiler/scheduler.h b/ecmascript/compiler/scheduler.h index edfa7be124fa35e539534324cd50d73a57ed9d01..69f569b91ba79b13865aef82ff6674348e46b937 100644 --- a/ecmascript/compiler/scheduler.h +++ b/ecmascript/compiler/scheduler.h @@ -25,18 +25,19 @@ #include "ecmascript/compiler/circuit.h" namespace kungfu { +using ControlFlowGraph = std::vector>; class Scheduler { public: static std::tuple, std::unordered_map, std::vector> CalculateDominatorTree(const Circuit *circuit); - static std::vector> Run(const Circuit *circuit); + static ControlFlowGraph Run(const Circuit *circuit); static std::optional> CalculateSchedulingUpperBound(const Circuit *circuit, const std::unordered_map &bbGatesAddrToIdx, const std::function &isAncestor, const std::vector &schedulableGatesList); static std::optional> CalculateSchedulingLowerBound(const Circuit *circuit, const std::unordered_map &bbGatesAddrToIdx, const std::function &lowestCommonAncestor, std::vector *order = nullptr); - static void Print(const std::vector> *cfg, const Circuit *circuit); + static void Print(const ControlFlowGraph *cfg, const Circuit *circuit); }; }; // namespace kungfu diff --git a/ecmascript/compiler/stub_optimizer.cpp b/ecmascript/compiler/stub.cpp similarity index 70% rename from ecmascript/compiler/stub_optimizer.cpp rename to ecmascript/compiler/stub.cpp index 25e344e793695be399d82c8ccfeb843461163276..a3b0d945136f500a4283e59dc4c6249fafd69d52 100644 --- a/ecmascript/compiler/stub_optimizer.cpp +++ b/ecmascript/compiler/stub.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "ecmascript/compiler/stub_optimizer.h" +#include "ecmascript/compiler/stub.h" #include "ecmascript/compiler/llvm_ir_builder.h" #include "ecmascript/js_object.h" @@ -21,17 +21,17 @@ #include "libpandabase/macros.h" namespace kungfu { -using StubOPtimizerLabelImplement = StubOptimizerLabel::StubOptimizerLabelImplement; +using LabelImpl = Stub::Label::LabelImpl; -StubOptimizerLabel::StubOptimizerLabel(Environment *env) +Stub::Label::Label(Environment *env) { - impl_ = env->NewStubOptimizerLabel(env); + impl_ = env->NewLabel(env); } -AddrShift StubVariable::AddPhiOperand(AddrShift val) +AddrShift Stub::Variable::AddPhiOperand(AddrShift val) { ASSERT(IsSelector(val)); - StubOptimizerLabel label = env_->GetLabelFromSelector(val); + Label label = env_->GetLabelFromSelector(val); size_t idx = 0; for (auto pred : label.GetPredecessors()) { idx++; @@ -41,15 +41,15 @@ AddrShift StubVariable::AddPhiOperand(AddrShift val) return TryRemoveTrivialPhi(val); } -AddrShift StubVariable::AddOperandToSelector(AddrShift val, size_t idx, AddrShift in) +AddrShift Stub::Variable::AddOperandToSelector(AddrShift val, size_t idx, AddrShift in) { - env_->GetCircuit().NewIn(val, idx, in); + env_->GetCircuit()->NewIn(val, idx, in); return val; } -AddrShift StubVariable::TryRemoveTrivialPhi(AddrShift phiVal) +AddrShift Stub::Variable::TryRemoveTrivialPhi(AddrShift phiVal) { - Gate *phi = env_->GetCircuit().LoadGatePtr(phiVal); + Gate *phi = env_->GetCircuit()->LoadGatePtr(phiVal); Gate *same = nullptr; for (size_t i = 1; i < phi->GetNumIns(); ++i) { In *phiIn = phi->GetIn(i); @@ -64,7 +64,7 @@ AddrShift StubVariable::TryRemoveTrivialPhi(AddrShift phiVal) } if (same == nullptr) { // the phi is unreachable or in the start block - same = env_->GetCircuit().LoadGatePtr(env_->GetCircuitBuilder().UndefineConstant()); + same = env_->GetCircuit()->LoadGatePtr(env_->GetCircuitBuilder().UndefineConstant()); } // remove the trivial phi @@ -91,14 +91,14 @@ AddrShift StubVariable::TryRemoveTrivialPhi(AddrShift phiVal) // try to recursiveby remove all phi users, which might have vecome trivial for (auto out : outs) { if (IsSelector(out->GetGate())) { - auto out_addr_shift = env_->GetCircuit().SaveGatePtr(out->GetGate()); + auto out_addr_shift = env_->GetCircuit()->SaveGatePtr(out->GetGate()); TryRemoveTrivialPhi(out_addr_shift); } } - return env_->GetCircuit().SaveGatePtr(same); + return env_->GetCircuit()->SaveGatePtr(same); } -void StubVariable::RerouteOuts(const std::vector &outs, Gate *newGate) +void Stub::Variable::RerouteOuts(const std::vector &outs, Gate *newGate) { // reroute all outs to new node for (auto out : outs) { @@ -107,7 +107,7 @@ void StubVariable::RerouteOuts(const std::vector &outs, Gate *newGate) } } -void StubOPtimizerLabelImplement::Seal() +void LabelImpl::Seal() { for (auto &[variable, gate] : incompletePhis_) { variable->AddPhiOperand(gate); @@ -115,12 +115,12 @@ void StubOPtimizerLabelImplement::Seal() isSealed_ = true; } -void StubOPtimizerLabelImplement::WriteVariable(StubVariable *var, AddrShift value) +void LabelImpl::WriteVariable(Variable *var, AddrShift value) { valueMap_[var] = value; } -AddrShift StubOPtimizerLabelImplement::ReadVariable(StubVariable *var) +AddrShift LabelImpl::ReadVariable(Variable *var) { if (valueMap_.find(var) != valueMap_.end()) { return valueMap_.at(var); @@ -128,7 +128,7 @@ AddrShift StubOPtimizerLabelImplement::ReadVariable(StubVariable *var) return ReadVariableRecursive(var); } -AddrShift StubOPtimizerLabelImplement::ReadVariableRecursive(StubVariable *var) +AddrShift LabelImpl::ReadVariableRecursive(Variable *var) { AddrShift val; OpCode opcode = CircuitBuilder::GetSelectOpCodeFromMachineType(var->Type()); @@ -137,13 +137,13 @@ AddrShift StubOPtimizerLabelImplement::ReadVariableRecursive(StubVariable *var) int valueCounts = static_cast(this->predecessors.size()) + 1; val = env_->GetCircuitBuilder().NewSelectorGate(opcode, predeControl_, valueCounts); - env_->AddSelectorToLabel(val, StubOptimizerLabel(this)); + env_->AddSelectorToLabel(val, Label(this)); incompletePhis_[var] = val; } else if (predecessors.size() == 1) { val = predecessors[0]->ReadVariable(var); } else { val = env_->GetCircuitBuilder().NewSelectorGate(opcode, predeControl_, this->predecessors.size()); - env_->AddSelectorToLabel(val, StubOptimizerLabel(this)); + env_->AddSelectorToLabel(val, Label(this)); WriteVariable(var, val); val = var->AddPhiOperand(val); } @@ -151,7 +151,7 @@ AddrShift StubOPtimizerLabelImplement::ReadVariableRecursive(StubVariable *var) return val; } -void StubOPtimizerLabelImplement::Bind() +void LabelImpl::Bind() { ASSERT(!predecessors.empty()); if (IsNeedSeal()) { @@ -160,7 +160,7 @@ void StubOPtimizerLabelImplement::Bind() } } -void StubOPtimizerLabelImplement::MergeAllControl() +void LabelImpl::MergeAllControl() { if (predecessors.size() < 2) { // 2 : Loop Head only support two predecessors return; @@ -169,7 +169,7 @@ void StubOPtimizerLabelImplement::MergeAllControl() if (IsLoopHead()) { ASSERT(predecessors.size() == 2); // 2 : Loop Head only support two predecessors ASSERT(otherPredeControls_.size() == 1); - env_->GetCircuit().NewIn(predeControl_, 1, otherPredeControls_[0]); + env_->GetCircuit()->NewIn(predeControl_, 1, otherPredeControls_[0]); return; } @@ -188,139 +188,117 @@ void StubOPtimizerLabelImplement::MergeAllControl() control_ = merge; } -void StubOPtimizerLabelImplement::AppendPredecessor(StubOptimizerLabelImplement *predecessor) +void LabelImpl::AppendPredecessor(LabelImpl *predecessor) { if (predecessor != nullptr) { predecessors.push_back(predecessor); } } -bool StubOPtimizerLabelImplement::IsNeedSeal() const +bool LabelImpl::IsNeedSeal() const { - auto control = env_->GetCircuit().LoadGatePtr(predeControl_); + auto control = env_->GetCircuit()->LoadGatePtr(predeControl_); auto numsInList = control->GetOpCode().GetOpCodeNumInsArray(control->GetBitField()); return predecessors.size() >= numsInList[0]; } -bool StubOPtimizerLabelImplement::IsLoopHead() const +bool LabelImpl::IsLoopHead() const { - return env_->GetCircuit().IsLoopHead(predeControl_); + return env_->GetCircuit()->IsLoopHead(predeControl_); } -Environment::Environment(const char *name, size_t arguments) - : builder_(&circuit_), arguments_(arguments), method_name_(name) +Stub::Environment::Environment(size_t arguments, Circuit *circuit) + : circuit_(circuit), builder_(circuit), arguments_(arguments) { for (size_t i = 0; i < arguments; i++) { arguments_[i] = builder_.NewArguments(i); } - entry_ = StubOptimizerLabel(NewStubOptimizerLabel(this, Circuit::GetCircuitRoot(OpCode(OpCode::STATE_ENTRY)))); + entry_ = Label(NewLabel(this, Circuit::GetCircuitRoot(OpCode(OpCode::STATE_ENTRY)))); currentLabel_ = &entry_; currentLabel_->Seal(); } -Environment::Environment(Environment const &env) - : circuit_(env.circuit_), builder_(&circuit_), arguments_(env.arguments_), method_name_(env.method_name_) -{ - entry_ = StubOptimizerLabel(NewStubOptimizerLabel(this, Circuit::GetCircuitRoot(OpCode(OpCode::STATE_ENTRY)))); - currentLabel_ = &entry_; - currentLabel_->Seal(); -} - -Environment &Environment::operator=(const Environment &env) -{ - if (&env != this) { - this->circuit_ = env.circuit_; - this->arguments_ = env.arguments_; - this->method_name_ = env.method_name_; - - entry_ = StubOptimizerLabel(NewStubOptimizerLabel(this, Circuit::GetCircuitRoot(OpCode(OpCode::STATE_ENTRY)))); - currentLabel_ = &entry_; - currentLabel_->Seal(); - } - return *this; -} - -Environment::~Environment() +Stub::Environment::~Environment() { for (auto label : rawlabels_) { delete label; } } -void StubOptimizer::Jump(Label *label) +void Stub::Jump(Label *label) { ASSERT(label); - auto currentLabel = env_->GetCurrentLabel(); + auto currentLabel = env_.GetCurrentLabel(); auto currentControl = currentLabel->GetControl(); - auto jump = env_->GetCircuitBuilder().Goto(currentControl); + auto jump = env_.GetCircuitBuilder().Goto(currentControl); currentLabel->SetControl(jump); label->AppendPredecessor(currentLabel); label->MergeControl(currentLabel->GetControl()); - env_->SetCurrentLabel(nullptr); + env_.SetCurrentLabel(nullptr); } -void StubOptimizer::Branch(AddrShift condition, Label *trueLabel, Label *falseLabel) +void Stub::Branch(AddrShift condition, Label *trueLabel, Label *falseLabel) { - auto currentLabel = env_->GetCurrentLabel(); + auto currentLabel = env_.GetCurrentLabel(); auto currentControl = currentLabel->GetControl(); - AddrShift ifBranch = env_->GetCircuitBuilder().Branch(currentControl, condition); + AddrShift ifBranch = env_.GetCircuitBuilder().Branch(currentControl, condition); currentLabel->SetControl(ifBranch); - AddrShift ifTrue = env_->GetCircuitBuilder().NewIfTrue(ifBranch); - trueLabel->AppendPredecessor(env_->GetCurrentLabel()); + AddrShift ifTrue = env_.GetCircuitBuilder().NewIfTrue(ifBranch); + trueLabel->AppendPredecessor(env_.GetCurrentLabel()); trueLabel->MergeControl(ifTrue); - AddrShift ifFalse = env_->GetCircuitBuilder().NewIfFalse(ifBranch); - falseLabel->AppendPredecessor(env_->GetCurrentLabel()); + AddrShift ifFalse = env_.GetCircuitBuilder().NewIfFalse(ifBranch); + falseLabel->AppendPredecessor(env_.GetCurrentLabel()); falseLabel->MergeControl(ifFalse); - env_->SetCurrentLabel(nullptr); + env_.SetCurrentLabel(nullptr); } -void StubOptimizer::Switch(AddrShift index, Label *defaultLabel, int32_t *keysValue, Label *keysLabel, int numberOfKeys) +void Stub::Switch(AddrShift index, Label *defaultLabel, int32_t *keysValue, Label *keysLabel, int numberOfKeys) { - auto currentLabel = env_->GetCurrentLabel(); + auto currentLabel = env_.GetCurrentLabel(); auto currentControl = currentLabel->GetControl(); - AddrShift switchBranch = env_->GetCircuitBuilder().SwitchBranch(currentControl, index, numberOfKeys); + AddrShift switchBranch = env_.GetCircuitBuilder().SwitchBranch(currentControl, index, numberOfKeys); currentLabel->SetControl(switchBranch); for (int i = 0; i < numberOfKeys; i++) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - AddrShift switchCase = env_->GetCircuitBuilder().NewSwitchCase(switchBranch, keysValue[i]); + AddrShift switchCase = env_.GetCircuitBuilder().NewSwitchCase(switchBranch, keysValue[i]); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) keysLabel[i].AppendPredecessor(currentLabel); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) keysLabel[i].MergeControl(switchCase); } - AddrShift defaultCase = env_->GetCircuitBuilder().NewDefaultCase(switchBranch); + AddrShift defaultCase = env_.GetCircuitBuilder().NewDefaultCase(switchBranch); defaultLabel->AppendPredecessor(currentLabel); defaultLabel->MergeControl(defaultCase); - env_->SetCurrentLabel(nullptr); + env_.SetCurrentLabel(nullptr); } -void StubOptimizer::LoopBegin(Label *loopHead) +void Stub::LoopBegin(Label *loopHead) { ASSERT(loopHead); - auto loopControl = env_->GetCircuitBuilder().LoopBegin(loopHead->GetControl()); + auto loopControl = env_.GetCircuitBuilder().LoopBegin(loopHead->GetControl()); loopHead->SetControl(loopControl); loopHead->SetPreControl(loopControl); loopHead->Bind(); - env_->SetCurrentLabel(loopHead); + env_.SetCurrentLabel(loopHead); } -void StubOptimizer::LoopEnd(Label *loopHead) +void Stub::LoopEnd(Label *loopHead) { ASSERT(loopHead); - auto currentLabel = env_->GetCurrentLabel(); + auto currentLabel = env_.GetCurrentLabel(); auto currentControl = currentLabel->GetControl(); - auto loopend = env_->GetCircuitBuilder().LoopEnd(currentControl); + auto loopend = env_.GetCircuitBuilder().LoopEnd(currentControl); currentLabel->SetControl(loopend); loopHead->AppendPredecessor(currentLabel); loopHead->MergeControl(loopend); loopHead->Seal(); loopHead->MergeAllControl(); - env_->SetCurrentLabel(nullptr); + env_.SetCurrentLabel(nullptr); } -AddrShift StubOptimizer::FixLoadType(AddrShift x) +AddrShift Stub::FixLoadType(AddrShift x) { if (PtrValueCode() == ValueCode::INT64) { return SExtInt32ToInt64(x); @@ -331,7 +309,7 @@ AddrShift StubOptimizer::FixLoadType(AddrShift x) UNREACHABLE(); } -AddrShift StubOptimizer::LoadFromObject(MachineType type, AddrShift object, AddrShift offset) +AddrShift Stub::LoadFromObject(MachineType type, AddrShift object, AddrShift offset) { AddrShift elementsOffset = GetInteger32Constant(panda::ecmascript::JSObject::ELEMENTS_OFFSET); if (PtrValueCode() == ValueCode::INT64) { @@ -349,11 +327,13 @@ AddrShift StubOptimizer::LoadFromObject(MachineType type, AddrShift object, Addr return Load(type, ChangeInt64ToPointer(elements), dataOffset); } -AddrShift StubOptimizer::FindElementFromNumberDictionary(AddrShift thread, AddrShift elements, AddrShift key, - Label *next) +AddrShift Stub::FindElementFromNumberDictionary(AddrShift thread, AddrShift elements, AddrShift key) { auto env = GetEnvironment(); + Label subentry(env); + [[maybe_unused]] SubCircuitScope subCircuit(env, &subentry); DEFVARIABLE(result, INT32_TYPE, GetInteger32Constant(-1)); + Label exit(env); AddrShift capcityoffset = PtrMul(GetPtrConstant(panda::ecmascript::JSTaggedValue::TaggedTypeSize()), GetPtrConstant(panda::ecmascript::TaggedHashTable::SIZE_INDEX)); @@ -363,7 +343,7 @@ AddrShift StubOptimizer::FindElementFromNumberDictionary(AddrShift thread, AddrS AddrShift pKey = Alloca(static_cast(MachineRep::K_WORD32)); AddrShift keyStore = Store(INT32_TYPE, pKey, GetPtrConstant(0), TaggedCastToInt32(key)); - StubInterfaceDescriptor *getHash32Descriptor = GET_STUBDESCRIPTOR(GetHash32); + StubDescriptor *getHash32Descriptor = GET_STUBDESCRIPTOR(GetHash32); AddrShift len = GetInteger32Constant(sizeof(int) / sizeof(uint8_t)); AddrShift hash = CallRuntime(getHash32Descriptor, thread, GetWord64Constant(FAST_STUB_ID(GetHash32)), keyStore, {pKey, len}); @@ -373,8 +353,7 @@ AddrShift StubOptimizer::FindElementFromNumberDictionary(AddrShift thread, AddrS Label afterLoop(env); Jump(&loopHead); LoopBegin(&loopHead); - Label afterGetKey(env); - AddrShift element = GetKeyFromNumberDictionary(elements, *entry, &afterGetKey); + AddrShift element = GetKeyFromNumberDictionary(elements, *entry); Label isHole(env); Label notHole(env); Branch(TaggedIsHole(element), &isHole, ¬Hole); @@ -386,28 +365,30 @@ AddrShift StubOptimizer::FindElementFromNumberDictionary(AddrShift thread, AddrS Branch(TaggedIsUndefined(element), &isUndefined, ¬Undefined); Bind(&isUndefined); result = GetInteger32Constant(-1); - Jump(next); + Jump(&exit); Bind(¬Undefined); - Label afterIsMatch(env); Label isMatch(env); Label notMatch(env); - Branch(IsMatchInNumberDictionary(key, element, &afterIsMatch), &isMatch, ¬Match); + Branch(IsMatchInNumberDictionary(key, element), &isMatch, ¬Match); Bind(&isMatch); result = *entry; - Jump(next); + Jump(&exit); Bind(¬Match); Jump(&loopEnd); Bind(&loopEnd); entry = Word32And(Int32Add(*entry, *count), Int32Sub(capacity, GetInteger32Constant(1))); count = Int32Add(*count, GetInteger32Constant(1)); LoopEnd(&loopHead); - Bind(next); + Bind(&exit); return *result; } -AddrShift StubOptimizer::IsMatchInNumberDictionary(AddrShift key, AddrShift other, Label *next) +AddrShift Stub::IsMatchInNumberDictionary(AddrShift key, AddrShift other) { auto env = GetEnvironment(); + Label entry(env); + [[maybe_unused]] SubCircuitScope subCircuit(env, &entry); + Label exit(env); DEFVARIABLE(result, BOOL_TYPE, FalseConstant()); Label isHole(env); Label notHole(env); @@ -415,11 +396,11 @@ AddrShift StubOptimizer::IsMatchInNumberDictionary(AddrShift key, AddrShift othe Label notUndefined(env); Branch(TaggedIsHole(key), &isHole, ¬Hole); Bind(&isHole); - Jump(next); + Jump(&exit); Bind(¬Hole); Branch(TaggedIsUndefined(key), &isUndefined, ¬Undefined); Bind(&isUndefined); - Jump(next); + Jump(&exit); Bind(¬Undefined); Label keyIsInt(env); Label keyNotInt(env); @@ -430,18 +411,21 @@ AddrShift StubOptimizer::IsMatchInNumberDictionary(AddrShift key, AddrShift othe Branch(TaggedIsInt(other), &otherIsInt, &otherNotInt); Bind(&otherIsInt); result = Word32Equal(TaggedCastToInt32(key), TaggedCastToInt32(other)); - Jump(next); + Jump(&exit); Bind(&otherNotInt); - Jump(next); + Jump(&exit); Bind(&keyNotInt); - Jump(next); - Bind(next); + Jump(&exit); + Bind(&exit); return *result; } -AddrShift StubOptimizer::GetKeyFromNumberDictionary(AddrShift elements, AddrShift entry, Label *next) +AddrShift Stub::GetKeyFromNumberDictionary(AddrShift elements, AddrShift entry) { auto env = GetEnvironment(); + Label subentry(env); + [[maybe_unused]] SubCircuitScope subCircuit(env, &subentry); + Label exit(env); DEFVARIABLE(result, TAGGED_TYPE, GetUndefinedConstant()); Label ltZero(env); Label notLtZero(env); @@ -453,29 +437,32 @@ AddrShift StubOptimizer::GetKeyFromNumberDictionary(AddrShift elements, AddrShif Int32Mul(entry, GetInteger32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE))); Branch(Int32LessThan(arrayIndex, GetInteger32Constant(0)), <Zero, ¬LtZero); Bind(<Zero); - Jump(next); + Jump(&exit); Bind(¬LtZero); Branch(Int32GreaterThan(arrayIndex, dictionaryLength), >Length, ¬GtLength); Bind(>Length); - Jump(next); + Jump(&exit); Bind(¬GtLength); result = GetValueFromTaggedArray(elements, arrayIndex); - Jump(next); - Bind(next); + Jump(&exit); + Bind(&exit); return *result; } -void StubOptimizer::ThrowTypeAndReturn(AddrShift thread, int messageId, AddrShift val) +void Stub::ThrowTypeAndReturn(AddrShift thread, int messageId, AddrShift val) { - StubInterfaceDescriptor *throwTypeError = GET_STUBDESCRIPTOR(ThrowTypeError); + StubDescriptor *throwTypeError = GET_STUBDESCRIPTOR(ThrowTypeError); AddrShift taggedId = IntBuildTagged(GetInteger32Constant(messageId)); CallStub(throwTypeError, GetWord64Constant(FAST_STUB_ID(ThrowTypeError)), {thread, taggedId}); Return(val); } -AddrShift StubOptimizer::TaggedToRepresentation(AddrShift value, Label *next) +AddrShift Stub::TaggedToRepresentation(AddrShift value) { auto env = GetEnvironment(); + Label entry(env); + [[maybe_unused]] SubCircuitScope subCircuit(env, &entry); + Label exit(env); DEFVARIABLE(resultRep, INT64_TYPE, GetWord64Constant(static_cast(panda::ecmascript::Representation::OBJECT))); Label isInt(env); @@ -485,7 +472,7 @@ AddrShift StubOptimizer::TaggedToRepresentation(AddrShift value, Label *next) Bind(&isInt); { resultRep = GetWord64Constant(static_cast(panda::ecmascript::Representation::INT)); - Jump(next); + Jump(&exit); } Bind(¬Int); { @@ -495,32 +482,34 @@ AddrShift StubOptimizer::TaggedToRepresentation(AddrShift value, Label *next) Bind(&isDouble); { resultRep = GetWord64Constant(static_cast(panda::ecmascript::Representation::DOUBLE)); - Jump(next); + Jump(&exit); } Bind(¬Double); { resultRep = GetWord64Constant(static_cast(panda::ecmascript::Representation::OBJECT)); - Jump(next); + Jump(&exit); } } - Bind(next); + Bind(&exit); return *resultRep; } -AddrShift StubOptimizer::UpdateRepresention(AddrShift oldRep, AddrShift value, Label *next) +AddrShift Stub::UpdateRepresention(AddrShift oldRep, AddrShift value) { auto env = GetEnvironment(); + Label entry(env); + [[maybe_unused]] SubCircuitScope subCircuit(env, &entry); + Label exit(env); DEFVARIABLE(resultRep, INT64_TYPE, oldRep); Label isMixedRep(env); Label notMiexedRep(env); Branch(Word64Equal(oldRep, GetWord64Constant(static_cast(panda::ecmascript::Representation::MIXED))), &isMixedRep, ¬MiexedRep); Bind(&isMixedRep); - Jump(next); + Jump(&exit); Bind(¬MiexedRep); { - Label newRepLabel(env); - AddrShift newRep = TaggedToRepresentation(value, &newRepLabel); + AddrShift newRep = TaggedToRepresentation(value); Label isNoneRep(env); Label notNoneRep(env); Branch(Word64Equal(oldRep, GetWord64Constant(static_cast(panda::ecmascript::Representation::NONE))), @@ -528,7 +517,7 @@ AddrShift StubOptimizer::UpdateRepresention(AddrShift oldRep, AddrShift value, L Bind(&isNoneRep); { resultRep = newRep; - Jump(next); + Jump(&exit); } Bind(¬NoneRep); { @@ -538,7 +527,7 @@ AddrShift StubOptimizer::UpdateRepresention(AddrShift oldRep, AddrShift value, L Bind(&isEqaulNewRep); { resultRep = newRep; - Jump(next); + Jump(&exit); } Bind(¬EqaualNewRep); { @@ -572,36 +561,36 @@ AddrShift StubOptimizer::UpdateRepresention(AddrShift oldRep, AddrShift value, L Label isObjectNewRep(env); Label notObjectNewRep(env); Branch(Word64NotEqual(newRep, GetWord64Constant( - static_cast(panda::ecmascript::Representation::OBJECT))), - ¬ObjectNewRep, &isObjectNewRep); + static_cast(panda::ecmascript::Representation::OBJECT))), + ¬ObjectNewRep, &isObjectNewRep); Bind(¬ObjectNewRep); { resultRep = GetWord64Constant(static_cast(panda::ecmascript::Representation::NUMBER)); - Jump(next); + Jump(&exit); } Bind(&isObjectNewRep); { resultRep = GetWord64Constant(static_cast(panda::ecmascript::Representation::MIXED)); - Jump(next); + Jump(&exit); } } Bind(&objectLabel); { resultRep = GetWord64Constant(static_cast(panda::ecmascript::Representation::MIXED)); - Jump(next); + Jump(&exit); } Bind(&defaultLabel); - Jump(next); + Jump(&exit); } } } - Bind(next); + Bind(&exit); return *resultRep; } -void StubOptimizer::UpdateAndStoreRepresention(AddrShift hclass, AddrShift value, Label *next) +void Stub::UpdateAndStoreRepresention(AddrShift hclass, AddrShift value) { - AddrShift newRep = UpdateRepresention(GetElementRepresentation(hclass), value, next); + AddrShift newRep = UpdateRepresention(GetElementRepresentation(hclass), value); SetElementRepresentation(hclass, newRep); } } // namespace kungfu \ No newline at end of file diff --git a/ecmascript/compiler/stub_optimizer.h b/ecmascript/compiler/stub.h similarity index 52% rename from ecmascript/compiler/stub_optimizer.h rename to ecmascript/compiler/stub.h index cedc09c784a7c3843610fcee56d315260158b4a4..93bf7bac0be89dca53ebb8d20e80f8491959c9b2 100644 --- a/ecmascript/compiler/stub_optimizer.h +++ b/ecmascript/compiler/stub.h @@ -13,320 +13,351 @@ * limitations under the License. */ -#ifndef ECMASCRIPT_COMPILER_STUBOPTIMIZER_H -#define ECMASCRIPT_COMPILER_STUBOPTIMIZER_H +#ifndef ECMASCRIPT_COMPILER_Stub_H +#define ECMASCRIPT_COMPILER_Stub_H #include "ecmascript/accessor_data.h" #include "ecmascript/compiler/circuit.h" #include "ecmascript/compiler/circuit_builder.h" #include "ecmascript/compiler/gate.h" -#include "ecmascript/compiler/stub_interface.h" +#include "ecmascript/compiler/stub_descriptor.h" #include "ecmascript/js_object.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/tagged_dictionary.h" namespace kungfu { -class CompilerOptions; -class Environment; -class StubOptimizerLabel; -class StubVariable; -class CallerDescriptor; // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define DEFVARIABLE(varname, type, val) StubVariable varname(GetEnvironment(), type, NextVariableId(), val) +#define DEFVARIABLE(varname, type, val) Stub::Variable varname(GetEnvironment(), type, NextVariableId(), val) -class StubOptimizerLabel { +class Stub { public: - class StubOptimizerLabelImplement { + class Environment; + class Label; + class Variable; + + class Label { public: - StubOptimizerLabelImplement(Environment *env, AddrShift control) - : env_(env), control_(control), predeControl_(-1), isSealed_(false) + class LabelImpl { + public: + LabelImpl(Environment *env, AddrShift control) + : env_(env), control_(control), predeControl_(-1), isSealed_(false) + { + } + + ~LabelImpl() = default; + + NO_MOVE_SEMANTIC(LabelImpl); + NO_COPY_SEMANTIC(LabelImpl); + void Seal(); + void WriteVariable(Variable *var, AddrShift value); + AddrShift ReadVariable(Variable *var); + void Bind(); + void MergeAllControl(); + void AppendPredecessor(LabelImpl *predecessor); + std::vector GetPredecessors() const + { + return predecessors; + } + + void SetControl(AddrShift control) + { + control_ = control; + } + + void SetPreControl(AddrShift control) + { + predeControl_ = control; + } + + void MergeControl(AddrShift control) + { + if (predeControl_ == -1) { + predeControl_ = control; + control_ = predeControl_; + } else { + otherPredeControls_.push_back(control); + } + } + + AddrShift GetControl() const + { + return control_; + } + + private: + bool IsNeedSeal() const; + bool IsSealed() const + { + return isSealed_; + } + bool IsLoopHead() const; + AddrShift ReadVariableRecursive(Variable *var); + Environment *env_; + AddrShift control_; + AddrShift predeControl_; + std::vector otherPredeControls_; + bool isSealed_; + std::map valueMap_; + std::vector phi; + std::vector predecessors; + std::map incompletePhis_; + }; + explicit Label() = default; + explicit Label(Environment *env); + explicit Label(LabelImpl *impl) : impl_(impl) {} + ~Label() = default; + Label(Label const &label) = default; + Label &operator=(Label const &label) = default; + Label(Label &&label) = default; + Label &operator=(Label &&label) = default; + + void Seal() + { + return impl_->Seal(); + } + + void WriteVariable(Variable *var, AddrShift value) + { + impl_->WriteVariable(var, value); + } + + AddrShift ReadVariable(Variable *var) + { + return impl_->ReadVariable(var); + } + + void Bind() { + impl_->Bind(); } - ~StubOptimizerLabelImplement() = default; - - NO_MOVE_SEMANTIC(StubOptimizerLabelImplement); - NO_COPY_SEMANTIC(StubOptimizerLabelImplement); - using Variable = StubVariable; - void Seal(); - void WriteVariable(Variable *var, AddrShift value); - AddrShift ReadVariable(Variable *var); - void Bind(); - void MergeAllControl(); - void AppendPredecessor(StubOptimizerLabelImplement *predecessor); - std::vector GetPredecessors() const + void MergeAllControl() { - return predecessors; + impl_->MergeAllControl(); + } + + void AppendPredecessor(const Label *predecessor) + { + impl_->AppendPredecessor(predecessor->GetRawLabel()); + } + + std::vector