From e79bf4aad8bddc1a4383b78b6d9f90ee464837f3 Mon Sep 17 00:00:00 2001 From: getingke Date: Thu, 9 Sep 2021 17:40:54 +0800 Subject: [PATCH] fixed for runtime stub module Signed-off-by: getingke Change-Id: I95f38c0c8d1280ffad25e613a2cd200105081906 --- BUILD.gn | 8 +- ecmascript/compiler/BUILD.gn | 34 +- ecmascript/compiler/code_generator.h | 43 + ecmascript/compiler/compile_llvm_lib.sh | 46 + ecmascript/compiler/fast_stub_define.h | 7 +- ecmascript/compiler/fastpath_optimizer.cpp | 628 +++++++++++- ecmascript/compiler/fastpath_optimizer.h | 100 +- ecmascript/compiler/llvm_codegen.cpp | 54 + ecmascript/compiler/llvm_codegen.h | 49 + ecmascript/compiler/llvm_ir_builder.cpp | 21 +- ecmascript/compiler/llvm_ir_builder.h | 23 +- ecmascript/compiler/llvm_mcjit_compiler.cpp | 14 +- ecmascript/compiler/llvm_mcjit_compiler.h | 42 +- ecmascript/compiler/llvm_stackmap_parse.h | 4 + ecmascript/compiler/scheduler.h | 5 +- ecmascript/compiler/stub_interface.cpp | 283 ++++-- ecmascript/compiler/stub_interface.h | 62 +- ecmascript/compiler/stub_module_builder.cpp | 175 ++++ ecmascript/compiler/stub_module_builder.h | 45 + ecmascript/compiler/stub_optimizer.cpp | 20 +- ecmascript/compiler/stub_optimizer.h | 82 +- ecmascript/compiler/tests/BUILD.gn | 6 +- .../compiler/tests/stub_optimizer_tests.cpp | 948 ++++-------------- ecmascript/compiler/verifier.cpp | 1 + ecmascript/compiler/verifier.h | 19 +- ecmascript/js_thread.cpp | 13 +- ecmascript/js_thread.h | 18 +- ecmascript/runtime_trampolines.cpp | 24 +- ecmascript/runtime_trampolines.h | 2 + ecmascript/stub_module.cpp | 46 + ecmascript/stub_module.h | 50 + test/test_helper.gni | 2 +- 32 files changed, 1867 insertions(+), 1007 deletions(-) create mode 100644 ecmascript/compiler/code_generator.h create mode 100755 ecmascript/compiler/compile_llvm_lib.sh create mode 100644 ecmascript/compiler/llvm_codegen.cpp create mode 100644 ecmascript/compiler/llvm_codegen.h create mode 100644 ecmascript/compiler/stub_module_builder.cpp create mode 100644 ecmascript/compiler/stub_module_builder.h create mode 100644 ecmascript/stub_module.cpp create mode 100644 ecmascript/stub_module.h diff --git a/BUILD.gn b/BUILD.gn index 0f8e7fe84d..e33feedf1f 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -32,11 +32,9 @@ group("ark_js_host_linux_tools_packages") { "//ark/js_runtime:libark_jsruntime(${host_toolchain})", "//ark/js_runtime/ecmascript/js_vm:ark_js_vm(${host_toolchain})", - #"//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer(${host_toolchain})", + "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer(${host_toolchain})", + "//ark/js_runtime/ecmascript/compiler:ark_stub_opt(${host_toolchain})", ] - if (current_cpu == "x86_64" || current_cpu == "x64") { - deps += [ "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer(${host_toolchain})" ] - } } } @@ -69,6 +67,7 @@ group("ark_js_host_unittest") { "//ark/js_runtime/ecmascript/snapshot/tests:host_unittest", "//ark/js_runtime/ecmascript/tests:host_unittest", "//ark/js_runtime/ecmascript/tooling/test:host_unittest", + "//ark/js_runtime/ecmascript/compiler/tests:host_unittest", ] if (current_cpu == "x86_64" || current_cpu == "x64") { deps += [ "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer(${host_toolchain})" ] @@ -352,6 +351,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 162ecd4975..0c19a24650 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" ] } @@ -39,6 +39,7 @@ ohos_shared_library("libark_jsoptimizer") { "circuit_visualizer.cpp", "fastpath_optimizer.cpp", "gate.cpp", + "llvm_codegen.cpp", "llvm_ir_builder.cpp", "llvm_mcjit_compiler.cpp", "llvm_stackmap_parse.cpp", @@ -172,7 +173,7 @@ ohos_shared_library("libark_jsoptimizer") { "LLVMTransformUtils", "LLVMAArch64Utils", "LLVMARMUtils", - "LLVMX86Utils", + #"LLVMX86Utils", ] deps = [ @@ -185,3 +186,30 @@ ohos_shared_library("libark_jsoptimizer") { relative_install_dir = "ark" subsystem_name = "ark" } + +ohos_executable("ark_stub_opt") { + sources = [ "stub_module_builder.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_stub_opt" + install_enable = false + + output_name = "ark_stub_opt" + subsystem_name = "ark" +} \ No newline at end of file diff --git a/ecmascript/compiler/code_generator.h b/ecmascript/compiler/code_generator.h new file mode 100644 index 0000000000..04ac6904ce --- /dev/null +++ b/ecmascript/compiler/code_generator.h @@ -0,0 +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_CODE_GENERATOR_H +#define ECMASCRIPT_COMPILER_CODE_GENERATOR_H + +#include "circuit.h" + +namespace kungfu { +using ControlFlowGraph = std::vector>; +class CodegenImplement { +public: + CodegenImplement() = default; + virtual ~CodegenImplement() = default; + virtual void GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, int index) = 0; +}; + +class CodeGenerator { +public: + explicit CodeGenerator(CodegenImplement *impl) : impl_(impl) {} + ~CodeGenerator() = default; + void Run(Circuit *circuit, const ControlFlowGraph &graph, int index) + { + impl_->GenerateCodeForStub(circuit, graph, index); + } + +private: + CodegenImplement *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 0000000000..f43489a5fe --- /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_CXX_FLAGS="-D_GLIBCXX_USE_CXX11_ABI=0" -DCMAKE_BUILD_TYPE=Release ../llvm + ninja +else + cd build + if [ ! -d "lib" ]; then + rm -rf * + cmake -GNinja -DCMAKE_CXX_FLAGS="-D_GLIBCXX_USE_CXX11_ABI=0" -DCMAKE_BUILD_TYPE=Release ../llvm + ninja + fi +fi + +echo "++++++++++++++++++++++++++++++++++" \ No newline at end of file diff --git a/ecmascript/compiler/fast_stub_define.h b/ecmascript/compiler/fast_stub_define.h index 9dbc8ab846..e56ce3cd0c 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.cpp b/ecmascript/compiler/fastpath_optimizer.cpp index 65ffd6a449..b962ab34d9 100644 --- a/ecmascript/compiler/fastpath_optimizer.cpp +++ b/ecmascript/compiler/fastpath_optimizer.cpp @@ -13,11 +13,15 @@ * limitations under the License. */ -#include "ecmascript/compiler/fastpath_optimizer.h" +#include "fastpath_optimizer.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 FastArrayLoadElementOptimizer::GenerateCircuit() { auto env = GetEnvironment(); @@ -25,18 +29,18 @@ void FastArrayLoadElementOptimizer::GenerateCircuit() AddrShift indexVal = Int32Argument(1); // load a.length - AddrShift lengthOffset = GetInteger32Constant(panda::ecmascript::JSArray::GetArrayLengthOffset()); + AddrShift lengthOffset = GetInteger32Constant(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 taggedLength = Load(MachineType::TAGGED_TYPE, aVal, lengthOffset); - AddrShift intLength = TaggedCastToInt32(taggegLength); + AddrShift intLength = TaggedCastToInt32(taggedLength); // if index < length - StubOptimizerLabel ifTrue(env); - StubOptimizerLabel ifFalse(env); + Label ifTrue(env); + Label ifFalse(env); Branch(Int32LessThan(indexVal, intLength), &ifTrue, &ifFalse); Bind(&ifTrue); Return(LoadFromObject(MachineType::TAGGED_TYPE, aVal, indexVal)); @@ -44,13 +48,611 @@ void FastArrayLoadElementOptimizer::GenerateCircuit() 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])} +void FastAddOptimizer::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 FastSubOptimizer::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 FastMulOptimizer::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 FastDivOptimizer::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); + Label afterFindElement(env); + AddrShift entry = FindElementFromNumberDictionary(thread, elements, taggedIndex, &afterFindElement); + 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); + { + Label afterFindElement(env); + AddrShift entry = FindElementFromNumberDictionary(thread, elements, IntBuildTagged(index), &afterFindElement); + 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 SetElementStub::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); + StubInterfaceDescriptor *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); + StubInterfaceDescriptor *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); + Label updateRepLabel(env); + UpdateRepresention(LoadHClass(receiver), value, &updateRepLabel); + 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); + { + StubInterfaceDescriptor *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); + { + StubInterfaceDescriptor *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); + { + StubInterfaceDescriptor *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/fastpath_optimizer.h b/ecmascript/compiler/fastpath_optimizer.h index bf61207024..62de2251f1 100644 --- a/ecmascript/compiler/fastpath_optimizer.h +++ b/ecmascript/compiler/fastpath_optimizer.h @@ -27,46 +27,78 @@ public: 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); - } +}; + +class FastAddOptimizer : public StubOptimizer { +public: + explicit FastAddOptimizer(Environment *env) : StubOptimizer(env) {} + ~FastAddOptimizer() = default; + NO_MOVE_SEMANTIC(FastAddOptimizer); + NO_COPY_SEMANTIC(FastAddOptimizer); + void GenerateCircuit() override; +}; + +class FastSubOptimizer : public StubOptimizer { +public: + explicit FastSubOptimizer(Environment *env) : StubOptimizer(env) {} + ~FastSubOptimizer() = default; + NO_MOVE_SEMANTIC(FastSubOptimizer); + NO_COPY_SEMANTIC(FastSubOptimizer); + void GenerateCircuit() override; +}; + +class FastMulOptimizer : public StubOptimizer { +public: + explicit FastMulOptimizer(Environment *env) : StubOptimizer(env) {} + ~FastMulOptimizer() = default; + NO_MOVE_SEMANTIC(FastMulOptimizer); + NO_COPY_SEMANTIC(FastMulOptimizer); + void GenerateCircuit() override; +}; -private: - const size_t MAX_MACHINE_CODE_SIZE = (1U << 20U); +class FastDivOptimizer : public StubOptimizer { +public: + explicit FastDivOptimizer(Environment *env) : StubOptimizer(env) {} + ~FastDivOptimizer() = default; + NO_MOVE_SEMANTIC(FastDivOptimizer); + NO_COPY_SEMANTIC(FastDivOptimizer); + void GenerateCircuit() override; }; -class FastRuntimeStubs { +class FastFindOwnElementStub : public StubOptimizer { 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, - }; + explicit FastFindOwnElementStub(Environment *env) : StubOptimizer(env) {} + ~FastFindOwnElementStub() = default; + NO_MOVE_SEMANTIC(FastFindOwnElementStub); + NO_COPY_SEMANTIC(FastFindOwnElementStub); + void GenerateCircuit() override; +}; - void GenerateFastRuntimeStubs(); +class FastGetElementStub : public StubOptimizer { +public: + explicit FastGetElementStub(Environment *env) : StubOptimizer(env) {} + ~FastGetElementStub() = default; + NO_MOVE_SEMANTIC(FastGetElementStub); + NO_COPY_SEMANTIC(FastGetElementStub); + void GenerateCircuit() override; +}; -private: - FastRuntimeStubs(); - ~FastRuntimeStubs(); - NO_MOVE_SEMANTIC(FastRuntimeStubs); - NO_COPY_SEMANTIC(FastRuntimeStubs); - std::array fastRuntimeEnvs_; - std::array fastRuntimeOptimizers_; +class FastFindOwnElement2Stub : public StubOptimizer { +public: + explicit FastFindOwnElement2Stub(Environment *env) : StubOptimizer(env) {} + ~FastFindOwnElement2Stub() = default; + NO_MOVE_SEMANTIC(FastFindOwnElement2Stub); + NO_COPY_SEMANTIC(FastFindOwnElement2Stub); + void GenerateCircuit() override; +}; + +class SetElementStub : public StubOptimizer { +public: + explicit SetElementStub(Environment *env) : StubOptimizer(env) {} + ~SetElementStub() = default; + NO_MOVE_SEMANTIC(SetElementStub); + NO_COPY_SEMANTIC(SetElementStub); + void GenerateCircuit() override; }; } // namespace kungfu #endif // ECMASCRIPT_COMPILER_FASTPATH_OPTIMIZER_H \ No newline at end of file diff --git a/ecmascript/compiler/llvm_codegen.cpp b/ecmascript/compiler/llvm_codegen.cpp new file mode 100644 index 0000000000..f11e6234b6 --- /dev/null +++ b/ecmascript/compiler/llvm_codegen.cpp @@ -0,0 +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 "llvm_codegen.h" +#include "ecmascript/object_factory.h" +#include "stub_interface.h" + +using namespace panda::ecmascript; +namespace kungfu { +void LLVMCodeGenrator::GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, int index) +{ + auto function = reinterpret_cast(FastStubs::GetInstance().GetFastStub(index)); + + LLVMIRBuilder builder(&graph, circuit, module_, function); + builder.Build(); +} + +void LLVMModuleAssembler::AssembleModule() +{ + compiler_.Run(); +} + +void LLVMModuleAssembler::CopyAssembleCodeToModule(StubModule *module) +{ + auto codeBuff = reinterpret_cast
(compiler_.GetCodeBuffer()); + auto engine = compiler_.GetEngine(); + for (int i = 0; i < FAST_STUB_MAXCOUNT; i++) { + auto stubfunction = reinterpret_cast(FastStubs::GetInstance().GetFastStub(i)); + if (stubfunction != nullptr) { + Address stubEntry = reinterpret_cast
(LLVMGetPointerToGlobal(engine, stubfunction)); + module->SetStubEntry(i, stubEntry - codeBuff); + } + } + + auto codeSize = compiler_.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 0000000000..f7bb2cf9be --- /dev/null +++ b/ecmascript/compiler/llvm_codegen.h @@ -0,0 +1,49 @@ +/* + * 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_compiler.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 LLVMCodeGenrator : public CodegenImplement { +public: + explicit LLVMCodeGenrator(LLVMModuleRef module) : module_(module) {} + ~LLVMCodeGenrator() = default; + void GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, int index) override; + +private: + LLVMModuleRef module_; +}; + +class LLVMModuleAssembler { +public: + explicit LLVMModuleAssembler(LLVMModuleRef module) : compiler_(module) {} + void AssembleModule(); + void CopyAssembleCodeToModule(panda::ecmascript::StubModule *module); + +private: + LLVMMCJITCompiler compiler_; +}; +} // 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 22fa5a9adb..d70d6d49b5 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -360,9 +360,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: { @@ -1031,7 +1034,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,12 +1044,22 @@ 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); } diff --git a/ecmascript/compiler/llvm_ir_builder.h b/ecmascript/compiler/llvm_ir_builder.h index ca6f1dd085..cc3a094c49 100644 --- a/ecmascript/compiler/llvm_ir_builder.h +++ b/ecmascript/compiler/llvm_ir_builder.h @@ -78,11 +78,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 { @@ -102,12 +103,13 @@ struct LLVMTFBuilderBasicBlockImpl { class LLVMIRBuilder { public: - LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit); - LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, LLVMModuleRef module, - LLVMValueRef function); + explicit LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit); + explicit LLVMIRBuilder(const std::vector> *schedule, const Circuit *circuit, + LLVMModuleRef module, LLVMValueRef function); void Build(); ~LLVMIRBuilder() = default; + private: void VisitCall(AddrShift gate, const std::vector &inList); void VisitAlloca(AddrShift gate); @@ -142,7 +144,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; @@ -175,5 +178,5 @@ private: std::vector phiRebuildWorklist_; }; -#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_compiler.cpp index 2ad0a094d0..2eaa1f75a3 100644 --- a/ecmascript/compiler/llvm_mcjit_compiler.cpp +++ b/ecmascript/compiler/llvm_mcjit_compiler.cpp @@ -140,13 +140,15 @@ void LLVMMCJITCompiler::Run() void LLVMMCJITCompiler::Initialize() { - LLVMInitializeAllTargetInfos(); - LLVMInitializeAllTargetMCs(); - LLVMInitializeAllDisassemblers(); +#if defined(PANDA_TARGET_AMD64) + LLVMInitializeX86TargetInfo(); + LLVMInitializeX86TargetMC(); + LLVMInitializeX86Disassembler(); /* this method must be called, ohterwise "Target does not support MC emission" */ - LLVMInitializeNativeAsmPrinter(); - LLVMInitializeNativeAsmParser(); - LLVMInitializeAllTargets(); + LLVMInitializeX86AsmPrinter(); + LLVMInitializeX86AsmParser(); + LLVMInitializeX86Target(); +#endif llvm::linkAllBuiltinGCs(); LLVMInitializeMCJITCompilerOptions(&options_, sizeof(options_)); options_.OptLevel = 2; // opt level 2 diff --git a/ecmascript/compiler/llvm_mcjit_compiler.h b/ecmascript/compiler/llvm_mcjit_compiler.h index b8c38782c6..9ceb596ab6 100644 --- a/ecmascript/compiler/llvm_mcjit_compiler.h +++ b/ecmascript/compiler/llvm_mcjit_compiler.h @@ -38,38 +38,39 @@ using ByteBuffer = std::vector; using BufferList = std::list; using StringList = std::list; struct CompilerState { - CompilerState(): machineCode(nullptr), codeBufferPos(0), stackMapsSection_(nullptr) + CompilerState() : 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() { 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,25 +93,37 @@ 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 { public: @@ -127,6 +140,15 @@ public: return compilerState_.GetStackMapsSection(); } + int GetCodeSize() const + { + return compilerState_.GetCodeSize(); + } + uint8_t *GetCodeBuffer() const + { + return compilerState_.GetCodeBuff(); + } + private: void UseRoundTripSectionMemoryManager(); bool BuildMCJITEngine(); diff --git a/ecmascript/compiler/llvm_stackmap_parse.h b/ecmascript/compiler/llvm_stackmap_parse.h index 17204129db..44c3e10180 100644 --- a/ecmascript/compiler/llvm_stackmap_parse.h +++ b/ecmascript/compiler/llvm_stackmap_parse.h @@ -18,6 +18,7 @@ #include #include #include +#include namespace kungfu { using OffsetType = int32_t; @@ -205,7 +206,10 @@ private: const uint8_t *stackMapAddr_; struct LLVMStackMap llvmStackMap_; std::vector callSiteInfos_; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-private-field" std::unique_ptr dataInfo_; +#pragma clang diagnostic pop }; } // namespace kungfu #endif // ECMASCRIPT_COMPILER_LLVM_LLVMSTACKPARSE_H \ No newline at end of file diff --git a/ecmascript/compiler/scheduler.h b/ecmascript/compiler/scheduler.h index edfa7be124..69f569b91b 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_interface.cpp b/ecmascript/compiler/stub_interface.cpp index 66908736a1..015ff8d706 100644 --- a/ecmascript/compiler/stub_interface.cpp +++ b/ecmascript/compiler/stub_interface.cpp @@ -38,26 +38,46 @@ namespace kungfu { LLVM_STUB_GETFUCTION(FastAdd) { - (void)module; - return nullptr; + // 2 : 2 input parameters + std::array paramTys = { + LLVMInt64Type(), + LLVMInt64Type(), + }; + // 2 : 2 input parameters + return LLVMAddFunction(module, "FastAdd", LLVMFunctionType(LLVMInt64Type(), paramTys.data(), 2, 0)); } LLVM_STUB_GETFUCTION(FastSub) { - (void)module; - return nullptr; + // 2 : 2 input parameters + std::array paramTys = { + LLVMInt64Type(), + LLVMInt64Type(), + }; + // 2 : 2 input parameters + return LLVMAddFunction(module, "FastSub", LLVMFunctionType(LLVMInt64Type(), paramTys.data(), 2, 0)); } LLVM_STUB_GETFUCTION(FastMul) { - (void)module; - return nullptr; + // 2 : 2 input parameters + std::array paramTys = { + LLVMInt64Type(), + LLVMInt64Type(), + }; + // 2 : 2 input parameters + return LLVMAddFunction(module, "FastMul", LLVMFunctionType(LLVMInt64Type(), paramTys.data(), 2, 0)); } LLVM_STUB_GETFUCTION(FastDiv) { - (void)module; - return nullptr; + // 2 : 2 input parameters + std::array paramTys = { + LLVMInt64Type(), + LLVMInt64Type(), + }; + // 2 : 2 input parameters + return LLVMAddFunction(module, "FastDiv", LLVMFunctionType(LLVMInt64Type(), paramTys.data(), 2, 0)); } LLVM_STUB_GETFUCTION(FastMod) @@ -98,13 +118,14 @@ LLVM_STUB_GETFUCTION(IsSpecialIndexedObjForGet) LLVM_STUB_GETFUCTION(GetElement) { - // 2 : 2 input parameters - std::array paramTys = { + // 3 : 3 input parameters + std::array paramTys = { + LLVMInt64Type(), LLVMInt64Type(), LLVMInt32Type(), }; - // 2 : 2 input parameters - return LLVMAddFunction(module, "GetElement", LLVMFunctionType(LLVMInt64Type(), paramTys.data(), 2, 0)); + // 3 : 3 input parameters + return LLVMAddFunction(module, "GetElement", LLVMFunctionType(LLVMInt64Type(), paramTys.data(), 3, 0)); } LLVM_STUB_GETFUCTION(SetElement) @@ -173,13 +194,14 @@ LLVM_STUB_GETFUCTION(FindOwnProperty) LLVM_STUB_GETFUCTION(FindOwnElement) { - // 2 : 2 input parameters - std::array paramTys = { + // 3 : 3 input parameters + std::array paramTys = { + LLVMInt64Type(), LLVMInt64Type(), LLVMInt32Type(), }; - // 2 : 2 input parameters - return LLVMAddFunction(module, "FindOwnElement", LLVMFunctionType(LLVMInt64Type(), paramTys.data(), 2, 0)); + // 3 : 3 input parameters + return LLVMAddFunction(module, "FindOwnElement", LLVMFunctionType(LLVMInt64Type(), paramTys.data(), 3, 0)); } LLVM_STUB_GETFUCTION(NewLexicalEnvDyn) @@ -190,12 +212,8 @@ LLVM_STUB_GETFUCTION(NewLexicalEnvDyn) LLVM_STUB_GETFUCTION(FindOwnProperty2) { - // 5 : 5 input parameters - std::array paramTys = { - LLVMInt64Type(), LLVMInt32Type(), LLVMInt1Type(), LLVMInt64Type(), LLVMInt64Type(), - }; - // 5 : 5 input parameters - return LLVMAddFunction(module, "FindOwnProperty2", LLVMFunctionType(LLVMInt64Type(), paramTys.data(), 5, 0)); + (void)module; + return nullptr; } LLVM_STUB_GETFUCTION(FindOwnElement2) @@ -260,12 +278,13 @@ LLVM_STUB_GETFUCTION_TYPE(IsSpecialIndexedObjForGet) LLVM_STUB_GETFUCTION_TYPE(GetElement) { - // 2 : 2 input parameters - std::array paramTys = { + // 3 : 3 input parameters + std::array paramTys = { + LLVMInt64Type(), LLVMInt64Type(), LLVMInt32Type(), }; - return LLVMFunctionType(LLVMInt64Type(), paramTys.data(), 2, 0); // 2 : 2 parameters number + return LLVMFunctionType(LLVMInt64Type(), paramTys.data(), 3, 0); // 3 : 3 parameters number } LLVM_STUB_GETFUCTION_TYPE(SetElement) @@ -324,12 +343,13 @@ LLVM_STUB_GETFUCTION_TYPE(FindOwnProperty) LLVM_STUB_GETFUCTION_TYPE(FindOwnElement) { - // 2 : 2 parameters number - std::array paramTys = { + // 3 : 3 parameters number + std::array paramTys = { + LLVMInt64Type(), LLVMInt64Type(), LLVMInt32Type(), }; - return LLVMFunctionType(LLVMInt64Type(), paramTys.data(), 2, 0); // 2 : 2 parameters number + return LLVMFunctionType(LLVMInt64Type(), paramTys.data(), 3, 0); // 3 : 3 parameters number } LLVM_STUB_GETFUCTION_TYPE(NewLexicalEnvDyn) @@ -348,11 +368,11 @@ LLVM_STUB_GETFUCTION_TYPE(FindOwnProperty2) LLVM_STUB_GETFUCTION_TYPE(FindOwnElement2) { - // 5 : 5 parameters number - std::array paramTys = { - LLVMInt64Type(), LLVMInt32Type(), LLVMInt1Type(), LLVMInt64Type(), LLVMInt64Type(), + // 6 : 6 parameters number + std::array paramTys = { + LLVMInt64Type(), LLVMInt64Type(), LLVMInt32Type(), LLVMInt1Type(), LLVMInt64Type(), LLVMInt64Type(), }; - return LLVMFunctionType(LLVMInt64Type(), paramTys.data(), 5, 0); // 5 : 5 parameters number + return LLVMFunctionType(LLVMInt64Type(), paramTys.data(), 6, 0); // 6 : 6 parameters number } LLVM_STUB_GETFUCTION_TYPE(AddElementInternal) @@ -373,6 +393,20 @@ LLVM_STUB_GETFUCTION_TYPE(CallSetter) return LLVMFunctionType(LLVMInt1Type(), paramTys.data(), 5, 0); // 5 : 5 parameters number } +LLVM_STUB_GETFUCTION_TYPE(CallGetter) +{ + // 3 : 3 parameters number + std::array paramTys = {LLVMInt64Type(), LLVMInt64Type(), LLVMInt64Type()}; + return LLVMFunctionType(LLVMInt64Type(), paramTys.data(), 3, 0); // 3 : 3 parameters number +} + +LLVM_STUB_GETFUCTION_TYPE(AccessorGetter) +{ + // 3 : 3 parameters number + std::array paramTys = {LLVMInt64Type(), LLVMInt64Type(), LLVMInt64Type()}; + return LLVMFunctionType(LLVMInt64Type(), paramTys.data(), 3, 0); // 3 : 3 parameters number +} + LLVM_STUB_GETFUCTION_TYPE(ThrowTypeError) { // 2 : 2 parameters number @@ -399,13 +433,13 @@ LLVM_STUB_GETFUCTION_TYPE(GetHash32) return LLVMFunctionType(LLVMInt32Type(), paramTys.data(), 2, 0); // 2 : 2 parameters number } -LLVMStubsImplement::LLVMStubsImplement() +LLVMStubsImpl::LLVMStubsImpl() { stubsModule_ = LLVMModuleCreateWithName("fast_stubs"); LLVMSetTarget(stubsModule_, "x86_64-unknown-linux-gnu"); } -void LLVMStubsImplement::Initialize() +void LLVMStubsImpl::Initialize() { // Initialize Stubs Function // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) @@ -428,19 +462,19 @@ void LLVMStubsImplement::Initialize() #undef DEF_CALL_STUB } -void *LLVMStubsImplement::GetFastStub(int index) +void *LLVMStubsImpl::GetFastStub(int index) { ASSERT(index < CALL_STUB_MAXCOUNT && index >= 0); return reinterpret_cast(llvmCallStubs_[index]); } -void LLVMStubsImplement::SetFastStub(int index, void *code) +void LLVMStubsImpl::SetFastStub(int index, void *code) { ASSERT(index < CALL_STUB_MAXCOUNT && index >= 0); llvmCallStubs_[index] = reinterpret_cast(code); } -void *LLVMStubsImplement::GetRunTimeLLVMType(int index) +void *LLVMStubsImpl::GetRunTimeLLVMType(int index) { ASSERT(index < CALL_STUB_MAXCOUNT && index >= 0); return reinterpret_cast(llvm_fuction_type_[index]); @@ -454,13 +488,57 @@ void *LLVMStubsImplement::GetRunTimeLLVMType(int index) }; \ void Stub##name##InterfaceDescriptor::Initialize(StubInterfaceDescriptor *descriptor) -CALL_STUB_INIT_DESCRIPTOR(FastAdd) {} +CALL_STUB_INIT_DESCRIPTOR(FastAdd) +{ + // 2 : 2 input parameters + static StubInterfaceDescriptor fastAdd("FastAdd", 0, 2, DEFAULT_ORDER, UINT64_TYPE); + *descriptor = fastAdd; + // 2 : 2 input parameters + std::array params = { + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); +} -CALL_STUB_INIT_DESCRIPTOR(FastSub) {} +CALL_STUB_INIT_DESCRIPTOR(FastSub) +{ + // 2 : 2 input parameters + static StubInterfaceDescriptor fastSub("FastSub", 0, 2, DEFAULT_ORDER, UINT64_TYPE); + *descriptor = fastSub; + // 2 : 2 input parameters + std::array params = { + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); +} -CALL_STUB_INIT_DESCRIPTOR(FastMul) {} +CALL_STUB_INIT_DESCRIPTOR(FastMul) +{ + // 2 : 2 input parameters + static StubInterfaceDescriptor fastMul("FastMul", 0, 2, DEFAULT_ORDER, UINT64_TYPE); + *descriptor = fastMul; + // 2 : 2 input parameters + std::array params = { + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); +} -CALL_STUB_INIT_DESCRIPTOR(FastDiv) {} +CALL_STUB_INIT_DESCRIPTOR(FastDiv) +{ + // 2 : 2 input parameters + static StubInterfaceDescriptor fastDiv("FastDiv", 0, 2, DEFAULT_ORDER, UINT64_TYPE); + *descriptor = fastDiv; + // 2 : 2 input parameters + std::array params = { + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); +} CALL_STUB_INIT_DESCRIPTOR(FastMod) {} @@ -474,9 +552,32 @@ CALL_STUB_INIT_DESCRIPTOR(IsSpecialIndexedObjForSet) {} CALL_STUB_INIT_DESCRIPTOR(IsSpecialIndexedObjForGet) {} -CALL_STUB_INIT_DESCRIPTOR(GetElement) {} +CALL_STUB_INIT_DESCRIPTOR(GetElement) +{ + // 3 : 3 input parameters + static StubInterfaceDescriptor getElement("GetElement", 0, 3, DEFAULT_ORDER, UINT64_TYPE); + *descriptor = getElement; + // 3 : 3 input parameters + std::array params = { + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, + MachineType::UINT32_TYPE, + }; + descriptor->SetParameters(params.data()); +} -CALL_STUB_INIT_DESCRIPTOR(SetElement) {} +CALL_STUB_INIT_DESCRIPTOR(SetElement) +{ + // 5 : 5 input parameters + static StubInterfaceDescriptor setElement("SetElement", 0, 5, DEFAULT_ORDER, BOOL_TYPE); + *descriptor = setElement; + // 5 : 5 input parameters + std::array params = { + MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, MachineType::UINT32_TYPE, + MachineType::UINT64_TYPE, MachineType::UINT32_TYPE, + }; + descriptor->SetParameters(params.data()); +} CALL_STUB_INIT_DESCRIPTOR(SetPropertyByName) {} @@ -496,7 +597,18 @@ CALL_STUB_INIT_DESCRIPTOR(FastGetProperty) {} CALL_STUB_INIT_DESCRIPTOR(FindOwnProperty) {} -CALL_STUB_INIT_DESCRIPTOR(FindOwnElement) {} +CALL_STUB_INIT_DESCRIPTOR(FindOwnElement) +{ + // 2 : 2 input parameters + static StubInterfaceDescriptor findOwnElement("FindOwnElement", 0, 2, DEFAULT_ORDER, UINT64_TYPE); + *descriptor = findOwnElement; + // 2 : 2 input parameters + std::array params = { + MachineType::UINT64_TYPE, + MachineType::UINT32_TYPE, + }; + descriptor->SetParameters(params.data()); +} CALL_STUB_INIT_DESCRIPTOR(NewLexicalEnvDyn) {} @@ -504,15 +616,13 @@ CALL_STUB_INIT_DESCRIPTOR(FindOwnProperty2) {} CALL_STUB_INIT_DESCRIPTOR(FindOwnElement2) { - // 5 : 5 input parameters - static StubInterfaceDescriptor findOwnElement2(0, 5, DEFAULT_ORDER, UINT64_TYPE); + // 6 : 6 input parameters + static StubInterfaceDescriptor findOwnElement2("FindOwnElement2", 0, 6, DEFAULT_ORDER, UINT64_TYPE); *descriptor = findOwnElement2; - std::array params = { // 5 : 5 input parameters - MachineType::UINT64_TYPE, - MachineType::UINT32_TYPE, - MachineType::BOOL_TYPE, - MachineType::UINT64_TYPE, - MachineType::UINT64_TYPE, + // 6 : 6 input parameters + std::array params = { + MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, MachineType::UINT32_TYPE, + MachineType::BOOL_TYPE, MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, }; descriptor->SetParameters(params.data()); } @@ -520,14 +630,12 @@ CALL_STUB_INIT_DESCRIPTOR(FindOwnElement2) CALL_STUB_INIT_DESCRIPTOR(AddElementInternal) { // 5 : 5 input parameters - static StubInterfaceDescriptor addElementInternal(0, 5, DEFAULT_ORDER, BOOL_TYPE); + static StubInterfaceDescriptor addElementInternal("AddElementInternal", 0, 5, DEFAULT_ORDER, BOOL_TYPE); *descriptor = addElementInternal; - std::array params = { // 5 : 5 input parameters - MachineType::UINT64_TYPE, - MachineType::UINT64_TYPE, - MachineType::UINT32_TYPE, - MachineType::UINT64_TYPE, - MachineType::UINT32_TYPE, + // 5 : 5 input parameters + std::array params = { + MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, MachineType::UINT32_TYPE, + MachineType::UINT64_TYPE, MachineType::UINT32_TYPE, }; descriptor->SetParameters(params.data()); descriptor->SetStubKind(StubInterfaceDescriptor::RUNTIME_STUB); @@ -536,14 +644,42 @@ CALL_STUB_INIT_DESCRIPTOR(AddElementInternal) CALL_STUB_INIT_DESCRIPTOR(CallSetter) { // 5 : 5 input parameters - static StubInterfaceDescriptor callSetter(0, 5, DEFAULT_ORDER, NONE_TYPE); + static StubInterfaceDescriptor callSetter("CallSetter", 0, 5, DEFAULT_ORDER, NONE_TYPE); *descriptor = callSetter; - std::array params = { // 5 : 5 input parameters + // 5 : 5 input parameters + std::array params = { + MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, MachineType::BOOL_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubInterfaceDescriptor::RUNTIME_STUB); +} + +CALL_STUB_INIT_DESCRIPTOR(CallGetter) +{ + // 3 : 3 input parameters + static StubInterfaceDescriptor callGetter("CallGetter", 0, 3, DEFAULT_ORDER, NONE_TYPE); + *descriptor = callGetter; + // 3 : 3 input parameters + std::array params = { MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, + }; + descriptor->SetParameters(params.data()); + descriptor->SetStubKind(StubInterfaceDescriptor::RUNTIME_STUB); +} + +CALL_STUB_INIT_DESCRIPTOR(AccessorGetter) +{ + // 3 : 3 input parameters + static StubInterfaceDescriptor accessorGetter("AccessorGetter", 0, 3, DEFAULT_ORDER, NONE_TYPE); + *descriptor = accessorGetter; + // 3 : 3 input parameters + std::array params = { + MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, - MachineType::BOOL_TYPE, }; descriptor->SetParameters(params.data()); descriptor->SetStubKind(StubInterfaceDescriptor::RUNTIME_STUB); @@ -552,9 +688,10 @@ CALL_STUB_INIT_DESCRIPTOR(CallSetter) CALL_STUB_INIT_DESCRIPTOR(ThrowTypeError) { // 2 : 2 input parameters - static StubInterfaceDescriptor throwTypeError(0, 2, DEFAULT_ORDER, NONE_TYPE); + static StubInterfaceDescriptor throwTypeError("ThrowTypeError", 0, 2, DEFAULT_ORDER, NONE_TYPE); *descriptor = throwTypeError; - std::array params = { // 2 : 2 input parameters + // 2 : 2 input parameters + std::array params = { MachineType::UINT64_TYPE, MachineType::UINT32_TYPE, }; @@ -565,15 +702,12 @@ CALL_STUB_INIT_DESCRIPTOR(ThrowTypeError) CALL_STUB_INIT_DESCRIPTOR(JSProxySetProperty) { // 6 : 6 input parameters - static StubInterfaceDescriptor jsproxySetproperty(0, 6, DEFAULT_ORDER, BOOL_TYPE); + static StubInterfaceDescriptor jsproxySetproperty("JSProxySetProperty", 0, 6, DEFAULT_ORDER, BOOL_TYPE); *descriptor = jsproxySetproperty; - std::array params = { // 6 : 6 input parameters - MachineType::UINT64_TYPE, - MachineType::UINT64_TYPE, - MachineType::UINT64_TYPE, - MachineType::UINT64_TYPE, - MachineType::UINT64_TYPE, - MachineType::BOOL_TYPE, + // 6 : 6 input parameters + std::array params = { + MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, + MachineType::UINT64_TYPE, MachineType::UINT64_TYPE, MachineType::BOOL_TYPE, }; descriptor->SetParameters(params.data()); descriptor->SetStubKind(StubInterfaceDescriptor::RUNTIME_STUB); @@ -582,9 +716,10 @@ CALL_STUB_INIT_DESCRIPTOR(JSProxySetProperty) CALL_STUB_INIT_DESCRIPTOR(GetHash32) { // 2 : 2 input parameters - static StubInterfaceDescriptor getHash32(0, 2, DEFAULT_ORDER, UINT32_TYPE); + static StubInterfaceDescriptor getHash32("GetHash32", 0, 2, DEFAULT_ORDER, UINT32_TYPE); *descriptor = getHash32; - std::array params = { // 2 : 2 input parameters + // 2 : 2 input parameters + std::array params = { MachineType::POINTER_TYPE, MachineType::UINT32_TYPE, }; diff --git a/ecmascript/compiler/stub_interface.h b/ecmascript/compiler/stub_interface.h index 758fb6f1fa..cc371c5dbc 100644 --- a/ecmascript/compiler/stub_interface.h +++ b/ecmascript/compiler/stub_interface.h @@ -34,14 +34,16 @@ public: CODE_STUB, RUNTIME_STUB, }; - explicit StubInterfaceDescriptor(int flags, int paramCounter, ArgumentsOrder order, MachineType returnType) - : flags_(flags), paramCounter_(paramCounter), order_(order), returnType_(returnType) + explicit StubInterfaceDescriptor(std::string name, int flags, int paramCounter, ArgumentsOrder order, + MachineType returnType) + : name_(name), flags_(flags), paramCounter_(paramCounter), order_(order), returnType_(returnType) { } StubInterfaceDescriptor() = default; ~StubInterfaceDescriptor() = default; StubInterfaceDescriptor(StubInterfaceDescriptor const &other) { + name_ = other.name_; flags_ = other.flags_; paramCounter_ = other.paramCounter_; order_ = other.order_; @@ -57,6 +59,7 @@ public: StubInterfaceDescriptor &operator=(StubInterfaceDescriptor const &other) { + name_ = other.name_; flags_ = other.flags_; paramCounter_ = other.paramCounter_; order_ = other.order_; @@ -120,22 +123,28 @@ public: kind_ = kind; } -private: - CallStubKind kind_{CODE_STUB}; - int flags_{0}; - int paramCounter_{0}; - ArgumentsOrder order_{DEFAULT_ORDER}; + const std::string &GetName() + { + return name_; + } - MachineType returnType_{MachineType::NONE_TYPE}; - std::unique_ptr> paramsType_{nullptr}; +private: + std::string name_; + CallStubKind kind_ {CODE_STUB}; + int flags_ {0}; + int paramCounter_ {0}; + ArgumentsOrder order_ {DEFAULT_ORDER}; + + MachineType returnType_ {MachineType::NONE_TYPE}; + std::unique_ptr> paramsType_ {nullptr}; }; -class CallStubsImplement { +class CallStubsImpl { public: - CallStubsImplement() = default; - virtual ~CallStubsImplement() = default; - NO_MOVE_SEMANTIC(CallStubsImplement); - NO_COPY_SEMANTIC(CallStubsImplement); + CallStubsImpl() = default; + virtual ~CallStubsImpl() = default; + NO_MOVE_SEMANTIC(CallStubsImpl); + NO_COPY_SEMANTIC(CallStubsImpl); virtual void Initialize() = 0; virtual void *GetFastStub(int index) = 0; virtual void SetFastStub(int index, void *code) = 0; @@ -143,12 +152,12 @@ public: virtual void *GetModule() = 0; }; -class LLVMStubsImplement : public CallStubsImplement { +class LLVMStubsImpl : public CallStubsImpl { public: - LLVMStubsImplement(); - ~LLVMStubsImplement() override = default; - NO_MOVE_SEMANTIC(LLVMStubsImplement); - NO_COPY_SEMANTIC(LLVMStubsImplement); + LLVMStubsImpl(); + ~LLVMStubsImpl() override = default; + NO_MOVE_SEMANTIC(LLVMStubsImpl); + NO_COPY_SEMANTIC(LLVMStubsImpl); void Initialize() override; void *GetFastStub(int index) override; void SetFastStub(int index, void *code) override; @@ -160,12 +169,11 @@ public: } private: - std::array llvmCallStubs_{nullptr}; - std::array llvm_fuction_type_{nullptr}; - LLVMModuleRef stubsModule_{nullptr}; + std::array llvmCallStubs_ {nullptr}; + std::array llvm_fuction_type_ {nullptr}; + LLVMModuleRef stubsModule_ {nullptr}; }; -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define FAST_STUB_ID(name) NAME_##name + // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define GET_STUBDESCRIPTOR(name) FastStubs::GetInstance().GetStubDescriptor(FAST_STUB_ID(name)) @@ -213,14 +221,14 @@ public: private: FastStubs() { - stubsImpl_ = std::make_unique(); + stubsImpl_ = std::make_unique(); InitializeFastStubs(); } ~FastStubs() {} NO_MOVE_SEMANTIC(FastStubs); NO_COPY_SEMANTIC(FastStubs); - std::unique_ptr stubsImpl_{nullptr}; - std::array callStubsDescriptor_{}; + std::unique_ptr stubsImpl_ {nullptr}; + std::array callStubsDescriptor_ {}; }; } // namespace kungfu #endif // ECMASCRIPT_COMPILER_STUB_INTERFACE_H \ No newline at end of file diff --git a/ecmascript/compiler/stub_module_builder.cpp b/ecmascript/compiler/stub_module_builder.cpp new file mode 100644 index 0000000000..0c1bade032 --- /dev/null +++ b/ecmascript/compiler/stub_module_builder.cpp @@ -0,0 +1,175 @@ +/* + * 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 "stub_module_builder.h" +#include +#include +#include +#include "fastpath_optimizer.h" +#include "llvm_codegen.h" +#include "scheduler.h" +#include "stub_optimizer.h" +#include "verifier.h" + +namespace kungfu { +class PipeLineData { +public: + explicit PipeLineData(Circuit *circuit) : circuit_(circuit) {} + ~PipeLineData() = default; + const ControlFlowGraph &GetScheduleResult() const + { + return cfg; + } + + void SetScheduleResult(const ControlFlowGraph &result) + { + cfg = result; + } + + Circuit *GetCircuit() const + { + return circuit_; + } + +private: + Circuit *circuit_; + ControlFlowGraph cfg; +}; + +class CircuitPipeLine { +public: + explicit CircuitPipeLine(PipeLineData *data) : data_(data) {} + ~CircuitPipeLine() = default; + template + bool RunPass(Args... args) + { + T pass; + return pass.Run(data_, std::forward(args)...); + } + +private: + PipeLineData *data_; +}; + +class VerifierPass { +public: + bool Run(PipeLineData *data) + { + Verifier::Run(data->GetCircuit()); + return true; + } +}; + +class SchedulerPass { +public: + bool Run(PipeLineData *data) + { + data->SetScheduleResult(Scheduler::Run(data->GetCircuit())); + return true; + } +}; + +class LLVMCodegenPass { +public: + bool Run(PipeLineData *data, int index) + { + auto llvmModule = static_cast(FastStubs::GetInstance().GetModule()); + LLVMCodeGenrator llvmImpl(llvmModule); + CodeGenerator codegen(&llvmImpl); + codegen.Run(data->GetCircuit(), data->GetScheduleResult(), index); + return true; + } +}; + +void StubModuleBuilder::BuildStubModule(panda::ecmascript::StubModule *module) +{ + for (int i = 0; i < FAST_STUB_MAXCOUNT; i++) { + auto stubOptimizer = stubs_[i]; + if (stubOptimizer != nullptr) { + stubOptimizer->GenerateCircuit(); + auto circuit = stubOptimizer->GetEnvironment()->GetCircuit(); + PipeLineData data(&circuit); + CircuitPipeLine pipeline(&data); + pipeline.RunPass(); + pipeline.RunPass(); + pipeline.RunPass(i); + } + } + auto llvmModule = static_cast(FastStubs::GetInstance().GetModule()); + LLVMModuleAssembler assembler(llvmModule); + assembler.AssembleModule(); + assembler.CopyAssembleCodeToModule(module); +} +} // namespace kungfu + +int main(int argc, char *argv[]) +{ + int opt; + // 3 means ark_stub_opt -f stub.m + if (argc != 3) { + std::cerr << "Usage: " << argv[0] << " -f stub.m" << std::endl; + return -1; + } + std::string moduleFilename; + while ((opt = getopt(argc, argv, "f:")) != -1) { + switch (opt) { + case 'f': + moduleFilename += optarg; + break; + default: /* '?' */ + std::cerr << "Usage: " << argv[0] << " -f stub.m" << std::endl; + return -1; + } + } + + kungfu::StubModuleBuilder mouldeBuilder; + panda::ecmascript::StubModule stubModule; + /* Set Stub optimizers into module */ + kungfu::Environment fastaddEnv("FastAdd", 2); // 2 parameters + kungfu::FastAddOptimizer fastaddOptimizer(&fastaddEnv); + mouldeBuilder.SetStubOptimizer(FAST_STUB_ID(FastAdd), &fastaddOptimizer); + + kungfu::Environment fastsubEnv("FastSub", 2); // 2 parameters + kungfu::FastSubOptimizer fastsubOptimizer(&fastsubEnv); + mouldeBuilder.SetStubOptimizer(FAST_STUB_ID(FastSub), &fastsubOptimizer); + + kungfu::Environment fastmulEnv("FastMul", 2); // 2 parameters + kungfu::FastMulOptimizer fastmulOptimizer(&fastmulEnv); + mouldeBuilder.SetStubOptimizer(FAST_STUB_ID(FastMul), &fastmulOptimizer); + + kungfu::Environment fastdivEnv("FastDiv", 2); // 2 parameters + kungfu::FastDivOptimizer fastdivOptimizer(&fastdivEnv); + mouldeBuilder.SetStubOptimizer(FAST_STUB_ID(FastDiv), &fastdivOptimizer); + + kungfu::Environment fastFindOwnElementEnv("FindOwnElement", 3); // 3 parameters + kungfu::FastFindOwnElementStub fastFindOwnElementStub(&fastFindOwnElementEnv); + mouldeBuilder.SetStubOptimizer(FAST_STUB_ID(FindOwnElement), &fastFindOwnElementStub); + + kungfu::Environment fastGetElementEnv("GetElement", 3); // 3 parameters + kungfu::FastGetElementStub fastGetElementStub(&fastGetElementEnv); + mouldeBuilder.SetStubOptimizer(FAST_STUB_ID(GetElement), &fastGetElementStub); + + kungfu::Environment fastFindOwnElement2Env("FindOwnElement2", 6); // 6 parameters + kungfu::FastFindOwnElement2Stub fastFindOwnElement2Stub(&fastFindOwnElement2Env); + mouldeBuilder.SetStubOptimizer(FAST_STUB_ID(FindOwnElement2), &fastFindOwnElement2Stub); + + kungfu::Environment fastSetElementEnv("SetElement", 5); // 5 parameters + kungfu::SetElementStub fastSetElementStub(&fastSetElementEnv); + mouldeBuilder.SetStubOptimizer(FAST_STUB_ID(SetElement), &fastSetElementStub); + + mouldeBuilder.BuildStubModule(nullptr, &stubModule); + stubModule.Save(moduleFilename); + exit(0); +} \ No newline at end of file diff --git a/ecmascript/compiler/stub_module_builder.h b/ecmascript/compiler/stub_module_builder.h new file mode 100644 index 0000000000..e2822876d6 --- /dev/null +++ b/ecmascript/compiler/stub_module_builder.h @@ -0,0 +1,45 @@ +/* + * 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_STUB_MODULE_BUILDER_H +#define ECMASCRIPT_COMPILER_STUB_MODULE_BUILDER_H + +#include "ecmascript/js_thread.h" +#include "ecmascript/stub_module.h" + +namespace kungfu { +class StubOptimizer; +class circuit; +using Address = uintptr_t; +class StubModuleBuilder { +public: + StubModuleBuilder() + { + for (int i = 0; i < FAST_STUB_MAXCOUNT; i++) { + stubs_[i] = nullptr; + } + }; + ~StubModuleBuilder() = default; + void BuildStubModule(panda::ecmascript::StubModule *module); + void SetStubOptimizer(int index, StubOptimizer *optimizer) + { + stubs_[index] = optimizer; + } + +private: + std::array stubs_; +}; +} // namespace kungfu +#endif // ECMASCRIPT_COMPILER_STUB_MODULE_BUILDER_H diff --git a/ecmascript/compiler/stub_optimizer.cpp b/ecmascript/compiler/stub_optimizer.cpp index 25e344e793..17e86a7f0d 100644 --- a/ecmascript/compiler/stub_optimizer.cpp +++ b/ecmascript/compiler/stub_optimizer.cpp @@ -21,7 +21,7 @@ #include "libpandabase/macros.h" namespace kungfu { -using StubOPtimizerLabelImplement = StubOptimizerLabel::StubOptimizerLabelImplement; +using StubOptimizerLabelImpl = StubOptimizerLabel::StubOptimizerLabelImpl; StubOptimizerLabel::StubOptimizerLabel(Environment *env) { @@ -107,7 +107,7 @@ void StubVariable::RerouteOuts(const std::vector &outs, Gate *newGate) } } -void StubOPtimizerLabelImplement::Seal() +void StubOptimizerLabelImpl::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 StubOptimizerLabelImpl::WriteVariable(StubVariable *var, AddrShift value) { valueMap_[var] = value; } -AddrShift StubOPtimizerLabelImplement::ReadVariable(StubVariable *var) +AddrShift StubOptimizerLabelImpl::ReadVariable(StubVariable *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 StubOptimizerLabelImpl::ReadVariableRecursive(StubVariable *var) { AddrShift val; OpCode opcode = CircuitBuilder::GetSelectOpCodeFromMachineType(var->Type()); @@ -151,7 +151,7 @@ AddrShift StubOPtimizerLabelImplement::ReadVariableRecursive(StubVariable *var) return val; } -void StubOPtimizerLabelImplement::Bind() +void StubOptimizerLabelImpl::Bind() { ASSERT(!predecessors.empty()); if (IsNeedSeal()) { @@ -160,7 +160,7 @@ void StubOPtimizerLabelImplement::Bind() } } -void StubOPtimizerLabelImplement::MergeAllControl() +void StubOptimizerLabelImpl::MergeAllControl() { if (predecessors.size() < 2) { // 2 : Loop Head only support two predecessors return; @@ -188,21 +188,21 @@ void StubOPtimizerLabelImplement::MergeAllControl() control_ = merge; } -void StubOPtimizerLabelImplement::AppendPredecessor(StubOptimizerLabelImplement *predecessor) +void StubOptimizerLabelImpl::AppendPredecessor(StubOptimizerLabelImpl *predecessor) { if (predecessor != nullptr) { predecessors.push_back(predecessor); } } -bool StubOPtimizerLabelImplement::IsNeedSeal() const +bool StubOptimizerLabelImpl::IsNeedSeal() const { auto control = env_->GetCircuit().LoadGatePtr(predeControl_); auto numsInList = control->GetOpCode().GetOpCodeNumInsArray(control->GetBitField()); return predecessors.size() >= numsInList[0]; } -bool StubOPtimizerLabelImplement::IsLoopHead() const +bool StubOptimizerLabelImpl::IsLoopHead() const { return env_->GetCircuit().IsLoopHead(predeControl_); } diff --git a/ecmascript/compiler/stub_optimizer.h b/ecmascript/compiler/stub_optimizer.h index cedc09c784..3889f40e3d 100644 --- a/ecmascript/compiler/stub_optimizer.h +++ b/ecmascript/compiler/stub_optimizer.h @@ -36,25 +36,25 @@ class CallerDescriptor; class StubOptimizerLabel { public: - class StubOptimizerLabelImplement { + class StubOptimizerLabelImpl { public: - StubOptimizerLabelImplement(Environment *env, AddrShift control) + StubOptimizerLabelImpl(Environment *env, AddrShift control) : env_(env), control_(control), predeControl_(-1), isSealed_(false) { } - ~StubOptimizerLabelImplement() = default; + ~StubOptimizerLabelImpl() = default; - NO_MOVE_SEMANTIC(StubOptimizerLabelImplement); - NO_COPY_SEMANTIC(StubOptimizerLabelImplement); + NO_MOVE_SEMANTIC(StubOptimizerLabelImpl); + NO_COPY_SEMANTIC(StubOptimizerLabelImpl); 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 AppendPredecessor(StubOptimizerLabelImpl *predecessor); + std::vector GetPredecessors() const { return predecessors; } @@ -99,12 +99,12 @@ public: bool isSealed_; std::map valueMap_; std::vector phi; - std::vector predecessors; + std::vector predecessors; std::map incompletePhis_; }; explicit StubOptimizerLabel() = default; explicit StubOptimizerLabel(Environment *env); - explicit StubOptimizerLabel(StubOptimizerLabelImplement *impl) : impl_(impl) {} + explicit StubOptimizerLabel(StubOptimizerLabelImpl *impl) : impl_(impl) {} ~StubOptimizerLabel() = default; using Variable = StubVariable; StubOptimizerLabel(StubOptimizerLabel const &label) = default; @@ -173,16 +173,16 @@ public: private: friend class Environment; - StubOptimizerLabelImplement *GetRawLabel() const + StubOptimizerLabelImpl *GetRawLabel() const { return impl_; } - StubOptimizerLabelImplement *impl_{nullptr}; + StubOptimizerLabelImpl *impl_ {nullptr}; }; class Environment { public: - using StubOptimizerLabelImplement = StubOptimizerLabel::StubOptimizerLabelImplement; + using StubOptimizerLabelImpl = StubOptimizerLabel::StubOptimizerLabelImpl; Environment(const char *name, size_t arguments); ~Environment(); Environment(Environment const &env); // copy constructor @@ -212,7 +212,7 @@ public: StubOptimizerLabel GetLabelFromSelector(AddrShift sel) { - StubOptimizerLabelImplement *rawlabel = phi_to_labels[sel]; + StubOptimizerLabelImpl *rawlabel = phi_to_labels[sel]; return StubOptimizerLabel(rawlabel); } @@ -221,22 +221,22 @@ public: phi_to_labels[sel] = label.GetRawLabel(); } - StubOptimizerLabelImplement *NewStubOptimizerLabel(Environment *env, AddrShift control = -1) + StubOptimizerLabelImpl *NewStubOptimizerLabel(Environment *env, AddrShift control = -1) { - auto impl = new StubOptimizerLabelImplement(env, control); + auto impl = new StubOptimizerLabelImpl(env, control); rawlabels_.push_back(impl); return impl; } private: - StubOptimizerLabel *currentLabel_{nullptr}; + StubOptimizerLabel *currentLabel_ {nullptr}; Circuit circuit_; CircuitBuilder builder_; - std::map phi_to_labels; + std::map phi_to_labels; std::vector arguments_; std::string method_name_; StubOptimizerLabel entry_; - std::vector rawlabels_; + std::vector rawlabels_; }; class StubVariable { @@ -300,7 +300,7 @@ public: private: uint32_t id_; MachineType type_; - AddrShift currentValue_{0}; + AddrShift currentValue_ {0}; Environment *env_; }; @@ -888,22 +888,25 @@ public: return Load(MachineType::UINT64_TYPE, object, elementsOffset); } + AddrShift GetLengthofElements(AddrShift elements) + { + return Load(UINT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); + } + // object operation AddrShift LoadHClass(AddrShift object) { return ChangeInt32ToPointer(Load(UINT32_TYPE, object)); } - AddrShift GetObjectType(AddrShift object) + AddrShift GetObjectType(AddrShift hclass) { - AddrShift hclass = LoadHClass(object); AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); AddrShift bitfield = Load(INT64_TYPE, hclass, bitfieldOffset); return ChangeInt64ToInt32( - Word64And(Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::ExtensibleBit::START_BIT)), - GetWord64Constant((1LLU << panda::ecmascript::JSHClass::ExtensibleBit::SIZE) - 1))); + Word64And(bitfield, GetWord64Constant((1LLU << panda::ecmascript::JSHClass::ObjectTypeBits::SIZE) - 1))); } AddrShift IsDictionaryMode(AddrShift object) @@ -913,6 +916,19 @@ public: GetInteger32Constant(0)); } + AddrShift IsDictionaryElement(AddrShift hclass) + { + AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET); + + AddrShift bitfield = Load(INT64_TYPE, hclass, bitfieldOffset); + // decode + return Word64NotEqual( + Word64And( + Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::DictionaryElementBits::START_BIT)), + GetWord64Constant((1LLU << panda::ecmascript::JSHClass::DictionaryElementBits::SIZE) - 1)), + GetWord64Constant(0)); + } + AddrShift IsExtensible(AddrShift object) { AddrShift hclass = LoadHClass(object); @@ -928,7 +944,7 @@ public: AddrShift IsJsProxy(AddrShift obj) { - AddrShift objectType = GetObjectType(obj); + AddrShift objectType = GetObjectType(LoadHClass(obj)); return Word32Equal(objectType, GetInteger32Constant(static_cast(panda::ecmascript::JSType::JS_PROXY))); } @@ -997,7 +1013,7 @@ public: panda::ecmascript::JSHClass::ElementRepresentationBits::START_BIT)))); } - void UpdateValueAndDetails(AddrShift elements, AddrShift index, AddrShift value, AddrShift attr) + void UpdateValueAndAttributes(AddrShift elements, AddrShift index, AddrShift value, AddrShift attr) { AddrShift arrayIndex = Int32Add(GetInteger32Constant(panda::ecmascript::NameDictionary::TABLE_HEADER_SIZE), @@ -1010,11 +1026,23 @@ public: StoreElement(elements, attributesIndex, IntBuildTagged(attr)); } + AddrShift IsSpecialIndexedObj(AddrShift jsType) + { + return Int32GreaterThan(jsType, + GetInteger32Constant(static_cast(panda::ecmascript::JSType::JS_ARRAY))); + } + + AddrShift IsAccessorInternal(AddrShift value) + { + return Word32Equal(GetObjectType(LoadHClass(value)), + GetInteger32Constant(static_cast(panda::ecmascript::JSType::INTERNAL_ACCESSOR))); + } + void UpdateAndStoreRepresention(AddrShift hclass, AddrShift value, Label *next); AddrShift UpdateRepresention(AddrShift oldRep, AddrShift value, Label *next); - AddrShift GetDetailsFromDictionary(AddrShift elements, AddrShift entry) + AddrShift GetAttributesFromDictionary(AddrShift elements, AddrShift entry) { AddrShift arrayIndex = Int32Add(GetInteger32Constant(panda::ecmascript::NumberDictionary::TABLE_HEADER_SIZE), @@ -1114,7 +1142,7 @@ public: private: Environment *env_; - uint32_t varibial_id_{0}; + uint32_t varibial_id_ {0}; }; } // namespace kungfu #endif // ECMASCRIPT_COMPILER_STUBOPTIMIZER_H diff --git a/ecmascript/compiler/tests/BUILD.gn b/ecmascript/compiler/tests/BUILD.gn index 4c5845aa30..e75c82eeab 100644 --- a/ecmascript/compiler/tests/BUILD.gn +++ b/ecmascript/compiler/tests/BUILD.gn @@ -156,15 +156,15 @@ host_unittest_action("StubOptimizerTest") { "LLVMTransformUtils", "LLVMAArch64Utils", "LLVMARMUtils", - "LLVMX86Utils", + #"LLVMX86Utils", "LLVMIRReader", ] deps = [ "$ark_root/libpandabase:libarkbase", "$ark_root/runtime:libarkruntime", - "//ark/js_runtime:libark_jsruntime_test", - "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer(${host_toolchain})", + "//ark/js_runtime/ecmascript/compiler:libark_jsoptimizer", + "//third_party/googletest:gtest_main", sdk_libc_secshared_dep, ] } diff --git a/ecmascript/compiler/tests/stub_optimizer_tests.cpp b/ecmascript/compiler/tests/stub_optimizer_tests.cpp index 165e90c9a1..72b51cc820 100644 --- a/ecmascript/compiler/tests/stub_optimizer_tests.cpp +++ b/ecmascript/compiler/tests/stub_optimizer_tests.cpp @@ -14,13 +14,14 @@ */ #include -#include +#include #include #include "gtest/gtest.h" #include "ecmascript/compiler/fastpath_optimizer.h" #include "ecmascript/compiler/llvm_ir_builder.h" #include "ecmascript/compiler/llvm_mcjit_compiler.h" +#include "ecmascript/compiler/llvm_stackmap_parse.h" #include "ecmascript/compiler/scheduler.h" #include "ecmascript/compiler/stub_interface.h" #include "ecmascript/ecma_vm.h" @@ -29,8 +30,13 @@ #include "ecmascript/message_string.h" #include "ecmascript/tests/test_helper.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/IRReader/IRReader.h" #include "llvm/IR/Instructions.h" #include "llvm/Support/Host.h" +#include "ecmascript/compiler/llvm_stackmap_parse.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/IRReader/IRReader.h" namespace panda::test { using namespace panda::coretypes; @@ -49,9 +55,14 @@ public: TestHelper::DestroyEcmaVMWithScope(instance, scope); } - PandaVM *instance{nullptr}; - EcmaHandleScope *scope{nullptr}; - JSThread *thread{nullptr}; + JSTaggedValue FastMul2(JSTaggedValue x, JSTaggedValue y) + { + return FastRuntimeStub::FastMul(x, y); + } + + PandaVM *instance {nullptr}; + EcmaHandleScope *scope {nullptr}; + JSThread *thread {nullptr}; }; HWTEST_F_L0(StubOptimizerTest, FastLoadElement) @@ -170,7 +181,7 @@ HWTEST_F_L0(StubOptimizerTest, PhiGateTest) class StubCallPhiOptimizer : public StubOptimizer { public: explicit StubCallPhiOptimizer(Environment *env) - : StubOptimizer(env), phi_descriptor_(0, 1, DEFAULT_ORDER, MachineType::INT32_TYPE) + : StubOptimizer(env), phi_descriptor_("phi", 0, 1, DEFAULT_ORDER, MachineType::INT32_TYPE) { std::array *params = new std::array(); (*params)[0] = MachineType::INT32_TYPE; @@ -204,9 +215,11 @@ HWTEST_F_L0(StubOptimizerTest, CallPhiGateTest) FastStubs::GetInstance().SetFastStub(0, reinterpret_cast(function)); LLVMValueRef barfunction = LLVMAddFunction(module, "CallPhiGateTest_bar", LLVMFunctionType(LLVMInt32Type(), barParamTys, 1, 0)); + Environment env("PhiTest", 1); StubPhiOptimizer optimizer(&env); optimizer.GenerateCircuit(); + auto netOfGates = env.GetCircuit(); netOfGates.PrintAllGates(); auto cfg = Scheduler::Run(&netOfGates); @@ -388,74 +401,6 @@ HWTEST_F_L0(StubOptimizerTest, LoopTest1) std::cout << "res for loop1(11) = " << std::dec << resInvalid << std::endl; } -class FastAddOptimizer : public StubOptimizer { -public: - explicit FastAddOptimizer(Environment *env) : StubOptimizer(env) {} - ~FastAddOptimizer() = default; - NO_MOVE_SEMANTIC(FastAddOptimizer); - NO_COPY_SEMANTIC(FastAddOptimizer); - void GenerateCircuit() override - { - auto env = GetEnvironment(); - AddrShift x = Int64Argument(0); - AddrShift y = Int64Argument(1); - DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); - DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); - StubOptimizerLabel ifTrue1(env); - StubOptimizerLabel ifTrue2(env); - StubOptimizerLabel ifFalse1(env); - StubOptimizerLabel ifFalse2(env); - StubOptimizerLabel ifTrue3(env); - StubOptimizerLabel ifTrue4(env); - StubOptimizerLabel ifTrue5(env); - StubOptimizerLabel ifFalse3(env); - StubOptimizerLabel ifFalse4(env); - StubOptimizerLabel ifFalse5(env); - StubOptimizerLabel next1(env); - StubOptimizerLabel next2(env); - StubOptimizerLabel next3(env); - // if x is number - Branch(TaggedIsNumber(x), &ifTrue1, &ifFalse1); - Bind(&ifTrue1); - // if y is number - Branch(TaggedIsNumber(y), &ifTrue2, &ifFalse2); - Bind(&ifTrue2); - Branch(TaggedIsInt(x), &ifTrue3, &ifFalse3); - Bind(&ifTrue3); - AddrShift intX = TaggedCastToInt32(x); - Branch(TaggedIsInt(y), &ifTrue4, &ifFalse4); - Bind(&ifTrue4); - AddrShift intY = TaggedCastToInt32(y); - intX = Int32Add(intX, intY); - Jump(&next3); - Bind(&ifFalse4); - doubleY = TaggedCastToDouble(y); - doubleX = CastInt32ToFloat64(intX); - Jump(&next2); - Bind(&ifFalse3); - doubleX = TaggedCastToDouble(x); - Branch(TaggedIsInt(y), &ifTrue5, &ifFalse5); - Bind(&ifTrue5); - intY = TaggedCastToInt32(y); - doubleY = CastInt32ToFloat64(intY); - Jump(&next2); - Bind(&ifFalse5); - doubleY = TaggedCastToDouble(y); - Jump(&next2); - Bind(&ifFalse2); - Jump(&next1); - Bind(&ifFalse1); - Jump(&next1); - Bind(&next1); - Return(GetHoleConstant()); - Bind(&next2); - doubleX = DoubleAdd(*doubleX, *doubleY); - Return(DoubleBuildTagged(*doubleX)); - Bind(&next3); - Return(IntBuildTagged(intX)); - } -}; - HWTEST_F_L0(StubOptimizerTest, FastAddTest) { LLVMModuleRef module = LLVMModuleCreateWithName("fast_add_module"); @@ -492,76 +437,13 @@ HWTEST_F_L0(StubOptimizerTest, FastAddTest) std::cout << "res for FastAdd(1, 1) = " << std::dec << resValid.GetNumber() << std::endl; std::cout << "res for FastAdd(2, 2) = " << std::dec << resValid2.GetNumber() << std::endl; std::cout << "res for FastAdd(11, 11) = " << std::dec << resInvalid.GetNumber() << std::endl; + int x1 = 2147483647; + int y1 = 15; + auto resG = fn(JSTaggedValue(x1).GetRawData(), JSTaggedValue(y1).GetRawData()); + auto expectedG = FastRuntimeStub::FastAdd(JSTaggedValue(x1), JSTaggedValue(y1)); + EXPECT_EQ(resG, expectedG); } -class FastSubOptimizer : public StubOptimizer { -public: - explicit FastSubOptimizer(Environment *env) : StubOptimizer(env) {} - ~FastSubOptimizer() = default; - NO_MOVE_SEMANTIC(FastSubOptimizer); - NO_COPY_SEMANTIC(FastSubOptimizer); - void GenerateCircuit() override - { - auto env = GetEnvironment(); - AddrShift x = Int64Argument(0); - AddrShift y = Int64Argument(1); - DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); - DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); - StubOptimizerLabel ifTrue1(env); - StubOptimizerLabel ifTrue2(env); - StubOptimizerLabel ifFalse1(env); - StubOptimizerLabel ifFalse2(env); - StubOptimizerLabel ifTrue3(env); - StubOptimizerLabel ifTrue4(env); - StubOptimizerLabel ifTrue5(env); - StubOptimizerLabel ifFalse3(env); - StubOptimizerLabel ifFalse4(env); - StubOptimizerLabel ifFalse5(env); - StubOptimizerLabel next1(env); - StubOptimizerLabel next2(env); - StubOptimizerLabel next3(env); - // if x is number - Branch(TaggedIsNumber(x), &ifTrue1, &ifFalse1); - Bind(&ifTrue1); - // if y is number - Branch(TaggedIsNumber(y), &ifTrue2, &ifFalse2); - Bind(&ifTrue2); - Branch(TaggedIsInt(x), &ifTrue3, &ifFalse3); - Bind(&ifTrue3); - AddrShift intX = TaggedCastToInt32(x); - Branch(TaggedIsInt(y), &ifTrue4, &ifFalse4); - Bind(&ifTrue4); - AddrShift intY = TaggedCastToInt32(y); - intX = Int32Sub(intX, intY); - Jump(&next3); - Bind(&ifFalse4); - doubleY = TaggedCastToDouble(y); - doubleX = CastInt32ToFloat64(intX); - Jump(&next2); - Bind(&ifFalse3); - doubleX = TaggedCastToDouble(x); - Branch(TaggedIsInt(y), &ifTrue5, &ifFalse5); - Bind(&ifTrue5); - intY = TaggedCastToInt32(y); - doubleY = CastInt32ToFloat64(intY); - Jump(&next2); - Bind(&ifFalse5); - doubleY = TaggedCastToDouble(y); - Jump(&next2); - Bind(&ifFalse2); - Jump(&next1); - Bind(&ifFalse1); - Jump(&next1); - Bind(&next1); - Return(GetHoleConstant()); - Bind(&next2); - doubleX = DoubleSub(*doubleX, *doubleY); - Return(DoubleBuildTagged(*doubleX)); - Bind(&next3); - Return(IntBuildTagged(intX)); - } -}; - HWTEST_F_L0(StubOptimizerTest, FastSubTest) { LLVMModuleRef module = LLVMModuleCreateWithName("fast_sub_module"); @@ -600,74 +482,6 @@ HWTEST_F_L0(StubOptimizerTest, FastSubTest) std::cout << "res for FastSub(11, 11) = " << std::dec << resC.GetNumber() << std::endl; } -class FastMulOptimizer : public StubOptimizer { -public: - explicit FastMulOptimizer(Environment *env) : StubOptimizer(env) {} - ~FastMulOptimizer() = default; - NO_MOVE_SEMANTIC(FastMulOptimizer); - NO_COPY_SEMANTIC(FastMulOptimizer); - void GenerateCircuit() override - { - auto env = GetEnvironment(); - AddrShift x = Int64Argument(0); - AddrShift y = Int64Argument(1); - DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); - DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); - StubOptimizerLabel ifTrue1(env); - StubOptimizerLabel ifTrue2(env); - StubOptimizerLabel ifFalse1(env); - StubOptimizerLabel ifFalse2(env); - StubOptimizerLabel ifTrue3(env); - StubOptimizerLabel ifTrue4(env); - StubOptimizerLabel ifTrue5(env); - StubOptimizerLabel ifFalse3(env); - StubOptimizerLabel ifFalse4(env); - StubOptimizerLabel ifFalse5(env); - StubOptimizerLabel next1(env); - StubOptimizerLabel next2(env); - StubOptimizerLabel next3(env); - // if x is number - Branch(TaggedIsNumber(x), &ifTrue1, &ifFalse1); - Bind(&ifTrue1); - // if y is number - Branch(TaggedIsNumber(y), &ifTrue2, &ifFalse2); - Bind(&ifTrue2); - Branch(TaggedIsInt(x), &ifTrue3, &ifFalse3); - Bind(&ifTrue3); - AddrShift intX = TaggedCastToInt32(x); - Branch(TaggedIsInt(y), &ifTrue4, &ifFalse4); - Bind(&ifTrue4); - AddrShift intY = TaggedCastToInt32(y); - intX = Int32Mul(intX, intY); - Jump(&next3); - Bind(&ifFalse4); - doubleY = TaggedCastToDouble(y); - doubleX = CastInt32ToFloat64(intX); - Jump(&next2); - Bind(&ifFalse3); - doubleX = TaggedCastToDouble(x); - Branch(TaggedIsInt(y), &ifTrue5, &ifFalse5); - Bind(&ifTrue5); - intY = TaggedCastToInt32(y); - doubleY = CastInt32ToFloat64(intY); - Jump(&next2); - Bind(&ifFalse5); - doubleY = TaggedCastToDouble(y); - Jump(&next2); - Bind(&ifFalse2); - Jump(&next1); - Bind(&ifFalse1); - Jump(&next1); - Bind(&next1); - Return(GetHoleConstant()); - Bind(&next2); - doubleX = DoubleMul(*doubleX, *doubleY); - Return(DoubleBuildTagged(*doubleX)); - Bind(&next3); - Return(IntBuildTagged(intX)); - } -}; - HWTEST_F_L0(StubOptimizerTest, FastMulTest) { LLVMModuleRef module = LLVMModuleCreateWithName("fast_mul_module"); @@ -705,89 +519,28 @@ HWTEST_F_L0(StubOptimizerTest, FastMulTest) std::cout << "res for FastMul(-2, 1) = " << std::dec << resA.GetNumber() << std::endl; std::cout << "res for FastMul(-7, -2) = " << std::dec << resB.GetNumber() << std::endl; std::cout << "res for FastMul(11, 11) = " << std::dec << resC.GetNumber() << std::endl; + int x = 7; + double y = 1125899906842624; + auto resD = fn(JSTaggedValue(x).GetRawData(), JSTaggedValue(y).GetRawData()); + JSTaggedValue expectedD = FastRuntimeStub::FastMul(JSTaggedValue(x), JSTaggedValue(y)); + EXPECT_EQ(resD, expectedD); + x = -1; + y = 1.7976931348623157e+308; + auto resE = fn(JSTaggedValue(x).GetRawData(), JSTaggedValue(y).GetRawData()); + JSTaggedValue expectedE = FastRuntimeStub::FastMul(JSTaggedValue(x), JSTaggedValue(y)); + EXPECT_EQ(resE, expectedE); + x = -1; + y = -1 * std::numeric_limits::infinity(); + auto resF = fn(JSTaggedValue(x).GetRawData(), JSTaggedValue(y).GetRawData()); + JSTaggedValue expectedF = FastRuntimeStub::FastMul(JSTaggedValue(x), JSTaggedValue(y)); + EXPECT_EQ(resF, expectedF); + int x1 = 2147483647; + int y1 = 15; + auto resG = fn(JSTaggedValue(x1).GetRawData(), JSTaggedValue(y1).GetRawData()); + auto expectedG = FastRuntimeStub::FastMul(JSTaggedValue(x1), JSTaggedValue(y1)); + EXPECT_EQ(resG, expectedG); } -class FastDivOptimizer : public StubOptimizer { -public: - explicit FastDivOptimizer(Environment *env) : StubOptimizer(env) {} - ~FastDivOptimizer() = default; - NO_MOVE_SEMANTIC(FastDivOptimizer); - NO_COPY_SEMANTIC(FastDivOptimizer); - void GenerateCircuit() override - { - auto env = GetEnvironment(); - AddrShift x = Int64Argument(0); - AddrShift y = Int64Argument(1); - DEFVARIABLE(doubleX, MachineType::FLOAT64_TYPE, 0); - DEFVARIABLE(doubleY, MachineType::FLOAT64_TYPE, 0); - StubOptimizerLabel ifTrue1(env); - StubOptimizerLabel ifTrue2(env); - StubOptimizerLabel ifFalse1(env); - StubOptimizerLabel ifFalse2(env); - StubOptimizerLabel ifTrue3(env); - StubOptimizerLabel ifTrue4(env); - StubOptimizerLabel ifTrue5(env); - StubOptimizerLabel ifTrue6(env); - StubOptimizerLabel ifFalse3(env); - StubOptimizerLabel ifFalse4(env); - StubOptimizerLabel ifFalse5(env); - StubOptimizerLabel ifFalse6(env); - StubOptimizerLabel next1(env); - StubOptimizerLabel next2(env); - StubOptimizerLabel next3(env); - StubOptimizerLabel next4(env); - Branch(TaggedIsNumber(x), &ifTrue1, &ifFalse1); - Bind(&ifTrue1); - // if right.IsNumber() - Branch(TaggedIsNumber(y), &ifTrue2, &ifFalse2); - Bind(&ifTrue2); - Branch(TaggedIsInt(x), &ifTrue3, &ifFalse3); - Bind(&ifTrue3); - AddrShift intX = TaggedCastToInt32(x); - doubleX = CastInt32ToFloat64(intX); - Jump(&next2); - Bind(&ifFalse3); - doubleX = TaggedCastToDouble(x); - Jump(&next2); - Bind(&ifFalse2); - Jump(&next1); - Bind(&ifFalse1); - Jump(&next1); - Bind(&next1); - Return(GetHoleConstant()); - Bind(&next2); - Branch(TaggedIsInt(y), &ifTrue4, &ifFalse4); - Bind(&ifTrue4); - AddrShift intY = TaggedCastToInt32(y); - doubleY = CastInt32ToFloat64(intY); - Jump(&next3); - Bind(&ifFalse4); - doubleY = TaggedCastToDouble(y); - Jump(&next3); - Bind(&next3); - Branch(DoubleEqual(*doubleY, GetDoubleConstant(0.0)), &ifTrue5, &ifFalse5); - Bind(&ifTrue5); - // dLeft == 0.0 || std::isnan(dLeft) - Branch(TruncInt64ToInt1(Word64Or(SExtInt1ToInt64(DoubleEqual(*doubleX, GetDoubleConstant(0.0))), - SExtInt32ToInt64(DoubleIsNAN(*doubleX)))), - &ifTrue6, &ifFalse6); - Bind(&ifTrue6); - Return(DoubleBuildTagged(GetDoubleConstant(base::NAN_VALUE))); - Bind(&ifFalse6); - Jump(&next4); - Bind(&next4); - 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(&ifFalse5); - doubleX = DoubleDiv(*doubleX, *doubleY); - Return(DoubleBuildTagged(*doubleX)); - } -}; - HWTEST_F_L0(StubOptimizerTest, FastDivTest) { LLVMModuleRef module = LLVMModuleCreateWithName("fast_div_module"); @@ -823,162 +576,11 @@ HWTEST_F_L0(StubOptimizerTest, FastDivTest) std::cout << "res for FastDiv(50, 25) = " << res.GetRawData() << std::endl; } -class FastFindOwnElementStub : public StubOptimizer { -public: - explicit FastFindOwnElementStub(Environment *env) : StubOptimizer(env) {} - ~FastFindOwnElementStub() = default; - NO_MOVE_SEMANTIC(FastFindOwnElementStub); - NO_COPY_SEMANTIC(FastFindOwnElementStub); - void GenerateCircuit() override - { - auto env = GetEnvironment(); - AddrShift obj = PtrArgument(0); - AddrShift index = Int32Argument(1); - - StubOptimizerLabel notDict(env); - StubOptimizerLabel lessOrEqual1(env); - StubOptimizerLabel greaterThan1(env); - StubOptimizerLabel isHole1(env); - StubOptimizerLabel isHole2(env); - StubOptimizerLabel isHole3(env); - StubOptimizerLabel notHole1(env); - StubOptimizerLabel notHole2(env); - StubOptimizerLabel notHole3(env); - StubOptimizerLabel isDict(env); - StubOptimizerLabel lessThan(env); - StubOptimizerLabel greaterOrEqual(env); - StubOptimizerLabel greaterThan2(env); - StubOptimizerLabel lessOrEqual2(env); - StubOptimizerLabel isUndef1(env); - StubOptimizerLabel isUndef2(env); - StubOptimizerLabel notUndef1(env); - StubOptimizerLabel notUndef2(env); - StubOptimizerLabel indexIsInt(env); - StubOptimizerLabel indexIsNotInt(env); - StubOptimizerLabel equal1(env); - StubOptimizerLabel equal2(env); - StubOptimizerLabel notEqual1(env); - StubOptimizerLabel notEqual2(env); - StubOptimizerLabel lessThanZero(env); - StubOptimizerLabel greaterOrEqualZero(env); - StubOptimizerLabel greaterThanLength(env); - StubOptimizerLabel elelmentIsInt(env); - StubOptimizerLabel elelmentIsNotInt(env); - StubOptimizerLabel notGreaterThanLength(env); - StubOptimizerLabel next1(env); - AddrShift elements = Load(POINTER_TYPE, obj, GetPtrConstant(JSObject::ELEMENTS_OFFSET)); - - Branch(IsDictionaryMode(elements), &isDict, ¬Dict); - Bind(¬Dict); - AddrShift arrayLength = Load(UINT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); - - Branch(Int32LessThanOrEqual(arrayLength, index), &lessOrEqual1, &greaterThan1); - Bind(&lessOrEqual1); - Jump(&next1); - Bind(&greaterThan1); - AddrShift offset = PtrMul(ChangeInt32ToPointer(index), GetPtrConstant(JSTaggedValue::TaggedTypeSize())); - AddrShift dataIndex = PtrAdd(offset, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); - AddrShift value = Load(TAGGED_TYPE, elements, dataIndex); - - Branch(TaggedIsHole(value), &isHole1, ¬Hole1); - Bind(&isHole1); - Jump(&next1); - Bind(¬Hole1); - Return(value); - Bind(&next1); - Return(GetHoleConstant()); - // IsDictionary - Bind(&isDict); - offset = PtrMul(GetPtrConstant(JSTaggedValue::TaggedTypeSize()), - GetPtrConstant(GetInteger32Constant(panda::ecmascript::NumberDictionary::SIZE_INDEX))); - AddrShift data = Load(POINTER_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); - AddrShift capacity = TaggedCastToInt32(Load(TAGGED_TYPE, data, offset)); - AddrShift count = GetInteger32Constant(1); - AddrShift taggedIndex = IntBuildTagged(index); - // 15 : size of entry - AddrShift entry = Word32And(GetInteger32Constant(15), Int32Sub(capacity, GetInteger32Constant(1))); - AddrShift dictionaryLength = - Load(INT32_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetLengthOffset())); - Label loopHead(env); - Label loopEnd(env); - Label afterLoop(env); - Jump(&loopHead); - LoopBegin(&loopHead); - AddrShift arrayIndex = - Int32Add(GetInteger32Constant(panda::ecmascript::NumberDictionary::TABLE_HEADER_SIZE), - Int32Mul(entry, GetInteger32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE))); - - Branch(Int32LessThan(arrayIndex, GetInteger32Constant(0)), &lessThan, &greaterOrEqual); - Bind(&lessThan); - Return(GetHoleConstant()); - Bind(&greaterOrEqual); - Branch(Int32GreaterThan(arrayIndex, dictionaryLength), &greaterThan2, &lessOrEqual2); - Bind(&greaterThan2); - Return(GetHoleConstant()); - Bind(&lessOrEqual2); - offset = PtrMul(ChangeInt32ToPointer(arrayIndex), GetPtrConstant(JSTaggedValue::TaggedTypeSize())); - data = Load(POINTER_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); - AddrShift element = Load(TAGGED_TYPE, data, offset); - Branch(TaggedIsHole(element), &isHole2, ¬Hole2); - Bind(&isHole2); - Jump(&loopEnd); - // if element is undefined - Bind(¬Hole2); - Branch(TaggedIsUndefined(element), &isUndef1, ¬Undef1); - Bind(&isUndef1); - Return(GetHoleConstant()); - Bind(¬Undef1); - Branch(TaggedIsHole(taggedIndex), &isHole3, ¬Hole3); - Bind(&isHole3); - Jump(&loopEnd); - Bind(¬Hole3); - Branch(TaggedIsUndefined(taggedIndex), &isUndef2, ¬Undef2); - Bind(&isUndef2); - Jump(&loopEnd); - Bind(¬Undef2); - Branch(TaggedIsInt(taggedIndex), &indexIsInt, &indexIsNotInt); - Bind(&indexIsNotInt); - Jump(&loopEnd); - Bind(&indexIsInt); - Branch(TaggedIsInt(element), &elelmentIsInt, &elelmentIsNotInt); - Bind(&elelmentIsNotInt); - Jump(&loopEnd); - Bind(&elelmentIsInt); - Branch(Word32Equal(TaggedCastToInt32(taggedIndex), TaggedCastToInt32(element)), &equal1, ¬Equal1); - Bind(¬Equal1); - Jump(&loopEnd); - Bind(&equal1); - Branch(Word32Equal(entry, GetInteger32Constant(-1)), &equal2, ¬Equal2); - Bind(&equal2); - Return(GetHoleConstant()); - Bind(¬Equal2); - entry = - Int32Add(GetInteger32Constant(panda::ecmascript::NumberDictionary::ENTRY_VALUE_INDEX), - Int32Add(GetInteger32Constant(panda::ecmascript::NumberDictionary::TABLE_HEADER_SIZE), - Int32Mul(entry, GetInteger32Constant(panda::ecmascript::NumberDictionary::ENTRY_SIZE)))); - Branch(Int32LessThan(entry, GetInteger32Constant(0)), &lessThanZero, &greaterOrEqualZero); - Bind(&lessThanZero); - Return(GetUndefinedConstant()); - Bind(&greaterOrEqualZero); - Branch(Int32GreaterThan(entry, dictionaryLength), &greaterThanLength, ¬GreaterThanLength); - Bind(&greaterThanLength); - Return(GetUndefinedConstant()); - Bind(¬GreaterThanLength); - offset = PtrMul(ChangeInt32ToPointer(arrayIndex), GetPtrConstant(JSTaggedValue::TaggedTypeSize())); - data = Load(POINTER_TYPE, elements, GetPtrConstant(panda::coretypes::Array::GetDataOffset())); - Return(Load(TAGGED_TYPE, data, offset)); - Bind(&loopEnd); - entry = Word32And(Int32Add(entry, count), Int32Sub(capacity, GetInteger32Constant(1))); - count = Int32Add(count, GetInteger32Constant(1)); - LoopEnd(&loopHead); - } -}; - HWTEST_F_L0(StubOptimizerTest, FastFindOwnElementStub) { LLVMModuleRef module = static_cast(FastStubs::GetInstance().GetModule()); LLVMValueRef findFunction = LLVMGetNamedFunction(module, "FindOwnElement"); - Environment env("FastFindOwnElementStub", 2); + Environment env("FastFindOwnElementStub", 3); FastFindOwnElementStub optimizer(&env); optimizer.GenerateCircuit(); auto netOfGates = env.GetCircuit(); @@ -996,59 +598,12 @@ HWTEST_F_L0(StubOptimizerTest, FastFindOwnElementStub) LLVMMCJITCompiler compiler(module); compiler.Run(); } -class FastGetElementStub : public StubOptimizer { -public: - explicit FastGetElementStub(Environment *env) - // 2 : parameter number - : StubOptimizer(env), findOwnElementDescriptor(0, 2, DEFAULT_ORDER, MachineType::TAGGED_TYPE) - { - // 2 : 2 means that there are 2 cases in total. - std::array *params = new std::array(); - (*params)[0] = MachineType::POINTER_TYPE; - (*params)[1] = MachineType::UINT32_TYPE; - findOwnElementDescriptor.SetParameters(params->data()); - } - ~FastGetElementStub() = default; - NO_MOVE_SEMANTIC(FastGetElementStub); - NO_COPY_SEMANTIC(FastGetElementStub); - - void GenerateCircuit() override - { - auto env = GetEnvironment(); - AddrShift receiver = Int64Argument(0); - AddrShift index = Int64Argument(1); - StubOptimizerLabel isHole(env); - StubOptimizerLabel notHole(env); - Label loopHead(env); - Label loopEnd(env); - Label afterLoop(env); - Label notHeapObj(env); - - Jump(&loopHead); - LoopBegin(&loopHead); - AddrShift objPtr = ChangeInt64ToPointer(receiver); - AddrShift callFindOwnElementVal = - CallStub(&findOwnElementDescriptor, GetWord64Constant(FAST_STUB_ID(FindOwnElement)), {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); - } - - StubInterfaceDescriptor findOwnElementDescriptor; -}; HWTEST_F_L0(StubOptimizerTest, FastGetElementStub) { LLVMModuleRef module = static_cast(FastStubs::GetInstance().GetModule()); LLVMValueRef findFunction = LLVMGetNamedFunction(module, "FindOwnElement"); - Environment findFuncEnv("FastFindOwnElement_Foo", 2); + Environment findFuncEnv("FastFindOwnElement_Foo", 3); FastFindOwnElementStub findOptimizer(&findFuncEnv); findOptimizer.GenerateCircuit(); auto netOfGates = findFuncEnv.GetCircuit(); @@ -1062,7 +617,7 @@ HWTEST_F_L0(StubOptimizerTest, FastGetElementStub) } LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, module, findFunction); llvmBuilder.Build(); - Environment getFuncEnv("FastGetElement", 2); + Environment getFuncEnv("FastGetElement", 3); FastGetElementStub getOptimizer(&getFuncEnv); getOptimizer.GenerateCircuit(); auto getNetOfGates = getFuncEnv.GetCircuit(); @@ -1080,247 +635,6 @@ HWTEST_F_L0(StubOptimizerTest, FastGetElementStub) compiler.Run(); } -class FastFindOwnElement2Stub : public StubOptimizer { -public: - explicit FastFindOwnElement2Stub(Environment *env) : StubOptimizer(env) {} - ~FastFindOwnElement2Stub() = default; - NO_MOVE_SEMANTIC(FastFindOwnElement2Stub); - NO_COPY_SEMANTIC(FastFindOwnElement2Stub); - void GenerateCircuit() override - { - auto env = GetEnvironment(); - AddrShift thread = PtrArgument(0); - AddrShift elements = PtrArgument(1); - AddrShift index = Int32Argument(2); - AddrShift isDict = Int32Argument(3); - AddrShift attr = PtrArgument(4); - AddrShift indexOrEntry = PtrArgument(5); - 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); - { - Label afterFindElement(env); - AddrShift entry = - FindElementFromNumberDictionary(thread, elements, IntBuildTagged(index), &afterFindElement); - Label notNegtiveOne(env); - Label negtiveOne(env); - Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), ¬NegtiveOne, &negtiveOne); - Bind(¬NegtiveOne); - { - Store(UINT32_TYPE, attr, GetPtrConstant(0), GetDetailsFromDictionary(elements, entry)); - Store(UINT32_TYPE, indexOrEntry, GetPtrConstant(0), entry); - Return(GetValueFromDictionary(elements, entry)); - } - Bind(&negtiveOne); - Jump(&end); - } - Bind(&end); - Return(GetHoleConstant()); - } -}; - -class SetElementStub : public StubOptimizer { -public: - explicit SetElementStub(Environment *env) : StubOptimizer(env) {} - ~SetElementStub() = default; - NO_MOVE_SEMANTIC(SetElementStub); - NO_COPY_SEMANTIC(SetElementStub); - void GenerateCircuit() override - { - 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); - StubInterfaceDescriptor *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); - StubInterfaceDescriptor *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); - Label updateRepLabel(env); - UpdateRepresention(LoadHClass(receiver), value, &updateRepLabel); - Return(TrueConstant()); - } - Bind(&isDict); - { - UpdateValueAndDetails(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); - { - StubInterfaceDescriptor *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 JSObject::Cast(holder)->GetJSHClass()->GetPrototype(); - 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); - { - StubInterfaceDescriptor *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); - { - StubInterfaceDescriptor *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); - } -}; - HWTEST_F_L0(StubOptimizerTest, FastFindOwnElement2Stub) { std::cout << " ------------------------FastFindOwnElement2Stub ---------------------" << std::endl; @@ -1388,24 +702,25 @@ HWTEST_F_L0(StubOptimizerTest, SetElementStub) compiler.Run(); } +#if 0 struct ThreadTy { - intptr_t magic; // 0x11223344 + intptr_t magic; // 0x11223344 intptr_t fp; }; class StubCallRunTimeThreadFpLock { public: - StubCallRunTimeThreadFpLock(struct ThreadTy *thread, intptr_t newFp): oldRbp_(thread->fp), - thread_(thread) + StubCallRunTimeThreadFpLock(struct ThreadTy *thread, intptr_t newFp) : oldRbp_(thread->fp), thread_(thread) { thread_->fp = *(reinterpret_cast(newFp)); std::cout << "StubCallRunTimeThreadFpLock newFp: " << newFp << " oldRbp_ : " << oldRbp_ - << " thread_->fp:" << thread_->fp <fp:" << thread_->fp << std::endl; } ~StubCallRunTimeThreadFpLock() { std::cout << "~StubCallRunTimeThreadFpLock oldRbp_: " << oldRbp_ << " thread_->fp:" << thread_->fp << std::endl; thread_->fp = oldRbp_; } + private: intptr_t oldRbp_; struct ThreadTy *thread_; @@ -1448,7 +763,7 @@ int RuntimeFunc2(struct ThreadTy *fpInfo) StubCallRunTimeThreadFpLock lock(fpInfo, newRbp); auto rbp = reinterpret_cast(fpInfo->fp); - std::cout << " RuntimeFunc2 rbp:" << rbp < elements_t {llvmI64, llvmI64}; LLVMTypeRef threadTy = LLVMStructTypeInContext(context, elements_t.data(), elements_t.size(), 0); LLVMTypeRef threadTyPtr = LLVMPointerType(threadTy, 0); - LLVMTypeRef paramTys0[] = { - threadTyPtr - }; + LLVMTypeRef paramTys0[] = {threadTyPtr}; /* implement stub1 */ LLVMValueRef stub1 = LLVMAddFunction(module, "stub1", LLVMFunctionType(LLVMInt64Type(), paramTys0, 1, 0)); LLVMAddTargetDependentFunctionAttr(stub1, "frame-pointer", "all"); @@ -1642,7 +955,7 @@ HWTEST_F_L0(StubOptimizerTest, JSEntryTest) retVal = LLVMConstInt(LLVMInt64Type(), 3, false); LLVMBuildRet(builder, retVal); LLVMDumpModule(module); - char* error = nullptr; + char *error = nullptr; LLVMVerifyModule(module, LLVMAbortProcessAction, &error); LLVMMCJITCompiler compiler(module); @@ -1651,9 +964,7 @@ HWTEST_F_L0(StubOptimizerTest, JSEntryTest) uint64_t stub1Code = LLVMGetFunctionAddress(engine, "stub1"); uint64_t stub2Code = LLVMGetFunctionAddress(engine, "stub2"); uint64_t stub3Code = LLVMGetFunctionAddress(engine, "stub3"); - std::map addr2name = { - {stub1Code, "stub1"}, {stub2Code, "stub2"}, {stub3Code, "stub3"} - }; + std::map addr2name = {{stub1Code, "stub1"}, {stub2Code, "stub2"}, {stub3Code, "stub3"}}; std::cout << std::endl << " stub1Code : " << stub1Code << std::endl; std::cout << std::endl << " stub2Code : " << stub2Code << std::endl; std::cout << std::endl << " stub3Code : " << stub3Code << std::endl; @@ -1662,8 +973,8 @@ HWTEST_F_L0(StubOptimizerTest, JSEntryTest) auto stub1Func = reinterpret_cast(stub1Code); g_stub2Func = reinterpret_cast(stub2Code); int64_t result = stub1Func(¶meters); - std::cout << std::endl << "parameters magic:" << parameters.magic - << " parameters.fp " << parameters.fp << std::endl; + std::cout << std::endl + << "parameters magic:" << parameters.magic << " parameters.fp " << parameters.fp << std::endl; EXPECT_EQ(parameters.fp, 0x0); EXPECT_EQ(result, 1); std::cout << " ++++++++++ JSEntryTest +++++++++++++ " << std::endl; @@ -1718,7 +1029,7 @@ HWTEST_F_L0(StubOptimizerTest, Prologue) LLVMBuildRet(builder, retVal); LLVMDumpModule(module); - char* error = nullptr; + char *error = nullptr; LLVMVerifyModule(module, LLVMAbortProcessAction, &error); LLVMMCJITCompiler compiler(module); @@ -1751,9 +1062,7 @@ HWTEST_F_L0(StubOptimizerTest, CEntryFp) std::vector elements_t {llvmI64, llvmI64}; LLVMTypeRef threadTy = LLVMStructTypeInContext(context, elements_t.data(), elements_t.size(), 0); LLVMTypeRef threadTyPtr = LLVMPointerType(threadTy, 0); - LLVMTypeRef paramTys0[] = { - threadTyPtr - }; + LLVMTypeRef paramTys0[] = {threadTyPtr}; /* implement main call RuntimeFunc */ LLVMValueRef func = LLVMAddFunction(module, "main", LLVMFunctionType(LLVMInt64Type(), paramTys0, 1, 0)); LLVMAddTargetDependentFunctionAttr(func, "frame-pointer", "all"); @@ -1799,7 +1108,7 @@ HWTEST_F_L0(StubOptimizerTest, CEntryFp) LLVMBuildRet(builder, retVal); LLVMDumpModule(module); - char* error = nullptr; + char *error = nullptr; LLVMVerifyModule(module, LLVMAbortProcessAction, &error); LLVMMCJITCompiler compiler(module); @@ -1833,18 +1142,16 @@ HWTEST_F_L0(StubOptimizerTest, LoadGCIRTest) llvm::LLVMContext context; llvm::StringRef inputFilename(resolvedPath); // Load the input module... - std::unique_ptr rawModule = - parseIRFile(inputFilename, err, context); + std::unique_ptr rawModule = parseIRFile(inputFilename, err, context); if (!rawModule) { std::cout << "parseIRFile :" << inputFilename.data() << " failed !" << std::endl; return; } - LLVMModuleRef module = LLVMCloneModule(wrap(rawModule.get())); + LLVMModuleRef module = LLVMCloneModule(wrap(rawModule.get())); LLVMMCJITCompiler compiler(module); compiler.Run(); auto engine = compiler.GetEngine(); - LLVMValueRef function = - LLVMGetNamedFunction(module, "main"); + LLVMValueRef function = LLVMGetNamedFunction(module, "main"); LLVMDumpValue(function); auto *mainPtr = reinterpret_cast(LLVMGetPointerToGlobal(engine, function)); @@ -1857,13 +1164,14 @@ HWTEST_F_L0(StubOptimizerTest, LoadGCIRTest) int value = reinterpret_cast(mainPtr)(); std::cout << " value:" << value << std::endl; } +#endif extern "C" { void DoSafepoint() { uintptr_t *rbp; - asm("mov %%rbp, %0" : "=rm" (rbp)); + asm("mov %%rbp, %0" : "=rm"(rbp)); for (int i = 0; i < 3; i++) { - uintptr_t returnAddr = *(rbp + 1); + uintptr_t returnAddr = *(rbp + 1); uintptr_t *rsp = rbp + 2; rbp = reinterpret_cast(*rbp); DwarfRegAndOffsetType info; @@ -1872,7 +1180,7 @@ void DoSafepoint() uintptr_t **address = nullptr; if (info.first == 7) { address = reinterpret_cast(reinterpret_cast(rsp) + info.second); - // rbp + // rbp } else if (info.first == 6) { address = reinterpret_cast(reinterpret_cast(rbp) + info.second); } @@ -1882,9 +1190,129 @@ void DoSafepoint() } std::cout << std::endl << std::endl; std::cout << std::hex << "+++++++++++++++++++ returnAddr : 0x" << returnAddr << " rbp:" << rbp - << " rsp: " << rsp << std::endl; + << " rsp: " << rsp << std::endl; } std::cout << "do_safepoint +++ " << std::endl; } } + +class GetPropertyByIndexStub : public StubOptimizer { +public: + explicit GetPropertyByIndexStub(Environment *env) : StubOptimizer(env) {} + ~GetPropertyByIndexStub() = default; + NO_MOVE_SEMANTIC(GetPropertyByIndexStub); + NO_COPY_SEMANTIC(GetPropertyByIndexStub); + void GenerateCircuit() override + { + auto env = GetEnvironment(); + AddrShift thread = PtrArgument(0); + AddrShift receiver = PtrArgument(1); + AddrShift index = Int32Argument(2); /* 2 : 3rd paramter is index */ + + DEFVARIABLE(holder, MachineType::TAGGED_POINTER_TYPE, receiver); + Label loopHead(env); + Label loopEnd(env); + Label loopExit(env); + Label afterLoop(env); + Jump(&loopHead); + LoopBegin(&loopHead); + { + AddrShift hclass = LoadHClass(*holder); + AddrShift jsType = GetObjectType(hclass); + Label isSpecialIndexed(env); + Label notSpecialIndexed(env); + Label loopEnd(env); + Branch(IsSpecialIndexedObj(jsType), &isSpecialIndexed, ¬SpecialIndexed); + Bind(&isSpecialIndexed); + { + Return(GetHoleConstant()); + } + Bind(¬SpecialIndexed); + { + AddrShift elements = GetElements(*holder); + Label isDictionaryElement(env); + Label notDictionaryElement(env); + Branch(IsDictionaryElement(hclass), &isDictionaryElement, ¬DictionaryElement); + Bind(¬DictionaryElement); + { + Label lessThanLength(env); + Label notLessThanLength(env); + Branch(Word32LessThan(index, GetLengthofElements(elements)), &lessThanLength, ¬LessThanLength); + Bind(&lessThanLength); + { + Label notHole(env); + Label isHole(env); + AddrShift value = GetValueFromTaggedArray(elements, index); + Branch(TaggedIsNotHole(value), ¬Hole, &isHole); + Bind(¬Hole); + { + Return(value); + } + Bind(&isHole); + { + Jump(&loopExit); + } + } + Bind(¬LessThanLength); + { + Return(GetHoleConstant()); + } + } + Bind(&isDictionaryElement); + { + Label afterFindElement(env); + AddrShift entry = + FindElementFromNumberDictionary(thread, elements, IntBuildTagged(index), &afterFindElement); + Label notNegtiveOne(env); + Label negtiveOne(env); + Branch(Word32NotEqual(entry, GetInteger32Constant(-1)), ¬NegtiveOne, &negtiveOne); + Bind(¬NegtiveOne); + { + AddrShift attr = GetAttributesFromDictionary(elements, entry); + AddrShift value = GetValueFromDictionary(elements, entry); + Label isAccessor(env); + Label notAccessor(env); + Branch(IsAcesscor(attr), &isAccessor, ¬Accessor); + Bind(&isAccessor); + { + Label isInternal(env); + Label notInternal(env); + Branch(IsAccessorInternal(value), &isInternal, ¬Internal); + Bind(&isInternal); + { + StubInterfaceDescriptor *callAccessorGetter = GET_STUBDESCRIPTOR(AccessorGetter); + Return(CallRuntime(callAccessorGetter, thread, + GetWord64Constant(FAST_STUB_ID(AccessorGetter)), + {thread, *holder, value})); + } + Bind(¬Internal); + { + StubInterfaceDescriptor *callGetter = GET_STUBDESCRIPTOR(CallGetter); + Return(CallRuntime(callGetter, thread, GetWord64Constant(FAST_STUB_ID(CallGetter)), + {thread, receiver, value})); + } + } + Bind(¬Accessor); + { + Return(value); + } + } + Bind(&negtiveOne); + Jump(&loopExit); + } + Bind(&loopExit); + { + holder = GetPrototypeFromHClass(LoadHClass(*holder)); + Branch(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop); + } + } + Bind(&loopEnd); + LoopEnd(&loopHead); + Bind(&afterLoop); + { + Return(GetUndefinedConstant()); + } + } + } +}; } // namespace panda::test diff --git a/ecmascript/compiler/verifier.cpp b/ecmascript/compiler/verifier.cpp index ef13d9f3fe..fd5b206fe8 100644 --- a/ecmascript/compiler/verifier.cpp +++ b/ecmascript/compiler/verifier.cpp @@ -16,6 +16,7 @@ #include "ecmascript/compiler/verifier.h" #include +#include #include "ecmascript/compiler/scheduler.h" diff --git a/ecmascript/compiler/verifier.h b/ecmascript/compiler/verifier.h index 2c23be63cf..ca8036ce22 100644 --- a/ecmascript/compiler/verifier.h +++ b/ecmascript/compiler/verifier.h @@ -30,23 +30,24 @@ public: static bool RunDataIntegrityCheck(const Circuit *circuit); static bool RunStateGatesCheck(const Circuit *circuit, const std::vector &bbGatesList); static bool RunCFGSoundnessCheck(const Circuit *circuit, const std::vector &bbGatesList, - const std::unordered_map &bbGatesAddrToIdx); + const std::unordered_map &bbGatesAddrToIdx); static bool RunCFGIsDAGCheck(const Circuit *circuit); static bool RunCFGReducibilityCheck(const Circuit *circuit, const std::vector &bbGatesList, - const std::unordered_map &bbGatesAddrToIdx, - const std::function &isAncestor); + const std::unordered_map &bbGatesAddrToIdx, + const std::function &isAncestor); static bool RunFixedGatesCheck(const Circuit *circuit, const std::vector &fixedGatesList); static bool RunFixedGatesRelationsCheck(const Circuit *circuit, const std::vector &fixedGatesList, - const std::unordered_map &bbGatesAddrToIdx, - const std::function &isAncestor); + const std::unordered_map &bbGatesAddrToIdx, + const std::function &isAncestor); static bool RunFlowCyclesFind(const Circuit *circuit, std::vector *schedulableGatesListPtr, - const std::vector &bbGatesList, const std::vector &fixedGatesList); + const std::vector &bbGatesList, + const std::vector &fixedGatesList); static bool RunSchedulableGatesCheck(const Circuit *circuit, const std::vector &schedulableGatesList); static bool RunPrologGatesCheck(const Circuit *circuit, const std::vector &schedulableGatesList); static bool RunSchedulingBoundsCheck(const Circuit *circuit, const std::vector &schedulableGatesList, - const std::unordered_map &bbGatesAddrToIdx, - const std::function &isAncestor, - const std::function &lowestCommonAncestor); + const std::unordered_map &bbGatesAddrToIdx, + const std::function &isAncestor, + const std::function &lowestCommonAncestor); static std::vector FindFixedGates(const Circuit *circuit, const std::vector &bbGatesList); static bool Run(const Circuit *circuit); }; diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index f2352867b9..93e94e2c00 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -17,6 +17,7 @@ #include "ecmascript/internal_call_params.h" #include "ecmascript/interpreter/interpreter-inl.h" #include "ecmascript/js_thread.h" +#include "ecmascript/stub_module.h" #include "include/panda_vm.h" namespace panda::ecmascript { @@ -31,7 +32,6 @@ JSThread *JSThread::Create(Runtime *runtime, PandaVM *vm) jsThread->currentFrame_ = jsThread->frameBase_ + MAX_STACK_SIZE; JSThread::SetCurrent(jsThread); EcmaInterpreter::InitStackFrame(jsThread); - return jsThread; } @@ -211,4 +211,15 @@ void JSThread::ResetGuardians() { stableArrayElementsGuardians_ = true; } + +void JSThread::LoadFastStubModule(const char *moduleFile) +{ + StubModule stubModule; + std::string fileName(moduleFile); + stubModule.Load(this, fileName); + for (int i = 0; i < kungfu::FAST_STUB_MAXCOUNT; i++) { + fastStubEntires_[i] = stubModule.GetStubEntry(i); + } + stubCode_ = stubModule.GetCode(); +} } // namespace panda::ecmascript diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index eef175a525..4cdc049d84 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -157,15 +157,23 @@ public: JSTaggedValue GetCurrentLexenv() const; - void SetRuntimeFunction(uint32_t id, uintptr_t functionAddress) + void SetRuntimeFunction(uint32_t id, Address functionAddress) { ASSERT(id < MAX_RUNTIME_FUNCTIONS); - runtimeFunctions[id] = functionAddress; + runtimeFunctions_[id] = functionAddress; } + Address GetFastStubEntry(uint32_t id) + { + ASSERT(id < kungfu::FAST_STUB_MAXCOUNT); + return fastStubEntires_[id]; + } + + void LoadFastStubModule(const char *moduleFile); + static uint32_t GetRuntimeFunctionsOffset() { - return MEMBER_OFFSET(JSThread, runtimeFunctions); + return MEMBER_OFFSET(JSThread, runtimeFunctions_); } static uint64_t GetCurrentFrameOffset() @@ -193,6 +201,9 @@ private: static constexpr uint32_t MAX_RUNTIME_FUNCTIONS = kungfu::EXTERN_RUNTIME_STUB_MAXCOUNT - kungfu::EXTERNAL_RUNTIME_STUB_BEGIN - 1; + Address runtimeFunctions_[MAX_RUNTIME_FUNCTIONS]; + Address fastStubEntires_[kungfu::FAST_STUB_MAXCOUNT]; + JSTaggedValue stubCode_ {JSTaggedValue::Hole()}; EcmaGlobalStorage *globalStorage_ {nullptr}; os::memory::ConditionVariable initializationVar_ GUARDED_BY(initializationLock_); @@ -210,7 +221,6 @@ private: JSTaggedValue exception_ {JSTaggedValue::Hole()}; bool stableArrayElementsGuardians_ {true}; GlobalEnvConstants globalConst_; // Place-Holder - Address runtimeFunctions[MAX_RUNTIME_FUNCTIONS]; InternalCallParams *internalCallParams_ {nullptr}; friend class EcmaHandleScope; diff --git a/ecmascript/runtime_trampolines.cpp b/ecmascript/runtime_trampolines.cpp index 1df5a19818..3608d39e5a 100644 --- a/ecmascript/runtime_trampolines.cpp +++ b/ecmascript/runtime_trampolines.cpp @@ -33,8 +33,8 @@ bool RuntimeTrampolines::AddElementInternal(uint64_t argThread, uint64_t argRece return JSObject::AddElementInternal(thread, receiver, argIndex, value, attr); } -bool RuntimeTrampolines::CallSetter(uint64_t argThread, uint64_t argSetter, uint64_t argReceiver, - uint64_t argValue, bool argMayThrow) +bool RuntimeTrampolines::CallSetter(uint64_t argThread, uint64_t argSetter, uint64_t argReceiver, uint64_t argValue, + bool argMayThrow) { auto thread = reinterpret_cast(argThread); [[maybe_unused]] EcmaHandleScope handleScope(thread); @@ -54,8 +54,8 @@ void RuntimeTrampolines::ThrowTypeError(uint64_t argThread, int argMessageString THROW_NEW_ERROR_AND_RETURN(thread, error.GetTaggedValue()); } -bool RuntimeTrampolines::JSProxySetProperty(uint64_t argThread, uint64_t argProxy, uint64_t argKey, - uint64_t argValue, uint64_t argReceiver, bool argMayThrow) +bool RuntimeTrampolines::JSProxySetProperty(uint64_t argThread, uint64_t argProxy, uint64_t argKey, uint64_t argValue, + uint64_t argReceiver, bool argMayThrow) { auto thread = reinterpret_cast(argThread); [[maybe_unused]] EcmaHandleScope handleScope(thread); @@ -72,4 +72,20 @@ uint32_t RuntimeTrampolines::GetHash32(uint64_t key, uint64_t len) auto pkey = reinterpret_cast(key); return panda::GetHash32(pkey, static_cast(len)); } + +uint64_t RuntimeTrampolines::CallGetter(uint64_t argThread, uint64_t argGetter, uint64_t argReceiver) +{ + auto thread = reinterpret_cast(argThread); + auto accessor = AccessorData::Cast(reinterpret_cast(argGetter)); + JSHandle objHandle(thread, JSTaggedValue(reinterpret_cast(argReceiver))); + return JSObject::CallGetter(thread, accessor, objHandle).GetRawData(); +} + +uint64_t RuntimeTrampolines::AccessorGetter(uint64_t argThread, uint64_t argGetter, uint64_t argReceiver) +{ + auto thread = reinterpret_cast(argThread); + auto accessor = AccessorData::Cast(reinterpret_cast(argGetter)); + JSHandle objHandle(thread, JSTaggedValue(reinterpret_cast(argReceiver))); + return accessor->CallInternalGet(thread, objHandle).GetRawData(); +} } // namespace panda::ecmascript diff --git a/ecmascript/runtime_trampolines.h b/ecmascript/runtime_trampolines.h index e63f3469ad..0881006e5b 100644 --- a/ecmascript/runtime_trampolines.h +++ b/ecmascript/runtime_trampolines.h @@ -40,6 +40,8 @@ public: uint64_t argValue, uint32_t argAttr); static bool CallSetter(uint64_t argThread, uint64_t argSetter, uint64_t argReceiver, uint64_t argValue, bool argMayThrow); + static uint64_t CallGetter(uint64_t argThread, uint64_t argGetter, uint64_t argReceiver); + static uint64_t AccessorGetter(uint64_t argThread, uint64_t argGetter, uint64_t argReceiver); static void ThrowTypeError(uint64_t argThread, int argMessageStringId); static bool JSProxySetProperty(uint64_t argThread, uint64_t argProxy, uint64_t argKey, uint64_t argValue, uint64_t argReceiver, bool argMayThrow); diff --git a/ecmascript/stub_module.cpp b/ecmascript/stub_module.cpp new file mode 100644 index 0000000000..4dee898c4d --- /dev/null +++ b/ecmascript/stub_module.cpp @@ -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. + */ + +#include "stub_module.h" + +namespace panda::ecmascript { +void StubModule::Save(const std::string &filename) +{ + if (code_ != nullptr) { + std::ofstream modulefile(filename.c_str(), std::ofstream::binary); + /* write stub entries offset */ + modulefile.write(reinterpret_cast(fastStubEntries_.data()), + sizeof(uintptr_t) * kungfu::FAST_STUB_MAXCOUNT); + /* write code length & code buff */ + int codeSize = code_->GetInstructionSizeInBytes().GetInt(); + modulefile.write(reinterpret_cast(&codeSize), sizeof(codeSize)); + modulefile.write(reinterpret_cast(code_->GetDataOffsetAddress()), codeSize); + modulefile.close(); + } +} + +void StubModule::Load(JSThread *thread, const std::string &filename) +{ + std::ifstream modulefile(filename.c_str(), std::ofstream::binary); + modulefile.read(reinterpret_cast(fastStubEntries_.data()), sizeof(uintptr_t) * kungfu::FAST_STUB_MAXCOUNT); + int codeSize = 0; + modulefile.read(reinterpret_cast(&codeSize), sizeof(codeSize)); + auto factory = thread->GetEcmaVM()->GetFactory(); + auto codeHandle = factory->NewMachineCodeObject(codeSize, nullptr); + modulefile.read(reinterpret_cast(codeHandle->GetDataOffsetAddress()), codeSize); + SetCode(*codeHandle); + modulefile.close(); +} +} // namespace panda::ecmascript \ No newline at end of file diff --git a/ecmascript/stub_module.h b/ecmascript/stub_module.h new file mode 100644 index 0000000000..98637c153d --- /dev/null +++ b/ecmascript/stub_module.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_STUB_MODULE_H +#define ECMASCRIPT_STUB_MODULE_H + +#include "ecmascript/js_thread.h" +#include "ecmascript/mem/machine_code.h" + +namespace panda::ecmascript { +using Address = uintptr_t; +class StubModule { +public: + Address GetStubEntry(int index) + { + return code_->GetDataOffsetAddress() + fastStubEntries_[index]; + } + void Save(const std::string &filename); + void Load(JSThread *thread, const std::string &filename); + void SetCode(MachineCode *code) + { + code_ = code; + } + void SetStubEntry(int index, Address offset) + { + fastStubEntries_[index] = offset; + } + JSTaggedValue GetCode() + { + return JSTaggedValue(code_); + } + +private: + std::array fastStubEntries_ {-1}; + MachineCode *code_ {nullptr}; +}; +} // namespace panda::ecmascript +#endif // ECMASCRIPT_STUB_MODULE_H \ No newline at end of file diff --git a/test/test_helper.gni b/test/test_helper.gni index 3a709bd090..e5bcb6c0de 100644 --- a/test/test_helper.gni +++ b/test/test_helper.gni @@ -32,7 +32,7 @@ template("host_unittest_action") { ] if (!is_standard_system) { - _deps_ += [ "//ark/runtime/runtime:libarkruntime" ] + _deps_ += [ "$ark_root/runtime/runtime:libarkruntime" ] } # unittest for phone running -- Gitee