diff --git a/compiler/ecma_compiler.yaml b/compiler/ecma_compiler.yaml index dac6af4c6874bbcc4b73d8b3702f901a43553b33..042e401cb5a1cf10623536765443034fd549b289 100644 --- a/compiler/ecma_compiler.yaml +++ b/compiler/ecma_compiler.yaml @@ -29,4 +29,10 @@ options: type: bool default: true description: Use profiling data when expanding newobj intrinsic + tags: [perf] + +- name: compiler-ecma-replace-intrinsics-to-deopt + type: bool + default: true + description: Replace intrinsics without profiling on deoptimize instruction tags: [perf] \ No newline at end of file diff --git a/compiler/templates/ecmascript_inst_builder_gen.cpp.erb b/compiler/templates/ecmascript_inst_builder_gen.cpp.erb index ad0498f06870ce4896fe9b976b5eeaa741f7f573..e8d76012d9a387b1e4bef7ec9eff21533f609127 100644 --- a/compiler/templates/ecmascript_inst_builder_gen.cpp.erb +++ b/compiler/templates/ecmascript_inst_builder_gen.cpp.erb @@ -173,6 +173,9 @@ void InstBuilder::BuildEcmaAsIntrinsics(const BytecodeInstruction* bc_inst) // N bool is_type_profiled = false; auto operand_type = GetRuntime()->GetProfilingAnyType(profile, bc_inst, <%= input_index %>, &allowed_input_type, &is_type_profiled); input = BuildAnyTypeCheckInst(GetPc(bc_inst->GetAddress()), input, inst_save_state, operand_type, is_type_profiled, allowed_input_type); + if (OPTIONS.IsCompilerEcmaReplaceIntrinsicsToDeopt() && !is_type_profiled) { + inst->SetReplaceOnDeoptimize(); + } } % end inst->AppendInput(input); @@ -235,7 +238,9 @@ void InstBuilder::BuildEcmaAsIntrinsics(const BytecodeInstruction* bc_inst) // N % idx = inst.profile.properties.include?('operand_types_2') ? 1 : 0 auto operand_type = GetRuntime()->GetProfilingAnyType(profile, bc_inst, <%= idx %>, &allowed_input_type, &is_type_profiled); input = BuildAnyTypeCheckInst(GetPc(bc_inst->GetAddress()), input, inst_save_state, operand_type, is_type_profiled, allowed_input_type); - + if (OPTIONS.IsCompilerEcmaReplaceIntrinsicsToDeopt() && !is_type_profiled) { + inst->SetReplaceOnDeoptimize(); + } } % end inst->AppendInput(input); diff --git a/runtime/compiler/ecmascript_runtime_interface.cpp b/runtime/compiler/ecmascript_runtime_interface.cpp index d7c61346757f79d7a25b6539f7d7040b326c08a7..6871d4ec31683047cd4bb4a7332c24cab89170ca 100644 --- a/runtime/compiler/ecmascript_runtime_interface.cpp +++ b/runtime/compiler/ecmascript_runtime_interface.cpp @@ -230,6 +230,10 @@ compiler::AnyBaseType EcmaRuntimeInterface::GetProfilingAnyType(RuntimeInterface case profiling::ProfilingKind::UNARY_ARITH: { UnaryOperationProfile p(ecma_prof); type = p.GetOperandType(index).GetType(); + if (type != ProfilingTypeBits::NONE) { + *is_type_profiled = true; + } + if (type == ProfilingTypeBits::STRING) { return compiler::AnyBaseType::ECMASCRIPT_STRING_TYPE; } @@ -241,6 +245,9 @@ compiler::AnyBaseType EcmaRuntimeInterface::GetProfilingAnyType(RuntimeInterface case profiling::ProfilingKind::BINARY_ARITH: { BinaryOperationProfile p(ecma_prof); type = p.GetOperandType(index).GetType(); + if (type != ProfilingTypeBits::NONE) { + *is_type_profiled = true; + } auto other_operand_type = p.GetOperandType(1 - index).GetType(); if (type == ProfilingTypeBits::STRING && other_operand_type == ProfilingTypeBits::STRING) { return compiler::AnyBaseType::ECMASCRIPT_STRING_TYPE; @@ -264,7 +271,6 @@ compiler::AnyBaseType EcmaRuntimeInterface::GetProfilingAnyType(RuntimeInterface return compiler::AnyBaseType::UNDEFINED_TYPE; } - *is_type_profiled = true; if (type == ProfilingTypeBits::BOOLEAN) { return compiler::AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE; } diff --git a/runtime/ecma_language_context.cpp b/runtime/ecma_language_context.cpp index 3cc6d5a606df4d6f6a48773bd0fb51c6e55b6922..5c03d59865dd958886f73fbb6411d408ad61d02e 100644 --- a/runtime/ecma_language_context.cpp +++ b/runtime/ecma_language_context.cpp @@ -113,6 +113,10 @@ void EcmaLanguageContext::RestoreEnv(Frame *current_iframe, const StackWalker::E ecmascript::JSFunction::Cast(ecmascript::JSTaggedValue(env_data[VRegType::THIS_FUNC]).GetHeapObject())); iframe_env->SetConstantPool(ecmascript::ConstantPool::Cast(env_data[VRegType::CONST_POOL])); iframe_env->SetLexicalEnv(ecmascript::LexicalEnv::Cast(env_data[VRegType::LEX_ENV])); + // restore func parameter + auto num_vregs = current_iframe->GetMethod()->GetNumVregs(); + DynamicFrameHandler frame_handler(current_iframe); + frame_handler.GetVReg(num_vregs + ecmascript::js_method_args::FUNC_IDX).SetValue(env_data[VRegType::THIS_FUNC]); } void EcmaLanguageContext::InitializeOsrCframeSlots(Span param_slots) const diff --git a/tests/checked/string_equals.js b/tests/checked/string_equals.js index e01ae9d2ff170b7d68c7222511bc3b3b05e7b337..2fc7186d7b49b29cca0516eae9565610b10c8b40 100644 --- a/tests/checked/string_equals.js +++ b/tests/checked/string_equals.js @@ -14,7 +14,7 @@ */ //! CHECKER String equals with profiled type - call fastpath EcmaStringEquals -//! RUN options: "--no-async-jit --compiler-hotness-threshold=1 --compiler-regex _GLOBAL::test_.*", entry: "_GLOBAL::func_main_0" +//! RUN options: "--no-async-jit --compiler-hotness-threshold=1 --compiler-ecma-replace-intrinsics-to-deopt=false --compiler-regex _GLOBAL::test_.*", entry: "_GLOBAL::func_main_0" //! EVENT_NOT /Deoptimization.*/ //! METHOD "test_eq" //! PASS_BEFORE "TypesResolving" @@ -29,7 +29,7 @@ //! INST_COUNT "Intrinsic.EcmaStringEquals", 1 //! CHECKER String equals without profiled type - call fastpath StrictEq/StrictNotEq -//! RUN options: "--no-async-jit --compiler-hotness-threshold=0 --compiler-regex _GLOBAL::test_.*", entry: "_GLOBAL::func_main_0" +//! RUN options: "--no-async-jit --compiler-hotness-threshold=0 --compiler-ecma-replace-intrinsics-to-deopt=false --compiler-regex _GLOBAL::test_.*", entry: "_GLOBAL::func_main_0" //! METHOD "test_eq" //! PASS_AFTER "Codegen" //! INST_NOT "Intrinsic.EcmaStringEquals"