From 04399367d6731668ee01849b3c5e49e0b8ebf09b Mon Sep 17 00:00:00 2001 From: Sergey Chernykh Date: Mon, 5 Jun 2023 16:53:11 +0300 Subject: [PATCH] Replace ecma inlining guards from checking functions to checking methods Signed-off-by: Sergey Chernykh --- .../intrinsics_type_resolving_ecmascript.cpp | 12 ++--- .../ir_builder/ecmascript_inst_builder.cpp | 21 +++----- .../optimizer/optimizations/ecma_inlining.cpp | 49 ++++++++++--------- .../optimizer/optimizations/ecma_inlining.h | 4 +- runtime/CMakeLists.txt | 1 + .../compiler/ecmascript_runtime_interface.cpp | 9 ++++ .../compiler/ecmascript_runtime_interface.h | 3 ++ runtime/ecma_call_profiling_table.cpp | 8 +-- runtime/ecma_profiling.cpp | 46 +++++++++++++++++ runtime/ecma_profiling.h | 27 +--------- subproject_sources.gn | 1 + tests/checked/CMakeLists.txt | 2 +- ...s => ecma_inlining_monomorphic_methods.js} | 48 ++++-------------- tests/checked/obj_by_name.js | 18 +++---- tests/checked/obj_by_value.js | 18 +++---- .../compiler/checks_elimination_ecma_test.cpp | 4 +- 16 files changed, 135 insertions(+), 136 deletions(-) create mode 100644 runtime/ecma_profiling.cpp rename tests/checked/{functionimmediate_check.js => ecma_inlining_monomorphic_methods.js} (32%) diff --git a/compiler/intrinsics_type_resolving_ecmascript.cpp b/compiler/intrinsics_type_resolving_ecmascript.cpp index d4dbf82b4..c71a70d59 100644 --- a/compiler/intrinsics_type_resolving_ecmascript.cpp +++ b/compiler/intrinsics_type_resolving_ecmascript.cpp @@ -108,7 +108,7 @@ bool TypesResolving::InlineTypeOf(IntrinsicInst *intrinsic) void TypesResolving::CreateCompareClass(uint32_t pc, Inst *get_cls_inst, RuntimeInterface::ClassPtr receiver, BasicBlock *load_bb) { - auto load_cls_inst = GetGraph()->CreateInstClassImmediate(DataType::REFERENCE, pc, receiver); + auto load_cls_inst = GetGraph()->CreateInstLoadImmediate(DataType::REFERENCE, pc, receiver); auto cmp_inst = GetGraph()->CreateInstCompare(DataType::BOOL, pc, ConditionCode::CC_EQ); auto if_inst = GetGraph()->CreateInstIfImm(DataType::BOOL, pc, ConditionCode::CC_NE, 0); cmp_inst->SetInput(0, load_cls_inst); @@ -116,7 +116,7 @@ void TypesResolving::CreateCompareClass(uint32_t pc, Inst *get_cls_inst, Runtime cmp_inst->SetOperandsType(DataType::REFERENCE); if_inst->SetInput(0, cmp_inst); if_inst->SetOperandsType(DataType::BOOL); - // We insert ClassImmediate in Dominate blockm because VN can be applied + // We insert LoadImmediate in Dominate blockm because VN can be applied get_cls_inst->InsertAfter(load_cls_inst); load_bb->AppendInst(cmp_inst); load_bb->AppendInst(if_inst); @@ -125,7 +125,7 @@ void TypesResolving::CreateCompareClass(uint32_t pc, Inst *get_cls_inst, Runtime Inst *TypesResolving::CreateCompareClassWithDeopt(uint32_t pc, Inst *get_cls_inst, RuntimeInterface::ClassPtr receiver, Inst *save_state) { - auto load_cls_inst = GetGraph()->CreateInstClassImmediate(DataType::REFERENCE, pc, receiver); + auto load_cls_inst = GetGraph()->CreateInstLoadImmediate(DataType::REFERENCE, pc, receiver); auto cmp_inst = GetGraph()->CreateInstCompare(DataType::BOOL, pc, ConditionCode::CC_NE); cmp_inst->SetInput(0, get_cls_inst); cmp_inst->SetInput(1, load_cls_inst); @@ -287,7 +287,7 @@ Inst *InsertChangeClassInst(IntrinsicInst *intrinsic, Inst *obj_inst, Inst *inse auto graph = obj_inst->GetBasicBlock()->GetGraph(); auto pc = obj_inst->GetPc(); auto klass = reinterpret_cast(klass_addr); - auto load_cls_inst = graph->CreateInstClassImmediate(DataType::REFERENCE, pc, klass); + auto load_cls_inst = graph->CreateInstLoadImmediate(DataType::REFERENCE, pc, klass); auto store_class = graph->CreateInstStoreObject(DataType::REFERENCE, pc); store_class->SetMethod(intrinsic->GetSaveState()->GetMethod()); store_class->SetObjField(nullptr); @@ -624,7 +624,7 @@ void TypesResolving::InlineObjByValueFromElements(IntrinsicInst *intrinsic) nullptr, ObjectType::MEM_DYN_CLASS, cast_value, DataType::REFERENCE); // check objects classes with first class from IC - auto load_cls_inst = GetGraph()->CreateInstClassImmediate(DataType::REFERENCE, pc, named_access_profile_[0].klass); + auto load_cls_inst = GetGraph()->CreateInstLoadImmediate(DataType::REFERENCE, pc, named_access_profile_[0].klass); auto cmp_inst = GetGraph()->CreateInstCompare(DataType::BOOL, pc, ConditionCode::CC_NE); cmp_inst->SetInput(0, get_cls_inst); cmp_inst->SetInput(1, load_cls_inst); @@ -635,7 +635,7 @@ void TypesResolving::InlineObjByValueFromElements(IntrinsicInst *intrinsic) if (named_access_profile_.size() == 2) { // check objects classes with second class from IC auto load_cls_inst_1 = - GetGraph()->CreateInstClassImmediate(DataType::REFERENCE, pc, named_access_profile_[1].klass); + GetGraph()->CreateInstLoadImmediate(DataType::REFERENCE, pc, named_access_profile_[1].klass); auto cmp_inst_1 = GetGraph()->CreateInstCompare(DataType::BOOL, pc, ConditionCode::CC_NE); cmp_inst_1->SetInput(0, get_cls_inst); cmp_inst_1->SetInput(1, load_cls_inst_1); diff --git a/compiler/optimizer/ir_builder/ecmascript_inst_builder.cpp b/compiler/optimizer/ir_builder/ecmascript_inst_builder.cpp index ded19ba1d..9bef8f03a 100644 --- a/compiler/optimizer/ir_builder/ecmascript_inst_builder.cpp +++ b/compiler/optimizer/ir_builder/ecmascript_inst_builder.cpp @@ -22,7 +22,6 @@ #include "bytecode_instruction-inl.h" #include "include/coretypes/tagged_value.h" #include "optimizer/ir_builder/pbc_iterator.h" -#include "plugins/ecmascript/runtime/ecma_profiling.h" namespace panda::compiler { void InstBuilder::FinalizeEcmaFnCall(SaveStateInst *save_state, CallInst *call_inst) @@ -280,29 +279,21 @@ void InstBuilder::BuildLdGlobalVar(const BytecodeInstruction *bc_inst, size_t ty void InstBuilder::BuildStObjByIndex(const BytecodeInstruction *bc_inst, uint64_t imm) { auto pc = GetPc(bc_inst->GetAddress()); - auto profile = GetRuntime()->GetBytecodeProfile(method_profile_, bc_inst->GetAddress(), pc); - - auto ecma_prof = reinterpret_cast(profile); - panda::ecmascript::ObjByIndexOperationProfile p(ecma_prof); - if (p.GetOperandType(0).GetType() != panda::ecmascript::ProfilingIndexedAccessBits::OBJECT_ARRAY_ACCESS) { + if (GetRuntime()->CanInlineLdStObjByIndex(bc_inst, pc, method_profile_)) { + BuildLdStObjByIndex(bc_inst, GetDefinition(bc_inst->GetVReg(0)), imm, GetDefinitionAcc()); + } else { BuildEcma(bc_inst); - return; } - BuildLdStObjByIndex(bc_inst, GetDefinition(bc_inst->GetVReg(0)), imm, GetDefinitionAcc()); } void InstBuilder::BuildLdObjByIndex(const BytecodeInstruction *bc_inst, uint64_t imm) { auto pc = GetPc(bc_inst->GetAddress()); - auto profile = GetRuntime()->GetBytecodeProfile(method_profile_, bc_inst->GetAddress(), pc); - - auto ecma_prof = reinterpret_cast(profile); - panda::ecmascript::ObjByIndexOperationProfile p(ecma_prof); - if (p.GetOperandType(0).GetType() != panda::ecmascript::ProfilingIndexedAccessBits::OBJECT_ARRAY_ACCESS) { + if (GetRuntime()->CanInlineLdStObjByIndex(bc_inst, pc, method_profile_)) { + BuildLdStObjByIndex(bc_inst, GetDefinitionAcc(), imm, nullptr); + } else { BuildEcma(bc_inst); - return; } - BuildLdStObjByIndex(bc_inst, GetDefinitionAcc(), imm, nullptr); } void InstBuilder::BuildLdStObjByIndex(const BytecodeInstruction *bc_inst, Inst *obj_inst, uint64_t imm, Inst *store_def) diff --git a/compiler/optimizer/optimizations/ecma_inlining.cpp b/compiler/optimizer/optimizations/ecma_inlining.cpp index 7da0b8a16..d8bf7634f 100644 --- a/compiler/optimizer/optimizations/ecma_inlining.cpp +++ b/compiler/optimizer/optimizations/ecma_inlining.cpp @@ -149,26 +149,25 @@ Graph *EcmaInlining::BuildGraph(InlineContext *ctx, CallInst *call_inst, CallIns return graph_inl; } -void EcmaInlining::BuildGuard(CallInst *call_inst) +void EcmaInlining::BuildGuard(CallInst *call_inst, RuntimeInterface::MethodPtr method_ptr) { - ASSERT(js_functions_.size() == 1U); - auto load_function = GetGraph()->CreateInstFunctionImmediate(DataType::ANY, call_inst->GetPc(), js_functions_[0]); + auto method_cnst = GetGraph()->CreateInstLoadImmediate(DataType::POINTER, call_inst->GetPc(), method_ptr, + LoadImmediateInst::ObjectType::METHOD); + auto load_method = GetGraph()->CreateInstLoadObject(DataType::POINTER, call_inst->GetPc()); + load_method->SetObjectType(ObjectType::MEM_DYN_METHOD); + load_method->SetTypeId(TypeIdMixin::MEM_DYN_METHOD_ID); + load_method->SetInput(0, call_inst->GetInput(0).GetInst()); auto cmp_inst = GetGraph()->CreateInstCompare(DataType::BOOL, call_inst->GetPc()); auto deopt_inst = GetGraph()->CreateInstDeoptimizeIf(DataType::BOOL, call_inst->GetPc()); cmp_inst->SetCc(ConditionCode::CC_NE); - cmp_inst->SetInput(0, load_function); - cmp_inst->SetInput(1, call_inst->GetInput(0).GetInst()); - cmp_inst->SetOperandsType(DataType::ANY); + cmp_inst->SetInput(0, load_method); + cmp_inst->SetInput(1, method_cnst); + cmp_inst->SetOperandsType(DataType::POINTER); deopt_inst->SetInput(0, cmp_inst); deopt_inst->SetInput(1, call_inst->GetSaveState()); deopt_inst->SetDeoptimizeType(DeoptimizeType::INLINE_DYN); - - auto save_state = call_inst->GetSaveState(); - ASSERT(save_state); - save_state->InsertBefore(load_function); - save_state->AppendInput(load_function); - VirtualRegister vreg {VirtualRegister::BRIDGE, VRegType::VREG}; - save_state->SetVirtualRegister(save_state->GetInputsCount() - 1, vreg); + call_inst->InsertBefore(method_cnst); + call_inst->InsertBefore(load_method); call_inst->InsertBefore(cmp_inst); call_inst->InsertBefore(deopt_inst); } @@ -176,7 +175,7 @@ void EcmaInlining::BuildGuard(CallInst *call_inst) void EcmaInlining::InsertGraph(CallInst *call_inst, const InlineContext &ctx, Graph *graph_inl) { if (!IsStaticInlining()) { - BuildGuard(call_inst); + BuildGuard(call_inst, ctx.method); } auto call_bb = call_inst->GetBasicBlock(); @@ -232,18 +231,25 @@ bool EcmaInlining::DoEcmaMonomorphicInilning(CallInst *call_inst, InlineContext return true; } -void EcmaInlining::CreateCompareFunctions(CallInst *call_inst, uintptr_t js_function, BasicBlock *call_bb) +void EcmaInlining::CreateCompareFunctions(CallInst *call_inst, RuntimeInterface::MethodPtr method_ptr, + BasicBlock *call_bb) { - auto load_function_inst = GetGraph()->CreateInstFunctionImmediate(DataType::ANY, call_inst->GetPc(), js_function); + auto method_cnst = GetGraph()->CreateInstLoadImmediate(DataType::POINTER, call_inst->GetPc(), method_ptr, + LoadImmediateInst::ObjectType::METHOD); + auto load_method = GetGraph()->CreateInstLoadObject(DataType::POINTER, call_inst->GetPc()); + load_method->SetObjectType(ObjectType::MEM_DYN_METHOD); + load_method->SetTypeId(TypeIdMixin::MEM_DYN_METHOD_ID); + load_method->SetInput(0, call_inst->GetInput(0).GetInst()); auto cmp_inst = GetGraph()->CreateInstCompare(DataType::BOOL, call_inst->GetPc()); auto if_inst = GetGraph()->CreateInstIfImm(DataType::BOOL, call_inst->GetPc(), ConditionCode::CC_NE, 0); cmp_inst->SetCc(ConditionCode::CC_EQ); - cmp_inst->SetInput(0, load_function_inst); - cmp_inst->SetInput(1, call_inst->GetInput(0).GetInst()); - cmp_inst->SetOperandsType(DataType::ANY); + cmp_inst->SetInput(0, load_method); + cmp_inst->SetInput(1, method_cnst); + cmp_inst->SetOperandsType(DataType::POINTER); if_inst->SetInput(0, cmp_inst); if_inst->SetOperandsType(DataType::BOOL); - call_bb->AppendInst(load_function_inst); + call_bb->AppendInst(method_cnst); + call_bb->AppendInst(load_method); call_bb->AppendInst(cmp_inst); call_bb->AppendInst(if_inst); } @@ -276,7 +282,6 @@ bool EcmaInlining::DoEcmaPolymorphicInilning(CallInst *call_inst) if (graph_inl == nullptr) { continue; } - // vregs_count_ += graph_inl->GetVRegsCount(); if (call_bb == nullptr) { // Split block by call instruction call_bb = call_inst->GetBasicBlock(); @@ -292,7 +297,7 @@ bool EcmaInlining::DoEcmaPolymorphicInilning(CallInst *call_inst) call_bb->AddSucc(new_call_bb); call_bb = new_call_bb; } - CreateCompareFunctions(call_inst, func, call_bb); + CreateCompareFunctions(call_inst, ctx.method, call_bb); // Create call_inlined_block auto call_inlined_block = GetGraph()->CreateEmptyBlock(call_bb); diff --git a/compiler/optimizer/optimizations/ecma_inlining.h b/compiler/optimizer/optimizations/ecma_inlining.h index 077a367ef..67579f4c3 100644 --- a/compiler/optimizer/optimizations/ecma_inlining.h +++ b/compiler/optimizer/optimizations/ecma_inlining.h @@ -46,8 +46,8 @@ private: bool CheckCallKind(CallInst *call_inst); bool CheckMethod(CallInst *call_inst, InlineContext *ctx); Graph *BuildGraph(InlineContext *ctx, CallInst *call_inst, CallInst *new_call_inst = nullptr); - void CreateCompareFunctions(CallInst *call_inst, uintptr_t js_function, BasicBlock *call_bb); - void BuildGuard(CallInst *call_inst); + void CreateCompareFunctions(CallInst *call_inst, RuntimeInterface::MethodPtr method_ptr, BasicBlock *call_bb); + void BuildGuard(CallInst *call_inst, RuntimeInterface::MethodPtr method_ptr); void InsertGraph(CallInst *call_inst, const InlineContext &ctx, Graph *graph_inl); bool IsStaticInlining() const { diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 96b140cab..eded94bc2 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -104,6 +104,7 @@ set(ECMASCRIPT_SOURCES ${ECMA_SRC_DIR}/ecma_exceptions.cpp ${ECMA_SRC_DIR}/ecma_language_context.cpp ${ECMA_SRC_DIR}/ecma_module.cpp + ${ECMA_SRC_DIR}/ecma_profiling.cpp ${ECMA_SRC_DIR}/ecma_string.cpp ${ECMA_SRC_DIR}/ecma_string_table.cpp ${ECMA_SRC_DIR}/ecma_vm.cpp diff --git a/runtime/compiler/ecmascript_runtime_interface.cpp b/runtime/compiler/ecmascript_runtime_interface.cpp index 6871d4ec3..b622b259a 100644 --- a/runtime/compiler/ecmascript_runtime_interface.cpp +++ b/runtime/compiler/ecmascript_runtime_interface.cpp @@ -127,6 +127,15 @@ EcmaRuntimeInterface::BytecodeProfile EcmaRuntimeInterface::GetBytecodeProfile(M return reinterpret_cast(reinterpret_cast(profile) + profile_id); } +bool EcmaRuntimeInterface::CanInlineLdStObjByIndex(const BytecodeInstruction *bc_inst, size_t pc, + MethodProfile method_profile) const +{ + auto profile = GetBytecodeProfile(method_profile, bc_inst->GetAddress(), pc); + auto ecma_prof = reinterpret_cast(profile); + panda::ecmascript::ObjByIndexOperationProfile p(ecma_prof); + return p.GetOperandType(0).GetType() == panda::ecmascript::ProfilingIndexedAccessBits::OBJECT_ARRAY_ACCESS; +} + profiling::CallKind EcmaRuntimeInterface::GetCallProfile(MethodPtr method, uint32_t pc, ArenaVector *methods, bool is_aot) { diff --git a/runtime/compiler/ecmascript_runtime_interface.h b/runtime/compiler/ecmascript_runtime_interface.h index d6fefb599..61648bb49 100644 --- a/runtime/compiler/ecmascript_runtime_interface.h +++ b/runtime/compiler/ecmascript_runtime_interface.h @@ -130,6 +130,9 @@ public: BytecodeProfile GetBytecodeProfile(MethodProfile prof, const uint8_t *bc_inst, size_t pc) const override; + bool CanInlineLdStObjByIndex(const BytecodeInstruction *bc_inst, size_t pc, + MethodProfile method_profile) const override; + profiling::CallKind GetCallProfile(MethodPtr method, uint32_t pc, ArenaVector *methods, bool is_aot) override; diff --git a/runtime/ecma_call_profiling_table.cpp b/runtime/ecma_call_profiling_table.cpp index 6482a8eb6..6dab745e3 100644 --- a/runtime/ecma_call_profiling_table.cpp +++ b/runtime/ecma_call_profiling_table.cpp @@ -28,13 +28,9 @@ EcmaCallProfilingTable::EcmaCallProfilingTable(uint32_t size) call_profiling_bit_map_[0] = true; } -void EcmaCallProfilingTable::ClearObject(uint16_t idx) +void EcmaCallProfilingTable::ClearObject([[maybe_unused]] uint16_t idx) { - ASSERT(idx != 0); - os::memory::LockHolder holder(table_lock_); - LOG(DEBUG, INTERPRETER) << "CallProfileTable: Clear slot " << idx; - call_profiling_table_[idx] = nullptr; - call_profiling_bit_map_[idx] = false; + UNREACHABLE(); } std::optional EcmaCallProfilingTable::InsertNewObject(ECMAObject *js_func) diff --git a/runtime/ecma_profiling.cpp b/runtime/ecma_profiling.cpp new file mode 100644 index 000000000..1ff107338 --- /dev/null +++ b/runtime/ecma_profiling.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021-2022 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 "ecma_profiling.h" +#include "plugins/ecmascript/runtime/js_function.h" + +namespace panda::ecmascript { + +void CallProfile::Update(ECMAObject *js_func, EcmaCallProfilingTable *table) +{ + if (callees_idx_[0] == MEGAMORPHIC) { + return; + } + auto method = JSFunction::Cast(js_func)->GetCallTarget(); + for (size_t i = 0; i < MAX_FUNC_NUMBER; ++i) { + if (callees_idx_[i] == UNKNOWN) { + auto idx = table->InsertNewObject(js_func); + if (idx) { + // Atomic with release order reason: profile data may be updated while the compiler thread loads it + reinterpret_cast *>(&callees_idx_[i])->store(idx.value(), std::memory_order_release); + } + return; + } + ASSERT(callees_idx_[i] > 0 && callees_idx_[i] <= std::numeric_limits::max() - 1U); + if (JSFunction::Cast(table->GetObject(callees_idx_[i]))->GetCallTarget() == method) { + return; + } + } + // TODO(schernykh): Create way for clear call profiling table, and clear it in this place. + // Atomic with release order reason: profile data may be updated while the compiler thread loads it + reinterpret_cast *>(&callees_idx_[0])->store(MEGAMORPHIC, std::memory_order_release); +} + +} // namespace panda::ecmascript diff --git a/runtime/ecma_profiling.h b/runtime/ecma_profiling.h index 56803fd83..7426ac7c1 100644 --- a/runtime/ecma_profiling.h +++ b/runtime/ecma_profiling.h @@ -520,32 +520,7 @@ public: } } - void Update(ECMAObject *js_func, EcmaCallProfilingTable *table) - { - if (callees_idx_[0] == MEGAMORPHIC) { - return; - } - for (size_t i = 0; i < MAX_FUNC_NUMBER; ++i) { - if (callees_idx_[i] == UNKNOWN) { - auto idx = table->InsertNewObject(js_func); - if (idx) { - // Atomic with release order reason: profile data may be updated while the compiler thread loads it - reinterpret_cast *>(&callees_idx_[i]) - ->store(idx.value(), std::memory_order_release); - } - return; - } - ASSERT(callees_idx_[i] > 0 && callees_idx_[i] <= std::numeric_limits::max() - 1U); - if (table->GetObject(callees_idx_[i]) == js_func) { - return; - } - } - for (size_t i = 0; i < MAX_FUNC_NUMBER; ++i) { - table->ClearObject(callees_idx_[i]); - // Atomic with release order reason: profile data may be updated while the compiler thread loads it - reinterpret_cast *>(&callees_idx_[i])->store(MEGAMORPHIC, std::memory_order_release); - } - } + void Update(ECMAObject *js_func, EcmaCallProfilingTable *table); private: std::array callees_idx_ {}; diff --git a/subproject_sources.gn b/subproject_sources.gn index 1c75a77bc..25c1206e2 100644 --- a/subproject_sources.gn +++ b/subproject_sources.gn @@ -133,6 +133,7 @@ srcs_runtime = [ "runtime/ecma_exceptions.cpp", "runtime/ecma_language_context.cpp", "runtime/ecma_module.cpp", + "runtime/ecma_profiling.cpp", "runtime/ecma_string.cpp", "runtime/ecma_string_table.cpp", "runtime/ecma_vm.cpp", diff --git a/tests/checked/CMakeLists.txt b/tests/checked/CMakeLists.txt index 18421ae91..1adfa3e4f 100644 --- a/tests/checked/CMakeLists.txt +++ b/tests/checked/CMakeLists.txt @@ -111,13 +111,13 @@ if (NOT PANDA_TARGET_ARM32) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inlining_megamorphic.js SUPPORT_RELEASE true) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inlining_polymorphic.js SUPPORT_RELEASE true) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inlining_polymorphic_2.js SUPPORT_RELEASE true) + panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inlining_monomorphic_methods.js SUPPORT_RELEASE true) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inlining_monomorphic.js SUPPORT_RELEASE true) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_inlining_static.js SUPPORT_RELEASE true) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ecma_call_profile_clear.js SUPPORT_RELEASE true) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/peephole_negoverflowandzerocheck.js SUPPORT_RELEASE true) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ldlex.js SUPPORT_RELEASE true) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/typeof.js SUPPORT_RELEASE true) - panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/functionimmediate_check.js SUPPORT_RELEASE true) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/string_equals.js SUPPORT_RELEASE true) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/stlex.js SUPPORT_RELEASE true) panda_add_checked_test_ecma(FILE ${CMAKE_CURRENT_SOURCE_DIR}/poplexenv.js SUPPORT_RELEASE true) diff --git a/tests/checked/functionimmediate_check.js b/tests/checked/ecma_inlining_monomorphic_methods.js similarity index 32% rename from tests/checked/functionimmediate_check.js rename to tests/checked/ecma_inlining_monomorphic_methods.js index 8dbe970ba..aba3af0c2 100644 --- a/tests/checked/functionimmediate_check.js +++ b/tests/checked/ecma_inlining_monomorphic_methods.js @@ -13,48 +13,20 @@ * limitations under the License. */ -//! CHECKER Checking LICM for FunctionImmediate. -//! RUN options: "--compiler-enable-jit=true --compiler-hotness-threshold=10 --compiler-profiling-threshold=0 --gc-type=g1-gc --compiler-regex _GLOBAL::test", entry: "_GLOBAL::func_main_0" +//! CHECKER Ecma Inlining. Must inline, monomorphic call by methods. +//! RUN options: "--no-async-jit --compiler-hotness-threshold=5 --compiler-regex _GLOBAL::test", entry: "_GLOBAL::func_main_0" +//! EVENT /Inline,_GLOBAL::test,_GLOBAL::func,.*DYNAMIC_MONOMORPHIC,SUCCESS/ //! EVENT /Compilation,_GLOBAL::test,.*,COMPILED/ -//! EVENT /Inline,_GLOBAL::test,_GLOBAL::bar,.*,SUCCESS/ -//! EVENT_NOT /Deoptimization,_GLOBAL::test/ -//! METHOD "_GLOBAL::func_test_4" -//! PASS_AFTER "ChecksElimination" -//! INST_COUNT "FunctionImmediate",1 -//! IN_BLOCK "loop 1" -//! INST "FunctionImmediate" -//! PASS_AFTER "LICM" -//! INST_COUNT "FunctionImmediate",1 -//! IN_BLOCK "prehead" -//! INST "FunctionImmediate" +//! EVENT_NOT /Deoptimization,_GLOBAL::.*test.*,.*,IFRAME/ -function bar() { return 1; } -function __noinline__add2() { return 2; } -function __noinline__add3() { return 3; } -function test () { - var sum = 0; - for (var i = 0; i < 20; i++) { - sum += __noinline__add2(); - sum += bar(); - let old_addr = getObjectAddress(bar); - let gc = startGC("full"); - waitForFinishGC(gc); - if (old_addr === getObjectAddress(bar)) { - throw "Object must be moved" - } - sum += __noinline__add3(); +function test(foo) { + if (foo() != 0) { + throw "Wrong result"; } - return sum } -RuntimeTesting.PrepareFunctionForOptimization(test); -let sum = test(); -if (sum != 120) { - throw "Wrong result: " + sum; -} -RuntimeTesting.OptimizeFunctionOnNextCall(test); -sum = test(); -if (sum != 120) { - throw "Wrong result: " + sum; +for (let i = 0; i < 10; ++i) { + let func = function() { return 0;} + test(func); } \ No newline at end of file diff --git a/tests/checked/obj_by_name.js b/tests/checked/obj_by_name.js index e9913df18..cf61edbc7 100644 --- a/tests/checked/obj_by_name.js +++ b/tests/checked/obj_by_name.js @@ -20,7 +20,7 @@ //! INST "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE" //! INST_NEXT "CastAnyTypeValue" //! INST_NEXT /LoadObject.*Class/ -//! INST_NEXT "ClassImmediate" +//! INST_NEXT "LoadImmediate" //! INST_NEXT "Compare" //! INST_NEXT "DeoptimizeIf" //! INST_NEXT /StoreObject.*Dynamic/ @@ -33,7 +33,7 @@ //! INST "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE" //! INST_NEXT "CastAnyTypeValue" //! INST_NEXT /LoadObject.*Class/ -//! INST_NEXT "ClassImmediate" +//! INST_NEXT "LoadImmediate" //! INST_NEXT "Compare" //! INST_NEXT "DeoptimizeIf" //! INST_NEXT /LoadObject.*Properties/ @@ -46,10 +46,10 @@ //! INST "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE" //! INST_NEXT "CastAnyTypeValue" //! INST_NEXT /LoadObject.*Class/ -//! INST_NEXT "ClassImmediate" +//! INST_NEXT "LoadImmediate" //! INST_NEXT "Compare" //! INST_NEXT "DeoptimizeIf" -//! INST_NEXT "ClassImmediate" +//! INST_NEXT "LoadImmediate" //! INST_NEXT /StoreObject.*Class/ //! INST_NEXT /StoreObject.*Dynamic/ //! INST_NEXT /LoadObject.*Dynamic/ @@ -61,13 +61,13 @@ //! INST "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE" //! INST_NEXT "CastAnyTypeValue" //! INST_NEXT /LoadObject.*Class/ -//! INST_NEXT "ClassImmediate" +//! INST_NEXT "LoadImmediate" //! INST_NEXT "Compare" //! INST_NEXT "DeoptimizeIf" //! INST_NEXT /LoadObject.*Properties/ //! INST_NEXT "LenArray" //! INST_NEXT "BoundsCheck" -//! INST_NEXT "ClassImmediate" +//! INST_NEXT "LoadImmediate" //! INST_NEXT /StoreObject.*Class/ //! INST_NEXT "StoreArray" //! EVENT /Compilation,_GLOBAL::test_load_store_by_name_single_transition_properties,.*,COMPILED/ @@ -76,7 +76,7 @@ //! INST "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE" //! INST_NEXT "CastAnyTypeValue" //! INST_NEXT /LoadObject.*Class/ -//! INST_NEXT "ClassImmediate" +//! INST_NEXT "LoadImmediate" //! INST_NEXT "Compare" //! INST_NEXT "DeoptimizeIf" //! INST_NEXT "LoadObjFromConst" @@ -90,8 +90,8 @@ //! INST "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE" //! INST_NEXT "CastAnyTypeValue" //! INST_NEXT /LoadObject.*Class/ -//! INST_NEXT "ClassImmediate" -//! INST_NEXT "ClassImmediate" +//! INST_NEXT "LoadImmediate" +//! INST_NEXT "LoadImmediate" //! INST_NEXT "Compare" //! INST_NEXT "IfImm" //! INST_COUNT "LoadObject", 5 diff --git a/tests/checked/obj_by_value.js b/tests/checked/obj_by_value.js index c88222080..e9837bd03 100644 --- a/tests/checked/obj_by_value.js +++ b/tests/checked/obj_by_value.js @@ -20,7 +20,7 @@ //! INST "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE" //! INST_NEXT "CastAnyTypeValue" //! INST_NEXT /LoadObject.*Class/ -//! INST_NEXT "ClassImmediate" +//! INST_NEXT "LoadImmediate" //! INST_NEXT "Compare" //! INST_NEXT "DeoptimizeIf" //! INST_NEXT "AnyTypeCheck ECMASCRIPT_INT_TYPE" @@ -34,7 +34,7 @@ //! INST "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE" //! INST_NEXT "CastAnyTypeValue" //! INST_NEXT /LoadObject.*Class/ -//! INST_NEXT "ClassImmediate" +//! INST_NEXT "LoadImmediate" //! INST_NEXT "Compare" //! INST_NEXT "DeoptimizeIf" //! INST_NEXT "AnyTypeCheck ECMASCRIPT_INT_TYPE" @@ -49,9 +49,9 @@ //! INST "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE" //! INST_NEXT "CastAnyTypeValue" //! INST_NEXT /LoadObject.*Class/ -//! INST_NEXT "ClassImmediate" +//! INST_NEXT "LoadImmediate" //! INST_NEXT "Compare" -//! INST_NEXT "ClassImmediate" +//! INST_NEXT "LoadImmediate" //! INST_NEXT "Compare" //! INST_NEXT "And" //! INST_NEXT "DeoptimizeIf" @@ -66,9 +66,9 @@ //! INST "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE" //! INST_NEXT "CastAnyTypeValue" //! INST_NEXT /LoadObject.*Class/ -//! INST_NEXT "ClassImmediate" +//! INST_NEXT "LoadImmediate" //! INST_NEXT "Compare" -//! INST_NEXT "ClassImmediate" +//! INST_NEXT "LoadImmediate" //! INST_NEXT "Compare" //! INST_NEXT "And" //! INST_NEXT "DeoptimizeIf" @@ -95,7 +95,7 @@ //! INST_NEXT "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE" //! INST_NEXT "CastAnyTypeValue" //! INST_NEXT /LoadObject.*Class/ -//! INST_NEXT "ClassImmediate" +//! INST_NEXT "LoadImmediate" //! INST_NEXT "Compare" //! INST_NEXT "DeoptimizeIf" //! INST_NOT "Intrinsic.StObjByValue" @@ -107,7 +107,7 @@ //! INST_NEXT "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE" //! INST_NEXT "CastAnyTypeValue" //! INST_NEXT /LoadObject.*Class/ -//! INST_NEXT "ClassImmediate" +//! INST_NEXT "LoadImmediate" //! INST_NEXT "Compare" //! INST_NEXT "DeoptimizeIf" //! INST_NOT "Intrinsic.LdObjByValue" @@ -119,7 +119,7 @@ //! INST "AnyTypeCheck ECMASCRIPT_HEAP_OBJECT_TYPE" //! INST_NEXT "CastAnyTypeValue" //! INST_NEXT /LoadObject.*Class/ -//! INST_NEXT "ClassImmediate" +//! INST_NEXT "LoadImmediate" //! INST_NEXT "Compare" //! INST_NEXT "DeoptimizeIf" //! INST_NEXT "AnyTypeCheck ECMASCRIPT_INT_TYPE" diff --git a/tests/compiler/checks_elimination_ecma_test.cpp b/tests/compiler/checks_elimination_ecma_test.cpp index 746cdcabf..6ed25ef58 100644 --- a/tests/compiler/checks_elimination_ecma_test.cpp +++ b/tests/compiler/checks_elimination_ecma_test.cpp @@ -736,8 +736,8 @@ TEST_F(CheckEliminationEcmaTest, EliminateDynamicCallCheckInlined) BASIC_BLOCK(2, -1) { INST(2, Opcode::SaveState).Inputs(0, 1).SrcVregs({0, 1}); - - INST(5, Opcode::CallDynamic).any().Inlined().InputsAutoType(0, 10, 10, 1, 2); + INST(3, Opcode::AnyTypeCheck).any().AnyType(AnyBaseType::ECMASCRIPT_FUNCTION_TYPE).Inputs(0, 2); + INST(5, Opcode::CallDynamic).any().Inlined().InputsAutoType(3, 10, 10, 1, 2); INST(6, Opcode::SaveState).Inputs(0, 1).SrcVregs({0, 1}); INST(7, Opcode::AnyTypeCheck).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(1, 6); INST(8, Opcode::ReturnInlined).Inputs(2); -- Gitee