From f14e5b4c263b471ca2bc079b7e37714b30a16ff8 Mon Sep 17 00:00:00 2001 From: Vsevolod Pukhov Date: Tue, 2 Aug 2022 13:21:31 +0300 Subject: [PATCH] [Compiler] Dynamic calling convention for ECMAScript Support dynamic CallingConvention for ECMAScript methods Rewrite handle_call* bridges, builtin bridges, fix Native CFrame unwind NewObjDynRange as stackrange intrinsic implementation for compiler Fixes and updates for ECMAScript codegen extensions Implement JSSpanHandle chain Adjust some intrinsics flags to avoid incorrect LSE Signed-off-by: Vsevolod Pukhov --- compiler/codegen_intrinsics_ecmascript.cpp | 75 +++++++---- compiler/ecmascript_call_params.h | 35 +++++ .../ecmascript_codegen_extensions.cpp | 89 ++++++------- .../ecmascript_codegen_extensions.h | 4 +- .../ecmascript_compiler_interface.h | 15 --- .../ecmascript_environment.h | 8 +- .../code_generator/compiler_base_types.cpp | 64 ++++----- .../ir_builder/ecmascript_inst_builder.cpp | 120 ++++++++++------- .../ir_builder/ecmascript_inst_builder.h | 2 + .../ir_builder/ecmascript_inst_templates.yaml | 14 +- ecmastdlib/ecmastdlib.pa | 2 +- irtoc_scripts/interpreter_handlers.irt | 126 ++++++++++-------- irtoc_scripts/interpreter_main_loop.irt | 2 +- isa/isa.yaml | 2 +- runtime/CMakeLists.txt | 6 +- runtime/asm_defines/asm_defines.def | 10 +- runtime/bridge.h | 3 +- .../arch/aarch64/builtin_bridge_aarch64.S | 16 +-- .../aarch64/handle_call_ecma_N_v8_aarch64.S | 89 +++++++------ ...ecma_callirangedyn_pref_imm16_v8_aarch64.S | 108 +++++++++------ ..._callithisrangedyn_pref_imm16_v8_aarch64.S | 82 ++++++------ .../arch/amd64/builtin_bridge_amd64.S | 20 +-- .../arch/amd64/handle_call_ecma_N_v8_amd64.S | 94 ++++++------- ...l_ecma_callirangedyn_pref_imm16_v8_amd64.S | 98 ++++++++------ ...ma_callithisrangedyn_pref_imm16_v8_amd64.S | 74 +++++----- .../arch/arm/builtin_bridge_arm.S | 0 .../compiler/ecmascript_runtime_interface.cpp | 23 ++-- .../compiler/ecmascript_runtime_interface.h | 23 +--- runtime/ecma_runtime.yaml | 92 ++++++++++++- runtime/ecma_runtime_call_info.h | 51 ++----- runtime/interpreter/ecma-interpreter-inl.h | 11 +- runtime/interpreter/interpreter-inl.h | 3 +- runtime/interpreter/js_frame-inl.h | 2 +- runtime/interpreter/slow_runtime_helper.cpp | 9 ++ runtime/interpreter/slow_runtime_stub.cpp | 15 +-- runtime/interpreter/slow_runtime_stub.h | 3 +- runtime/intrinsics-inl.h | 19 ++- runtime/js_function.h | 5 - runtime/js_handle.h | 52 ++++++++ runtime/js_invoker.cpp | 13 +- runtime/js_thread.cpp | 2 + runtime/js_thread.h | 3 + runtime/mem/mem.h | 21 --- runtime/runtime_sources.gn | 6 +- runtime/templates/intrinsics_gen.cpp.erb | 6 +- .../compiler/branch_elimination_ecma_test.cpp | 39 ++---- tests/compiler/ir_builder_ecma_test.cpp | 11 +- tests/compiler/peepholes_ecma_test.cpp | 10 +- tests/runtime/common/test_helper.cpp | 3 +- 49 files changed, 880 insertions(+), 700 deletions(-) create mode 100644 compiler/ecmascript_call_params.h rename runtime/{ => bridge}/arch/aarch64/builtin_bridge_aarch64.S (86%) rename runtime/{ => bridge}/arch/amd64/builtin_bridge_amd64.S (80%) rename runtime/{ => bridge}/arch/arm/builtin_bridge_arm.S (100%) diff --git a/compiler/codegen_intrinsics_ecmascript.cpp b/compiler/codegen_intrinsics_ecmascript.cpp index 100024cbe..52582262b 100644 --- a/compiler/codegen_intrinsics_ecmascript.cpp +++ b/compiler/codegen_intrinsics_ecmascript.cpp @@ -20,6 +20,34 @@ #include "plugins/ecmascript/runtime/mem/tagged_object.h" namespace panda::compiler { + +// TODO(vpukhov): reuse irtoc iframe reg +static void LoadIFramePtr(Codegen *cg, Reg dst) +{ + cg->GetEncoder()->EncodeLdr(dst, false, + MemRef(cg->ThreadReg(), cross_values::GetManagedThreadFrameOffset(cg->GetArch()))); +} + +static MemRef IFrameAccMemRef(Encoder *enc, Reg iframe_reg) +{ + return MemRef(iframe_reg, cross_values::GetFrameAccOffset(enc->GetArch())); +} + +static void ReadExtensionData(Codegen *cg, Reg dst, uint16_t env_offs) +{ + auto enc = cg->GetEncoder(); + auto arch = enc->GetArch(); + + if (cg->GetGraph()->SupportManagedCode()) { + enc->EncodeLdr(dst, false, MemRef(cg->SpReg(), cg->GetLanguageExtensionOffsetFromSpInBytes() + env_offs)); + } else { + auto dst_ptr = dst.As(TypeInfo::FromDataType(DataType::POINTER, arch)); + enc->EncodeLdr(dst_ptr, false, + MemRef(cg->ThreadReg(), cross_values::GetManagedThreadLanguageExtensionDataOffset(arch))); + enc->EncodeLdr(dst, false, MemRef(dst_ptr, env_offs)); + } +} + MemRef AccMemRef(Encoder *enc, Reg thread, Reg acc_reg) { enc->EncodeAdd(acc_reg, thread, Imm(ManagedThread::GetFrameOffset())); @@ -33,20 +61,20 @@ void Codegen::LdlexenvDyn([[maybe_unused]] IntrinsicInst *inst, [[maybe_unused]] auto enc = GetEncoder(); auto arch = enc->GetArch(); - ScopedTmpReg tmp1(enc); - Reg tmp1_reg(tmp1.GetReg().GetId(), Codegen::ConvertDataType(DataType::POINTER, arch)); - enc->EncodeLdr(tmp1_reg, false, MemRef(ThreadReg(), GetRuntime()->GetLanguageExtensionsDataOffset(arch))); - - auto lexical_env_ptr = MemRef(tmp1_reg, panda::ecmascript::EcmascriptEnvironment::GetLexicalEnvOffset()); - Reg tmp2_reg(tmp1.GetReg().GetId(), Codegen::ConvertDataType(DataType::ANY, arch)); - enc->EncodeLdr(tmp2_reg, false, lexical_env_ptr); + auto constexpr LE_OFFS = panda::ecmascript::EcmascriptEnvironment::GetLexicalEnvOffset(); if (!GetGraph()->GetMode().IsInterpreter()) { - enc->EncodeMov(dst, tmp2_reg); + ReadExtensionData(this, dst, LE_OFFS); } else { - ScopedTmpReg acc(enc); - Reg acc_reg(acc.GetReg().GetId(), Codegen::ConvertDataType(DataType::POINTER, arch)); - enc->EncodeStr(tmp2_reg, AccMemRef(enc, ThreadReg(), acc_reg)); + auto tmp1 = ConvertInstTmpReg(inst); + ScopedTmpReg tmp2(enc); + + Reg le_reg(tmp1.GetId(), Codegen::ConvertDataType(DataType::ANY, arch)); + Reg iframe_reg(tmp2.GetReg().GetId(), Codegen::ConvertDataType(DataType::POINTER, arch)); + + ReadExtensionData(this, le_reg, LE_OFFS); + LoadIFramePtr(this, iframe_reg); + enc->EncodeStr(le_reg, IFrameAccMemRef(enc, iframe_reg)); } } @@ -105,12 +133,9 @@ void Codegen::LdLexVarDyn([[maybe_unused]] IntrinsicInst *inst, [[maybe_unused]] auto runtime = GetRuntime(); auto tmp1 = ConvertInstTmpReg(inst); - Reg lang_ext(tmp1.GetId(), Codegen::ConvertDataType(DataType::POINTER, arch)); - enc->EncodeLdr(lang_ext, false, MemRef(ThreadReg(), GetRuntime()->GetLanguageExtensionsDataOffset(arch))); - auto lexical_env_ptr = MemRef(lang_ext, panda::ecmascript::EcmascriptEnvironment::GetLexicalEnvOffset()); Reg lex_env(tmp1.GetId(), Codegen::ConvertDataType(DataType::ANY, arch)); - enc->EncodeLdr(lex_env, false, lexical_env_ptr); + ReadExtensionData(this, lex_env, panda::ecmascript::EcmascriptEnvironment::GetLexicalEnvOffset()); auto begin_label = enc->CreateLabel(); auto exit_label = enc->CreateLabel(); @@ -218,8 +243,9 @@ void Codegen::LdLexVarDyn([[maybe_unused]] IntrinsicInst *inst, [[maybe_unused]] if (!GetGraph()->GetMode().IsInterpreter()) { enc->EncodeMov(dst, offset); } else { - Reg acc_reg(tmp1.GetId(), Codegen::ConvertDataType(DataType::POINTER, arch)); - enc->EncodeStr(offset, AccMemRef(enc, ThreadReg(), acc_reg)); + Reg iframe_reg(tmp1.GetId(), Codegen::ConvertDataType(DataType::POINTER, arch)); + LoadIFramePtr(this, iframe_reg); + enc->EncodeStr(offset, IFrameAccMemRef(enc, iframe_reg)); } } @@ -240,20 +266,13 @@ void Codegen::GetObjectClassTypeIntrinsic([[maybe_unused]] IntrinsicInst *inst, void Codegen::GetEcmaConstantPool([[maybe_unused]] IntrinsicInst *inst, [[maybe_unused]] Reg dst, [[maybe_unused]] SRCREGS src) { - auto dst_ext = dst.As(TypeInfo(TypeInfo::TypeId::INT64)); - GetEncoder()->EncodeLdr(dst_ext, false, - MemRef(ThreadReg(), GetRuntime()->GetLanguageExtensionsDataOffset(GetArch()))); - GetEncoder()->EncodeLdr(dst, false, - MemRef(dst_ext, panda::ecmascript::EcmascriptEnvironment::GetConstantPoolOffset())); + ReadExtensionData(this, dst, panda::ecmascript::EcmascriptEnvironment::GetConstantPoolOffset()); } void Codegen::GetEcmaThisFunc([[maybe_unused]] IntrinsicInst *inst, [[maybe_unused]] Reg dst, [[maybe_unused]] SRCREGS src) { - auto dst_ext = dst.As(TypeInfo(TypeInfo::TypeId::INT64)); - GetEncoder()->EncodeLdr(dst_ext, false, - MemRef(ThreadReg(), GetRuntime()->GetLanguageExtensionsDataOffset(GetArch()))); - GetEncoder()->EncodeLdr(dst, false, MemRef(dst_ext, panda::ecmascript::EcmascriptEnvironment::GetThisFuncOffset())); + ReadExtensionData(this, dst, panda::ecmascript::EcmascriptEnvironment::GetThisFuncOffset()); } void Codegen::GetWeakReferent([[maybe_unused]] IntrinsicInst *inst, [[maybe_unused]] Reg dst, @@ -303,14 +322,14 @@ void Codegen::CreateDynCallCheck([[maybe_unused]] IntrinsicInst *inst, [[maybe_u { auto exit_label = CreateSlowPath(inst, EntrypointId::DEOPTIMIZE)->GetLabel(); - ScopedTmpReg tmp(GetEncoder()); + ScopedTmpReg tmp(GetEncoder(), ConvertDataType(DataType::UINT64, GetArch())); LoadClassFromObject(tmp, src[0]); GetEncoder()->EncodeLdr(tmp, false, MemRef(tmp, -cross_values::GetJshclassHclassOffset(GetArch()) + cross_values::GetJshclassBitfieldOffset(GetArch()))); GetEncoder()->EncodeBitTestAndBranch(exit_label, tmp, - cross_values::GetJshclassBitfieldConstructorStartBit(GetArch()), true); + cross_values::GetJshclassBitfieldClassConstructorStartBit(GetArch()), true); } } // namespace panda::compiler diff --git a/compiler/ecmascript_call_params.h b/compiler/ecmascript_call_params.h new file mode 100644 index 000000000..d1f473f38 --- /dev/null +++ b/compiler/ecmascript_call_params.h @@ -0,0 +1,35 @@ +/** + * 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 PANDA_COMPILER_ECMASCRIPT_CALL_PARAMS +#define PANDA_COMPILER_ECMASCRIPT_CALL_PARAMS + +#include "compiler/optimizer/code_generator/callconv.h" + +// NOLINTNEXTLINE(modernize-concat-nested-namespaces) +namespace panda::compiler { + +namespace EcmascriptCallParams { +enum : uint8_t { + SLOT_FUNCTION = CallConvDynInfo::SLOT_CALLEE, + SLOT_NEWTARGET, + SLOT_THIS, + SLOT_FIRST_ARG, +}; +} // namespace EcmascriptCallParams + +} // namespace panda::compiler + +#endif // PANDA_COMPILER_ECMASCRIPT_CALL_PARAMS \ No newline at end of file diff --git a/compiler/ecmascript_extensions/ecmascript_codegen_extensions.cpp b/compiler/ecmascript_extensions/ecmascript_codegen_extensions.cpp index 9f10af6e5..b5e634248 100644 --- a/compiler/ecmascript_extensions/ecmascript_codegen_extensions.cpp +++ b/compiler/ecmascript_extensions/ecmascript_codegen_extensions.cpp @@ -15,71 +15,62 @@ #include "compiler/optimizer/code_generator/codegen.h" #include "ecmascript_environment.h" - -#ifdef PANDA_QEMU_AARCH64_GCC_8 -// Build PANDA_QEMU_AARCH64_GCC_8 hangs without this workaround. Please check issue #8094. -#include "plugins/ecmascript/runtime/js_thread.h" -namespace panda::ecmascript { -JSTaggedValue GetGlobalObject(JSThread *thread) -{ - return thread->GetGlobalObject(); -} -} // namespace panda::ecmascript -#endif +#include "plugins/ecmascript/compiler/ecmascript_call_params.h" namespace panda::compiler { -bool Codegen::GenerateEcmascriptEnvInPrologue() +void Codegen::GenerateEcmascriptEnvInPrologue() { - if (GetRuntime()->IsEcmascriptRuntime()) { - SCOPED_DISASM_STR(this, "Ecmascript Environment in Method Prologue"); - auto enc = GetEncoder(); + SCOPED_DISASM_STR(this, "Create EcmascriptEnvironment in method prologue"); + auto enc = GetEncoder(); + auto arch = GetArch(); - auto cp_src_offset = GetGraph()->GetRuntime()->GetConstantPoolOffset(); - auto le_src_offset = GetGraph()->GetRuntime()->GetLexicalEnvOffset(); + auto env_sp_offset = GetLanguageExtensionOffsetFromSpInBytes(); + auto env_ptr_tls_offset = cross_values::GetManagedThreadLanguageExtensionDataOffset(arch); + auto prev_env_sp_offset = env_sp_offset + cross_values::GetEcmascriptEnvironmentPrevEnvironmentOffset(arch); - auto ext_offset = GetLanguageExtensionOffsetFromSpInBytes(); - auto cp_dst_offset = ext_offset + panda::ecmascript::EcmascriptEnvironment::GetConstantPoolOffset(); - auto le_dst_offset = ext_offset + panda::ecmascript::EcmascriptEnvironment::GetLexicalEnvOffset(); - auto prev_env_offset = ext_offset + panda::ecmascript::EcmascriptEnvironment::GetPrevEnvironmentOffset(); - auto this_fnc_offset = ext_offset + panda::ecmascript::EcmascriptEnvironment::GetThisFuncOffset(); + // Initialize EcmascriptEnv fields + { + ScopedTmpReg jsfunc_reg(enc, ConvertDataType(DataType::ANY, GetArch())); + auto args_jsfunc_offset = GetStackOffset(Location::MakeStackParameter(EcmascriptCallParams::SLOT_FUNCTION)); + enc->EncodeLdr(jsfunc_reg, false, MemRef(SpReg(), args_jsfunc_offset)); - size_t js_func_reg_number = 2; - auto jsfunc_reg = GetTarget().GetParamReg(js_func_reg_number); + auto cp_jsf_offset = cross_values::GetJsfunctionConstantPoolOffset(GetArch()); + auto le_jsf_offset = cross_values::GetJsfunctionLexicalEnvOffset(GetArch()); - ScopedTmpReg tmp_reg(enc); - enc->EncodeLdr(tmp_reg, false, MemRef(ThreadReg(), GetRuntime()->GetLanguageExtensionsDataOffset(GetArch()))); + auto cp_sp_offset = env_sp_offset + cross_values::GetEcmascriptEnvironmentConstantPoolOffset(arch); + auto le_sp_offset = env_sp_offset + cross_values::GetEcmascriptEnvironmentLexicalEnvOffset(arch); + auto fn_sp_offset = env_sp_offset + cross_values::GetEcmascriptEnvironmentThisFuncOffset(arch); - ScopedTmpReg offset_reg(enc); - enc->EncodeAdd(offset_reg, SpReg(), Imm(ext_offset)); - enc->EncodeStr(offset_reg, MemRef(ThreadReg(), GetRuntime()->GetLanguageExtensionsDataOffset(GetArch()))); - offset_reg.Release(); - enc->EncodeMemCopy(MemRef(jsfunc_reg, cp_src_offset), MemRef(SpReg(), cp_dst_offset), jsfunc_reg.GetSize()); - enc->EncodeMemCopy(MemRef(jsfunc_reg, le_src_offset), MemRef(SpReg(), le_dst_offset), jsfunc_reg.GetSize()); - enc->EncodeStr(jsfunc_reg, MemRef(SpReg(), this_fnc_offset)); - enc->EncodeStr(tmp_reg, MemRef(SpReg(), prev_env_offset)); - return true; + enc->EncodeMemCopy(MemRef(jsfunc_reg, cp_jsf_offset), MemRef(SpReg(), cp_sp_offset), + DataType::GetTypeSize(DataType::ANY, arch)); + enc->EncodeMemCopy(MemRef(jsfunc_reg, le_jsf_offset), MemRef(SpReg(), le_sp_offset), + DataType::GetTypeSize(DataType::ANY, arch)); + enc->EncodeStr(jsfunc_reg, MemRef(SpReg(), fn_sp_offset)); } - return false; -} -bool Codegen::GenerateEcmascriptEnvInEpilogue() -{ - if (!GetRuntime()->IsEcmascriptRuntime()) { - return false; + // Update current env TLS pointer and link with previous + { + ScopedTmpReg tmp_reg(enc, ConvertDataType(DataType::POINTER, GetArch())); + enc->EncodeLdr(tmp_reg, false, MemRef(ThreadReg(), env_ptr_tls_offset)); + enc->EncodeStr(tmp_reg, MemRef(SpReg(), prev_env_sp_offset)); + enc->EncodeAdd(tmp_reg, SpReg(), Imm(env_sp_offset)); + enc->EncodeStr(tmp_reg, MemRef(ThreadReg(), env_ptr_tls_offset)); } - SCOPED_DISASM_STR(this, "Ecmascript Environment in Method Epilogue"); - ScopedTmpReg js_env_reg(GetEncoder()); +} +void Codegen::GenerateEcmascriptEnvInEpilogue() +{ + SCOPED_DISASM_STR(this, "Destroy EcmascriptEnvironment in method epilogue"); auto enc = GetEncoder(); - enc->EncodeLdr(js_env_reg, false, MemRef(ThreadReg(), GetRuntime()->GetLanguageExtensionsDataOffset(GetArch()))); - auto prev_env_offset = panda::ecmascript::EcmascriptEnvironment::GetPrevEnvironmentOffset(); - enc->EncodeMemCopy(MemRef(js_env_reg, prev_env_offset), - MemRef(ThreadReg(), GetRuntime()->GetLanguageExtensionsDataOffset(GetArch())), - js_env_reg.GetReg().GetSize()); + auto env_ptr_tls_offset = cross_values::GetManagedThreadLanguageExtensionDataOffset(GetArch()); + auto prev_env_env_offset = panda::ecmascript::EcmascriptEnvironment::GetPrevEnvironmentOffset(); - return true; + ScopedTmpReg env_reg(enc, ConvertDataType(DataType::POINTER, GetArch())); + enc->EncodeLdr(env_reg, false, MemRef(ThreadReg(), env_ptr_tls_offset)); + enc->EncodeMemCopy(MemRef(env_reg, prev_env_env_offset), MemRef(ThreadReg(), env_ptr_tls_offset), + env_reg.GetReg().GetSize()); } } // namespace panda::compiler diff --git a/compiler/ecmascript_extensions/ecmascript_codegen_extensions.h b/compiler/ecmascript_extensions/ecmascript_codegen_extensions.h index 43cacf59b..4b068f44c 100644 --- a/compiler/ecmascript_extensions/ecmascript_codegen_extensions.h +++ b/compiler/ecmascript_extensions/ecmascript_codegen_extensions.h @@ -16,7 +16,7 @@ #ifndef PANDA_COMPILER_ECMASCRIPT_CODEGEN_EXTENSIONS_H #define PANDA_COMPILER_ECMASCRIPT_CODEGEN_EXTENSIONS_H -bool GenerateEcmascriptEnvInPrologue(); -bool GenerateEcmascriptEnvInEpilogue(); +void GenerateEcmascriptEnvInPrologue(); +void GenerateEcmascriptEnvInEpilogue(); #endif // PANDA_COMPILER_ECMASCRIPT_CODEGEN_EXTENSIONS_H \ No newline at end of file diff --git a/compiler/ecmascript_extensions/ecmascript_compiler_interface.h b/compiler/ecmascript_extensions/ecmascript_compiler_interface.h index 16bdae245..9122b4313 100644 --- a/compiler/ecmascript_extensions/ecmascript_compiler_interface.h +++ b/compiler/ecmascript_extensions/ecmascript_compiler_interface.h @@ -16,19 +16,4 @@ #ifndef PANDA_COMPILER_ECMASCRIPT_COMPILER_INTERFACE_H #define PANDA_COMPILER_ECMASCRIPT_COMPILER_INTERFACE_H -virtual size_t GetConstantPoolOffset() -{ - return 0; -} - -virtual size_t GetLexicalEnvOffset() -{ - return 0; -} - -virtual bool IsEcmascriptRuntime() -{ - return false; -} - #endif // PANDA_COMPILER_ECMASCRIPT_COMPILER_INTERFACE_H \ No newline at end of file diff --git a/compiler/ecmascript_extensions/ecmascript_environment.h b/compiler/ecmascript_extensions/ecmascript_environment.h index ec2edf36e..5facccee7 100644 --- a/compiler/ecmascript_extensions/ecmascript_environment.h +++ b/compiler/ecmascript_extensions/ecmascript_environment.h @@ -33,8 +33,8 @@ class JSHandle; class EcmascriptEnvironment { public: - EcmascriptEnvironment(ObjectHeader *cp, ObjectHeader *le, ObjectHeader *tf, EcmascriptEnvironment *prev) - : constant_pool_(cp), lexical_env_(le), this_func_(tf), prev_env_(prev) + EcmascriptEnvironment(EcmascriptEnvironment *prev, ObjectHeader *cp, ObjectHeader *le, ObjectHeader *tf) + : prev_env_(prev), constant_pool_(cp), lexical_env_(le), this_func_(tf) { } @@ -103,16 +103,16 @@ public: prev_env_ = prev_env; } - static size_t GetSize() + static constexpr size_t GetSize() { return AlignUp(sizeof(EcmascriptEnvironment), GetAlignmentInBytes(DEFAULT_FRAME_ALIGNMENT)); } private: + EcmascriptEnvironment *prev_env_; panda::coretypes::TaggedValue constant_pool_; panda::coretypes::TaggedValue lexical_env_; panda::coretypes::TaggedValue this_func_; - EcmascriptEnvironment *prev_env_; }; } // namespace ecmascript diff --git a/compiler/optimizer/code_generator/compiler_base_types.cpp b/compiler/optimizer/code_generator/compiler_base_types.cpp index 8ea970369..2b12bc10b 100644 --- a/compiler/optimizer/code_generator/compiler_base_types.cpp +++ b/compiler/optimizer/code_generator/compiler_base_types.cpp @@ -102,7 +102,8 @@ static void IsEqualToValGen(Encoder *enc, Reg dst, Reg src, Imm val, } } -static void CompareAnyTypeGenObject(Encoder *enc, const Reg &src, LabelHolder::LabelId label) +// Jump out if !IsHeapObject() +static void CheckAnyTypeGenObject(Encoder *enc, const Reg &src, LabelHolder::LabelId label) { ScopedTmpReg tmp_reg(enc, TypeInfo(TypeInfo::TypeId::INT64)); @@ -120,24 +121,15 @@ static void CompareAnyTypeGenObject(Encoder *enc, const Reg &src, LabelHolder::L enc->EncodeJump(label, src, Imm(panda::coretypes::TaggedValue::TAG_SPECIAL_MASK), Condition::LE); } -static void CompareAnyTypeGenObject(Encoder *enc, const Reg &dst, const Reg &src) -{ - auto label = enc->CreateLabel(); - enc->EncodeMov(dst, Imm(0)); - CompareAnyTypeGenObject(enc, src, label); - enc->EncodeMov(dst, Imm(1U)); - enc->BindLabel(label); -} - -static void CompareAnyTypeGenObjectType(Codegen *codegen, Encoder *enc, const Reg &dst, const Reg &src, uint32_t type, - LabelHolder::LabelId label, Condition fail_cc = Condition::NE) +// Jump out if (!IsHeapObject() or object.type, type) +static void CheckAnyTypeGenObjectType(Codegen *codegen, Encoder *enc, const Reg &src, uint32_t type, + LabelHolder::LabelId label, Condition fail_cc = Condition::NE) { - enc->EncodeMov(dst, Imm(0)); - CompareAnyTypeGenObject(enc, src, label); - - ScopedTmpReg tmp_reg(enc, codegen->ConvertDataType(DataType::REFERENCE, enc->GetArch())); + CheckAnyTypeGenObject(enc, src, label); auto arch = codegen->GetArch(); + ScopedTmpReg tmp_reg(enc, codegen->ConvertDataType(DataType::REFERENCE, arch)); + enc->EncodeLdr(tmp_reg, false, MemRef(src, codegen->GetRuntime()->GetObjClassOffset(arch))); enc->EncodeLdr(tmp_reg, false, MemRef(tmp_reg, cross_values::GetHclassDataOffset(arch))); enc->EncodeAnd(tmp_reg, tmp_reg, Imm(static_cast(cross_values::GetJshclassBitfieldTypeMask(arch)))); @@ -146,16 +138,27 @@ static void CompareAnyTypeGenObjectType(Codegen *codegen, Encoder *enc, const Re enc->EncodeShr(tmp_reg, tmp_reg, Imm(type_start_bit)); } enc->EncodeJump(label, tmp_reg, Imm(type), fail_cc); +} +// dst = IsHeapObject() +static void CompareAnyTypeGenObject(Encoder *enc, const Reg &dst, const Reg &src) +{ + auto label_false = enc->CreateLabel(); + enc->EncodeMov(dst, Imm(0)); + CheckAnyTypeGenObject(enc, src, label_false); enc->EncodeMov(dst, Imm(1U)); + enc->BindLabel(label_false); } +// dst = (IsHeapObject() and ! object.type, type) static void CompareAnyTypeGenObjectType(Codegen *codegen, Encoder *enc, const Reg &dst, const Reg &src, uint32_t type, Condition fail_cc = Condition::NE) { - auto label = enc->CreateLabel(); - CompareAnyTypeGenObjectType(codegen, enc, dst, src, type, label, fail_cc); - enc->BindLabel(label); + auto label_false = enc->CreateLabel(); + enc->EncodeMov(dst, Imm(0)); + CheckAnyTypeGenObjectType(codegen, enc, src, type, label_false, fail_cc); + enc->EncodeMov(dst, Imm(1U)); + enc->BindLabel(label_false); } bool ecmascript::CompareAnyTypeGen(const CompareAnyTypeInst *cati, EncodeVisitor *enc_v) @@ -364,30 +367,28 @@ bool ecmascript::AnyTypeCheckGen(const AnyTypeCheckInst *check_inst, EncodeVisit Imm(panda::coretypes::TaggedValue::TAG_MASK), id); return true; case AnyBaseType::ECMASCRIPT_HEAP_OBJECT_TYPE: - CompareAnyTypeGenObject(enc, tmp_reg, src); + CheckAnyTypeGenObject(enc, src, id); return true; case AnyBaseType::ECMASCRIPT_DOUBLE_TYPE: CompareAnyTypeGenDouble(enc, tmp_reg, src, check_inst->IsIntegerWasSeen(), id); return true; case AnyBaseType::ECMASCRIPT_STRING_TYPE: - CompareAnyTypeGenObjectType(codegen, enc, tmp_reg, src, cross_values::GetJstypeString(codegen->GetArch()), - id); + CheckAnyTypeGenObjectType(codegen, enc, src, cross_values::GetJstypeString(codegen->GetArch()), id); return true; case AnyBaseType::ECMASCRIPT_ARRAY_TYPE: - CompareAnyTypeGenObjectType(codegen, enc, tmp_reg, src, cross_values::GetJstypeJsArray(codegen->GetArch()), - id); + CheckAnyTypeGenObjectType(codegen, enc, src, cross_values::GetJstypeJsArray(codegen->GetArch()), id); return true; case AnyBaseType::ECMASCRIPT_TRANSITION_HANDLER_TYPE: - CompareAnyTypeGenObjectType(codegen, enc, tmp_reg, src, - cross_values::GetJstypeTransitionHandler(codegen->GetArch()), id); + CheckAnyTypeGenObjectType(codegen, enc, src, cross_values::GetJstypeTransitionHandler(codegen->GetArch()), + id); return true; case AnyBaseType::ECMASCRIPT_PROTOTYPE_HANDLER_TYPE: - CompareAnyTypeGenObjectType(codegen, enc, tmp_reg, src, - cross_values::GetJstypePrototypeHandler(codegen->GetArch()), id); + CheckAnyTypeGenObjectType(codegen, enc, src, cross_values::GetJstypePrototypeHandler(codegen->GetArch()), + id); return true; case AnyBaseType::ECMASCRIPT_SPECIAL_INDEXED_TYPE: - CompareAnyTypeGenObjectType(codegen, enc, tmp_reg, src, cross_values::GetJstypeJsArray(codegen->GetArch()), - id, Condition::LE); + CheckAnyTypeGenObjectType(codegen, enc, src, cross_values::GetJstypeJsArray(codegen->GetArch()), id, + Condition::LE); return true; case AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE: { CompareAnyTypeGenBool(enc, tmp_reg, src, id); @@ -400,8 +401,7 @@ bool ecmascript::AnyTypeCheckGen(const AnyTypeCheckInst *check_inst, EncodeVisit IsEqualToValGen(enc, tmp_reg, src, Imm(panda::coretypes::TaggedValue::VALUE_HOLE), id); return true; case AnyBaseType::ECMASCRIPT_FUNCTION_TYPE: - CompareAnyTypeGenObjectType(codegen, enc, tmp_reg, src, - cross_values::GetJstypeJsFunction(codegen->GetArch()), id); + CheckAnyTypeGenObjectType(codegen, enc, src, cross_values::GetJstypeJsFunction(codegen->GetArch()), id); return true; default: return false; diff --git a/compiler/optimizer/ir_builder/ecmascript_inst_builder.cpp b/compiler/optimizer/ir_builder/ecmascript_inst_builder.cpp index 409c06f82..d08c2a701 100644 --- a/compiler/optimizer/ir_builder/ecmascript_inst_builder.cpp +++ b/compiler/optimizer/ir_builder/ecmascript_inst_builder.cpp @@ -26,68 +26,98 @@ namespace panda::compiler { // NOLINTNEXTLINE(misc-definitions-in-headers) void InstBuilder::BuildEcmaFnCall(const BytecodeInstruction *bc_inst, bool is_range, bool call_this, uint64_t num_args) { - constexpr size_t NUMBER_HIDE_ARGS = 3; - auto pc = GetPc(bc_inst->GetAddress()); - auto save_state = CreateSaveState(Opcode::SaveState, pc); + auto bc_pc = GetPc(bc_inst->GetAddress()); + auto save_state = CreateSaveState(Opcode::SaveState, bc_pc); AddInstruction(save_state); - auto input = GetDefinition(bc_inst->GetVReg(0)); - auto func_check = BuildAnyTypeCheckInst(pc, input, save_state, AnyBaseType::ECMASCRIPT_FUNCTION_TYPE); - - auto fn_class_check = GetGraph()->CreateInstIntrinsic(DataType::ANY, pc); - fn_class_check->SetIntrinsicId(RuntimeInterface::IntrinsicId::INTRINSIC_DYN_CALL_CHECK); - AdjustFlags(fn_class_check->GetIntrinsicId(), fn_class_check); - fn_class_check->SetFlag(inst_flags::CAN_DEOPTIMIZE); - fn_class_check->ReserveInputs(1); - fn_class_check->AllocateInputTypes(GetGraph()->GetAllocator(), 1); - fn_class_check->AppendInput(func_check); - fn_class_check->AddInputType(DataType::ANY); - fn_class_check->AppendInput(save_state); - fn_class_check->AddInputType(DataType::NO_TYPE); - AddInstruction(fn_class_check); + auto callee = GetDefinition(bc_inst->GetVReg(0)); - auto inst = GetGraph()->CreateInstCallDynamic(DataType::ANY, pc); + { // Check callee is JSFunction + auto callee_func = BuildAnyTypeCheckInst(bc_pc, callee, save_state, AnyBaseType::ECMASCRIPT_FUNCTION_TYPE); + callee = callee_func; + } - inst->SetCanNativeException(true); + { // Check callee is suitable to call (!IsConstructor) + auto fn_class_check = GetGraph()->CreateInstIntrinsic(DataType::ANY, bc_pc); + fn_class_check->SetIntrinsicId(RuntimeInterface::IntrinsicId::INTRINSIC_DYN_CALL_CHECK); + AdjustFlags(fn_class_check->GetIntrinsicId(), fn_class_check); + fn_class_check->SetFlag(inst_flags::CAN_DEOPTIMIZE); + fn_class_check->ReserveInputs(1); + fn_class_check->AllocateInputTypes(GetGraph()->GetAllocator(), 1); + fn_class_check->AppendInput(callee); + fn_class_check->AddInputType(DataType::ANY); + fn_class_check->AppendInput(save_state); + fn_class_check->AddInputType(DataType::NO_TYPE); + AddInstruction(fn_class_check); + } - size_t args_count = 0; + auto call_inst = GetGraph()->CreateInstCallDynamic(DataType::ANY, bc_pc); + call_inst->SetCanNativeException(true); + + // func, new_target, this?, args..., ss + uint64_t args_count = 2U + (call_this ? 0 : 1) + (is_range ? bc_inst->GetImm64() : num_args) + 1U; + call_inst->ReserveInputs(args_count); + call_inst->AllocateInputTypes(GetGraph()->GetAllocator(), args_count); + + // Append func, new_target, this + call_inst->AppendInput(callee); + call_inst->AddInputType(DataType::ANY); + call_inst->AppendInput(FindOrCreateConstant(coretypes::TaggedValue::VALUE_UNDEFINED)); + call_inst->AddInputType(DataType::ANY); + if (!call_this) { // Assume strict mode + call_inst->AppendInput(FindOrCreateConstant(coretypes::TaggedValue::VALUE_UNDEFINED)); + call_inst->AddInputType(DataType::ANY); + } - // Take into account this argument for virtual call if (is_range) { - args_count = bc_inst->GetImm64() + 1; + auto range_start = bc_inst->GetVReg(0) + 1; + auto range_size = bc_inst->GetImm64(); + + for (int64_t i = 0; i < range_size; ++i) { + call_inst->AppendInput(GetDefinition(range_start + i)); + call_inst->AddInputType(DataType::ANY); + } } else { - args_count = num_args; + for (uint64_t i = 0; i < num_args; ++i) { + call_inst->AppendInput(GetDefinition(bc_inst->GetVReg(1 + i))); + call_inst->AddInputType(DataType::ANY); + } } + call_inst->AppendInput(save_state); + call_inst->AddInputType(DataType::NO_TYPE); + AddInstruction(call_inst); + UpdateDefinitionAcc(call_inst); +} - inst->ReserveInputs(args_count + 1); // '+1' for SaveState input - inst->AllocateInputTypes(GetGraph()->GetAllocator(), args_count + 1); +void InstBuilder::BuildEcmaNewobjdynrange(const BytecodeInstruction *bc_inst) +{ + auto graph = GetGraph(); + auto bc_pc = GetPc(bc_inst->GetAddress()); + auto start_reg = bc_inst->GetVReg(0); - inst->AppendInput(func_check); - inst->AddInputType(DataType::ANY); + auto inst = graph->CreateInstIntrinsic(DataType::ANY, bc_pc); + inst->SetIntrinsicId(RuntimeInterface::IntrinsicId::INTRINSIC_NEWOBJ_DYNRANGE); + AdjustFlags(inst->GetIntrinsicId(), inst); + inst->SetFlag(inst_flags::CAN_THROW); - inst->AppendInput(FindOrCreateConstant(coretypes::TaggedValue::VALUE_UNDEFINED)); // newtarget argument - inst->AddInputType(DataType::ANY); + auto save_state = CreateSaveState(Opcode::SaveState, bc_pc); + AddInstruction(save_state); - if (!call_this) { - inst->AppendInput(FindOrCreateConstant(coretypes::TaggedValue::VALUE_UNDEFINED)); // this argument - inst->AddInputType(DataType::ANY); - } + uint32_t constexpr FIXED_INPUTS = 2U; + auto args_count = bc_inst->GetImm64(); + inst->ReserveInputs(args_count + FIXED_INPUTS); + inst->AllocateInputTypes(graph->GetAllocator(), args_count + FIXED_INPUTS); - if (is_range) { - auto start_reg = bc_inst->GetVReg(0); - // start reg for Virtual call was added - for (size_t i = 0; i < args_count - 1; i++) { - inst->AppendInput(GetDefinition(start_reg + i + 1)); - inst->AddInputType(DataType::ANY); - } - } else { - for (size_t i = 0; i < args_count - NUMBER_HIDE_ARGS; i++) { - inst->AppendInput(GetDefinition(bc_inst->GetVReg(i + 1))); - inst->AddInputType(DataType::ANY); - } + inst->AppendInput(FindOrCreateConstant(args_count - 2)); + inst->AddInputType(DataType::UINT16); + + for (int64_t i = 0; i < args_count; ++i) { + inst->AppendInput(GetDefinition(start_reg + i)); + inst->AddInputType(DataType::ANY); } inst->AppendInput(save_state); inst->AddInputType(DataType::NO_TYPE); + inst->SetFlag(inst_flags::ACC_WRITE); AddInstruction(inst); UpdateDefinitionAcc(inst); } diff --git a/compiler/optimizer/ir_builder/ecmascript_inst_builder.h b/compiler/optimizer/ir_builder/ecmascript_inst_builder.h index 6e6597601..27f4c2c27 100644 --- a/compiler/optimizer/ir_builder/ecmascript_inst_builder.h +++ b/compiler/optimizer/ir_builder/ecmascript_inst_builder.h @@ -27,4 +27,6 @@ void BuildLdGlobalVar(const BytecodeInstruction *bc_inst, size_t type_id); void BuildEcmaFnCall(const BytecodeInstruction *bc_inst, bool is_range, bool call_this, uint64_t num_args = 0); +void BuildEcmaNewobjdynrange(const BytecodeInstruction *bc_inst); + #endif // PLUGINS_ECMASCRIPT_COMPILER_OPTIMIZER_IR_BUILDER_ECMASCRIPT_INST_BUILDER_H diff --git a/compiler/optimizer/ir_builder/ecmascript_inst_templates.yaml b/compiler/optimizer/ir_builder/ecmascript_inst_templates.yaml index c2b13a526..b742a1c16 100644 --- a/compiler/optimizer/ir_builder/ecmascript_inst_templates.yaml +++ b/compiler/optimizer/ir_builder/ecmascript_inst_templates.yaml @@ -36,25 +36,25 @@ if (graph_->IsBytecodeOptimizer()) { BuildEcma(instruction); } else { - BuildEcmaFnCall(instruction, false, false, 3); + BuildEcmaFnCall(instruction, false, false, 0); } % when "CALL1DYN" if (graph_->IsBytecodeOptimizer()) { BuildEcma(instruction); } else { - BuildEcmaFnCall(instruction, false, false, 4); + BuildEcmaFnCall(instruction, false, false, 1); } % when "CALL2DYN" if (graph_->IsBytecodeOptimizer()) { BuildEcma(instruction); } else { - BuildEcmaFnCall(instruction, false, false, 5); + BuildEcmaFnCall(instruction, false, false, 2); } % when "CALL3DYN" if (graph_->IsBytecodeOptimizer()) { BuildEcma(instruction); } else { - BuildEcmaFnCall(instruction, false, false, 6); + BuildEcmaFnCall(instruction, false, false, 3); } % when "CALLIRANGEDYN" if (graph_->IsBytecodeOptimizer()) { @@ -72,6 +72,12 @@ BuildStGlobalVar< <%= inst.acc_read? %> >(instruction, instruction->template GetId<<%= inst.get_format %>>().AsFileId().GetOffset()); % when "LDGLOBALVAR" BuildLdGlobalVar< <%= inst.acc_write? %> >(instruction, instruction->template GetId<<%= inst.get_format %>>().AsFileId().GetOffset()); + % when "NEWOBJDYNRANGE" + if (graph_->IsBytecodeOptimizer()) { + BuildEcma(instruction); + } else { + BuildEcmaNewobjdynrange(instruction); + } % else BuildEcma(instruction); % end diff --git a/ecmastdlib/ecmastdlib.pa b/ecmastdlib/ecmastdlib.pa index 34cba78fe..e6fcb318d 100644 --- a/ecmastdlib/ecmastdlib.pa +++ b/ecmastdlib/ecmastdlib.pa @@ -64,7 +64,7 @@ .function any Ecmascript.Intrinsics.definefuncexpr(any a0, any a1) .function any Ecmascript.Intrinsics.definefuncDyn(u32 a0, any a1) .function any Ecmascript.Intrinsics.defineNCFuncDyn(u32 a0, any a1, any a2) -.function any Ecmascript.Intrinsics.newobjDynrange(u16 a0, any a1) +.function any Ecmascript.Intrinsics.newobjDynrangeInterp(u16 a0, any a1) .function any Ecmascript.Intrinsics.refeqDyn(any a0, any a1) .function any Ecmascript.Intrinsics.expDyn(any a0, any a1) .function any Ecmascript.Intrinsics.typeofDyn(any a0) diff --git a/irtoc_scripts/interpreter_handlers.irt b/irtoc_scripts/interpreter_handlers.irt index b25370e1f..84faa434d 100644 --- a/irtoc_scripts/interpreter_handlers.irt +++ b/irtoc_scripts/interpreter_handlers.irt @@ -276,15 +276,15 @@ macro(:and2dyn_smi_smi) do |l, r| end macro(:and2dyn_smi_double) do |l, r| - i32toany(And(anytoi32(l), i64toi32(f64toi64(anytof64(r)))).i32) + i32toany(And(anytoi32(l), f64toi32(anytof64(r))).i32) end macro(:and2dyn_double_smi) do |l, r| - i32toany(And(i64toi32(f64toi64(anytof64(l))), anytoi32(r)).i32) + i32toany(And(f64toi32(anytof64(l)), anytoi32(r)).i32) end macro(:and2dyn_double_double) do |l, r| - i32toany(And(i64toi32(f64toi64(anytof64(l))), i64toi32(f64toi64(anytof64(r)))).i32) + i32toany(And(f64toi32(anytof64(l)), f64toi32(anytof64(r))).i32) end #################################################################### @@ -295,15 +295,15 @@ macro(:or2dyn_smi_smi) do |l, r| end macro(:or2dyn_smi_double) do |l, r| - i32toany(Or(anytoi32(l), i64toi32(f64toi64(anytof64(r)))).i32) + i32toany(Or(anytoi32(l), f64toi32(anytof64(r))).i32) end macro(:or2dyn_double_smi) do |l, r| - i32toany(Or(i64toi32(f64toi64(anytof64(l))), anytoi32(r)).i32) + i32toany(Or(f64toi32(anytof64(l)), anytoi32(r)).i32) end macro(:or2dyn_double_double) do |l, r| - i32toany(Or(i64toi32(f64toi64(anytof64(l))), i64toi32(f64toi64(anytof64(r)))).i32) + i32toany(Or(f64toi32(anytof64(l)), f64toi32(anytof64(r))).i32) end #################################################################### @@ -314,15 +314,15 @@ macro(:xor2dyn_smi_smi) do |l, r| end macro(:xor2dyn_smi_double) do |l, r| - i32toany(Xor(anytoi32(l), i64toi32(f64toi64(anytof64(r)))).i32) + i32toany(Xor(anytoi32(l), f64toi32(anytof64(r))).i32) end macro(:xor2dyn_double_smi) do |l, r| - i32toany(Xor(i64toi32(f64toi64(anytof64(l))), anytoi32(r)).i32) + i32toany(Xor(f64toi32(anytof64(l)), anytoi32(r)).i32) end macro(:xor2dyn_double_double) do |l, r| - i32toany(Xor(i64toi32(f64toi64(anytof64(l))), i64toi32(f64toi64(anytof64(r)))).i32) + i32toany(Xor(f64toi32(anytof64(l)), f64toi32(anytof64(r))).i32) end #################################################################### @@ -337,11 +337,11 @@ macro(:shl2dyn_smi_double) do |l, r| end macro(:shl2dyn_double_smi) do |l, r| - i32toany(Shl(i64toi32(f64toi64(anytof64(l))), anytoi32(r.any)).i32) + i32toany(Shl(f64toi32(anytof64(l)), anytoi32(r.any)).i32) end macro(:shl2dyn_double_double) do |l, r| - i32toany(Shl(i64toi32(f64toi64(anytof64(l))), f64toi32(anytof64(r.any))).i32) + i32toany(Shl(f64toi32(anytof64(l)), f64toi32(anytof64(r.any))).i32) end #################################################################### @@ -356,11 +356,11 @@ macro(:shr2dyn_smi_double) do |l, r| end macro(:shr2dyn_double_smi) do |l, r| - i32toany(AShr(i64toi32(f64toi64(anytof64(l))), anytoi32(r.any)).i32) + i32toany(AShr(f64toi32(anytof64(l)), anytoi32(r.any)).i32) end macro(:shr2dyn_double_double) do |l, r| - i32toany(AShr(i64toi32(f64toi64(anytof64(l))), f64toi32(anytof64(r.any))).i32) + i32toany(AShr(f64toi32(anytof64(l)), f64toi32(anytof64(r.any))).i32) end #################################################################################### @@ -424,7 +424,7 @@ Label(:Exit) Phi(res, slow_res).any end -function(:EcmaMod2dyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaMod2dyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_mod2dyn(a, b)) end @@ -435,7 +435,7 @@ macro(:handle_ecma_tonumber) do |v| Phi(v.any, slow_res).any end -function(:EcmaTonumber, params: {'a'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaTonumber, params: {'a'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_tonumber(a)) end @@ -447,7 +447,7 @@ macro(:notdyn_smi) do |v| end macro(:notdyn_double) do |v| - i32toany(Not(i64toi32(f64toi64(anytof64(v)))).i32) + i32toany(Not(f64toi32(anytof64(v))).i32) end #################################################################### @@ -605,11 +605,11 @@ cpp_function(:"IrtocInlineIsTrueDyn") do } end -function(:"EcmaIsfalse", params: {a: 'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:"EcmaIsfalse", params: {a: 'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(isfalsedyn(a)) end -function(:"EcmaIstrue", params: {a: 'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:"EcmaIstrue", params: {a: 'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(istruedyn(a)) end @@ -654,7 +654,7 @@ end end end - function(:"Ecma#{op.capitalize}2dyn", params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do + function(:"Ecma#{op.capitalize}2dyn", params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(send(:"handle_ecma_#{op}2dyn", a, b)) end @@ -662,7 +662,7 @@ end params: {a: 'any', b: 'any'}, regmap: $full_regmap, regalloc_set: RegMask.new($full_regmap, :arg0, :arg1) + $panda_callees_mask - $panda_regmap, - mode: [:FastPath, :DynamicMethod]) do + mode: [:FastPath, :DynamicMethod, :DynamicStub]) do # Arm32 is not supported if Options.arch == :arm32 Intrinsic(:UNREACHABLE).Terminator.void @@ -723,7 +723,7 @@ end end end - function(:"Ecma#{op.capitalize}dyn", params: {'a'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do + function(:"Ecma#{op.capitalize}dyn", params: {'a'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(send(:"handle_ecma_#{op}dyn", a)) end @@ -731,7 +731,7 @@ end params: {a: 'any'}, regmap: $full_regmap, regalloc_set: RegMask.new($full_regmap, :tmp1, :arg0, :callee0), - mode: [:FastPath, :DynamicMethod]) do + mode: [:FastPath, :DynamicMethod, :DynamicStub]) do # Arm32 is not supported if Options.arch == :arm32 Intrinsic(:UNREACHABLE).Terminator.void @@ -809,7 +809,7 @@ macro(:handle_ecma_toboolean) do |v| booltoany(any_extractBoolean(v)) end -function(:EcmaToboolean, params: {'a'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaToboolean, params: {'a'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_toboolean(a)) end @@ -823,7 +823,7 @@ macro(:handle_ecma_lessdyn) do |l, r| Phi(slow_res, fp1_res).any end -function(:EcmaLessdyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaLessdyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_lessdyn(a, b)) end @@ -861,7 +861,7 @@ Label(:Exit) Phi(eq_res, int_neq_res, spec_obj_neq_res, spec_spec_neq_res, slow_res).any end -function(:EcmaEqdyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaEqdyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_eqdyn(a, b)) end @@ -875,7 +875,7 @@ macro(:handle_ecma_stricteqdyn) do |l, r| Phi(slow_res, fp1_res).any end -function(:EcmaStricteqdyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaStricteqdyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_stricteqdyn(a, b)) end @@ -889,7 +889,7 @@ macro(:handle_ecma_strictnoteqdyn) do |l, r| Phi(slow_res, fp1_res).any end -function(:EcmaStrictnoteqdyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaStrictnoteqdyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_strictnoteqdyn(a, b)) end @@ -903,7 +903,7 @@ macro(:handle_ecma_lesseqdyn) do |l, r| res := Phi(slow_res, fp1_res).any end -function(:EcmaLesseqdyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaLesseqdyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_lesseqdyn(a, b)) end @@ -935,7 +935,7 @@ Label(:Exit) Phi(int_res, fp1_res, fp2_res, fp3_res, slow_res).any end -function(:EcmaGreaterdyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaGreaterdyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_greaterdyn(a, b)) end @@ -949,7 +949,7 @@ macro(:handle_ecma_greatereqdyn) do |l, r| Phi(slow_res, fp1_res).any end -function(:EcmaGreatereqdyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaGreatereqdyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_greatereqdyn(a, b)) end @@ -963,7 +963,7 @@ macro(:handle_ecma_noteqdyn) do |l, r| Phi(slow_res, fp1_res).any end -function(:EcmaNoteqdyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaNoteqdyn, params: {'a'=>'any', 'b'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_noteqdyn(a, b)) end @@ -973,27 +973,37 @@ macro(:handle_ecma_ldlexenvdyn) do || lexical_env.any end -#function(:EcmaLdlexenvdyn, params: {}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +#function(:EcmaLdlexenvdyn, params: {}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do # Return(handle_ecma_ldlexenvdyn()) # end -function(:EcmaLdnull, params: {}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +macro(:handle_ecma_throwundefinedifhole) do |id, obj| + IfImm(cmpanyhole(obj)).Imm(0).CC(:CC_NE).b { + ecma_intrinsic_invoke("ThrowUndefinedIfHoleSlow", id, obj) + } +end + +function(:EcmaThrowundefinedifhole, params: {'id'=>'i32', 'obj'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do + Return(handle_ecma_throwundefinedifhole(id, obj)) +end + +function(:EcmaLdnull, params: {}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(Constants::TAGGED_NULL) end -function(:EcmaLdhole, params: {}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaLdhole, params: {}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(Constants::TAGGED_HOLE) end -function(:EcmaLdundefined, params: {}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaLdundefined, params: {}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(Constants::TAGGED_UNDEFINED) end -function(:EcmaLdinfinity, params: {}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaLdinfinity, params: {}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(Constants::TAGGED_INFINITY) end -function(:EcmaLdnan, params: {}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaLdnan, params: {}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(Constants::TAGGED_NAN_VALUE) end @@ -1058,7 +1068,7 @@ macro(:handle_ecma_getnextpropname) do |iter| Phi(pc_slow_path, pc_fast_path).any end -function(:EcmaGetnextpropname, params: {'a'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaGetnextpropname, params: {'a'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_getnextpropname(a)) end @@ -1075,7 +1085,7 @@ macro(:handle_ecma_negate) do |arg| booltoany(AndI(Not(any_extractBoolean(arg)).b).Imm(1).b) end -function(:EcmaNegate, params: {'a'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaNegate, params: {'a'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_negate(a)) end @@ -1083,15 +1093,15 @@ macro(:handle_ecma_isundefined) do |arg| booltoany(cmpanyundefined(arg)) end -function(:EcmaIsundefined, params: {'a'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaIsundefined, params: {'a'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_isundefined(a)) end -function(:EcmaLdtrue, params: {}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaLdtrue, params: {}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(Constants::TAGGED_TRUE) end -function(:EcmaLdfalse, params: {}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaLdfalse, params: {}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(Constants::TAGGED_FALSE) end @@ -1516,7 +1526,7 @@ macro(:handle_ecma_ldobjbyindex) do |index, obj| Phi(res, slow_res_exception).any end -function(:EcmaLdobjbyindex, params: {'index'=>'i32', 'obj'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaLdobjbyindex, params: {'index'=>'i32', 'obj'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_ldobjbyindex(index, obj)) end @@ -1531,7 +1541,7 @@ macro(:handle_ecma_stobjbyindex) do |index, obj, value| } end -function(:EcmaStobjbyindex, params: {'index'=>'i32', 'obj'=>'any', 'value'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaStobjbyindex, params: {'index'=>'i32', 'obj'=>'any', 'value'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do handle_ecma_stobjbyindex(index, obj, value) ReturnVoid() end @@ -1547,7 +1557,7 @@ macro(:handle_ecma_stownbyindex) do |index, obj, value| } end -function(:EcmaStownbyindex, params: {'index'=>'i32', 'obj'=>'any', 'value'=>'any'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaStownbyindex, params: {'index'=>'i32', 'obj'=>'any', 'value'=>'any'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do handle_ecma_stownbyindex(index, obj, value) ReturnVoid() end @@ -1568,13 +1578,13 @@ macro(:handle_ecma_ldobjbyvalue) do |obj, key, ic_slot| Phi(res, slow_res_exception).any end -function(:EcmaLdobjbyvalue, params: {'obj'=>'any', 'key'=>'any', 'ic_slot'=>'i32'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaLdobjbyvalue, params: {'obj'=>'any', 'key'=>'any', 'ic_slot'=>'i32'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_ldobjbyvalue(obj, key, ic_slot)) end function(:FastPathLdObjByValue, params: {obj: 'any', key: 'any', ic_slot: 'i32'}, - mode: [:FastPath, :DynamicMethod], + mode: [:FastPath, :DynamicMethod, :DynamicStub], regmap: $full_regmap, regalloc_set: RegMask.new($full_regmap, :arg0, :arg1) + $panda_callees_mask - $panda_regmap) do # Arm32 is not supported @@ -1608,14 +1618,14 @@ macro(:handle_ecma_stobjbyvalue) do |obj, key, value, ic_slot| } end -function(:EcmaStobjbyvalue, params: {'obj'=>'any', 'key'=>'any', 'value'=>'any', 'ic_slot'=>'i32'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaStobjbyvalue, params: {'obj'=>'any', 'key'=>'any', 'value'=>'any', 'ic_slot'=>'i32'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do handle_ecma_stobjbyvalue(obj, key, value, ic_slot) ReturnVoid() end function(:FastPathStObjByValue, params: {obj: 'any', key: 'any', value: 'any', ic_slot: 'i32'}, - mode: [:FastPath, :DynamicMethod], + mode: [:FastPath, :DynamicMethod, :DynamicStub], regmap: $full_regmap, regalloc_set: RegMask.new($full_regmap, :arg0, :arg1) + $panda_callees_mask - $panda_regmap, validate: { spills_count_max: { default: 4, arm32: 9999 } } ) do @@ -1659,13 +1669,13 @@ macro(:handle_ecma_ldobjbyname) do |obj, id, ic_slot| Phi(res, slow_res_exception).any end -function(:EcmaLdobjbyname, params: {'id'=>'i32', 'obj'=>'any','ic_slot'=>'i32'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaLdobjbyname, params: {'id'=>'i32', 'obj'=>'any','ic_slot'=>'i32'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_ldobjbyname(obj, id, ic_slot)) end function(:FastPathLdObjByName, params: {id: 'i32', obj: 'any', ic_slot: 'i32'}, - mode: [:FastPath, :DynamicMethod], + mode: [:FastPath, :DynamicMethod, :DynamicStub], regmap: $full_regmap, regalloc_set: RegMask.new($full_regmap, :arg0, :arg1) + $panda_callees_mask - $panda_regmap) do # Arm32 is not supported @@ -1701,14 +1711,14 @@ macro(:handle_ecma_stobjbyname) do |obj, id, value, ic_slot| } end -function(:EcmaStobjbyname, params: {'id'=>'i32', 'obj'=>'any', 'value'=>'any', 'ic_slot'=>'i32'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaStobjbyname, params: {'id'=>'i32', 'obj'=>'any', 'value'=>'any', 'ic_slot'=>'i32'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do handle_ecma_stobjbyname(obj, id, value, ic_slot) ReturnVoid() end function(:FastPathStObjByName, params: {id: 'i32', obj: 'any', value: 'any', ic_slot: 'i32'}, - mode: [:FastPath, :DynamicMethod], + mode: [:FastPath, :DynamicMethod, :DynamicStub], regmap: $full_regmap, regalloc_set: RegMask.new($full_regmap, :arg0, :arg1) + $panda_callees_mask - $panda_regmap, validate: { spills_count_max: { default: 4, arm32: 9999 } } ) do @@ -1744,7 +1754,7 @@ macro(:handle_ecma_tryldglobalbyname) do |id, ic_slot| Phi(res0, res1).any end -function(:EcmaTryldglobalbyname, params: {'id'=>'i32', 'ic_slot'=>'i32'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaTryldglobalbyname, params: {'id'=>'i32', 'ic_slot'=>'i32'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_tryldglobalbyname(id, ic_slot)) end @@ -1762,13 +1772,13 @@ macro(:handle_ecma_ldglobalvar) do |id, ic_slot| Phi(res0, res1).any end -function(:EcmaLdglobalvar, params: {'id'=>'i32', 'ic_slot'=>'i32'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaLdglobalvar, params: {'id'=>'i32', 'ic_slot'=>'i32'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do Return(handle_ecma_ldglobalvar(id, ic_slot)) end function(:FastPathLdGlobalVar, params: {id: 'i32', ic_slot: 'i32'}, - mode: [:FastPath, :DynamicMethod], + mode: [:FastPath, :DynamicMethod, :DynamicStub], regmap: $full_regmap, regalloc_set: RegMask.new($full_regmap, :arg0, :arg1) + $panda_callees_mask - $panda_regmap) do # Arm32 is not supported @@ -1796,14 +1806,14 @@ macro(:handle_ecma_stglobalvar) do |id, value, ic_slot| } end -function(:EcmaStglobalvar, params: {'id'=>'i32', 'value'=>'any', 'ic_slot'=>'i32'}, mode: [:Interpreter, :DynamicMethod], enable_builder: true) do +function(:EcmaStglobalvar, params: {'id'=>'i32', 'value'=>'any', 'ic_slot'=>'i32'}, mode: [:Interpreter, :DynamicMethod, :DynamicStub], enable_builder: true) do handle_ecma_stglobalvar(id, value, ic_slot) ReturnVoid() end function(:FastPathStGlobalVar, params: {id: 'i32', value: 'any', ic_slot: 'i32'}, - mode: [:FastPath, :DynamicMethod], + mode: [:FastPath, :DynamicMethod, :DynamicStub], regmap: $full_regmap, regalloc_set: RegMask.new($full_regmap, :arg0, :arg1) + $panda_callees_mask - $panda_regmap) do # Arm32 is not supported diff --git a/irtoc_scripts/interpreter_main_loop.irt b/irtoc_scripts/interpreter_main_loop.irt index b23e7bdfa..af23ad81c 100644 --- a/irtoc_scripts/interpreter_main_loop.irt +++ b/irtoc_scripts/interpreter_main_loop.irt @@ -239,7 +239,7 @@ when "ECMA_CALLIRANGEDYN_PREF_IMM16_V8" ecma_intrinsic_check_setacc("CalliRangeDynInterp", i.format.size, i8tou16(as_imm(op[0])), vreg_ptr(op[1])) when "ECMA_NEWOBJDYNRANGE_PREF_IMM16_V8" - ecma_intrinsic_setacc("NewobjDynrange", i8tou16(as_imm(op[0])), vreg_ptr(op[1])) + ecma_intrinsic_setacc("NewobjDynrangeInterp", i8tou16(as_imm(op[0])), vreg_ptr(op[1])) when "ECMA_SUPERCALL_PREF_IMM16_V8" method_ptr := LoadI(%frame).Imm(Constants::FRAME_METHOD_OFFSET).ptr num_vregs := u32toword(read_uleb(method_file_data(method_ptr))) diff --git a/isa/isa.yaml b/isa/isa.yaml index d20245080..aedb4fe55 100644 --- a/isa/isa.yaml +++ b/isa/isa.yaml @@ -495,7 +495,7 @@ groups: acc: in:top prefix: ecma format: [pref_op_id_32] - properties: [string_id] + properties: [string_id, inlinable] intrinsic_name: INTRINSIC_THROW_UNDEFINED_IF_HOLE - sig: ecma.call1dyn v1:in:top, v2:in:top acc: out:top diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 577ad2ccd..5f4cff34d 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -16,12 +16,12 @@ panda_promote_to_definitions(PANDA_ECMASCRIPT_ENABLE_RUNTIME_STAT) set(ECMA_SRC_DIR ${PANDA_ECMASCRIPT_PLUGIN_SOURCE}/runtime) if(PANDA_TARGET_ARM32) - SET(BUILTIN_BRIDGE_SOURCE ${ECMA_SRC_DIR}/arch/arm/builtin_bridge_arm.S) + SET(BUILTIN_BRIDGE_SOURCE ${ECMA_SRC_DIR}/bridge/arch/arm/builtin_bridge_arm.S) elseif(PANDA_TARGET_ARM64) - SET(BUILTIN_BRIDGE_SOURCE ${ECMA_SRC_DIR}/arch/aarch64/builtin_bridge_aarch64.S) + SET(BUILTIN_BRIDGE_SOURCE ${ECMA_SRC_DIR}/bridge/arch/aarch64/builtin_bridge_aarch64.S) elseif(PANDA_TARGET_X86) elseif(PANDA_TARGET_AMD64) - SET(BUILTIN_BRIDGE_SOURCE ${ECMA_SRC_DIR}/arch/amd64/builtin_bridge_amd64.S) + SET(BUILTIN_BRIDGE_SOURCE ${ECMA_SRC_DIR}/bridge/arch/amd64/builtin_bridge_amd64.S) endif() set(ECMA_GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") diff --git a/runtime/asm_defines/asm_defines.def b/runtime/asm_defines/asm_defines.def index c0fca877e..53a5d60e2 100644 --- a/runtime/asm_defines/asm_defines.def +++ b/runtime/asm_defines/asm_defines.def @@ -2,7 +2,11 @@ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. */ +DEFINE_VALUE(ECMASCRIPT_ENVIRONMENT_SIZE, panda::ecmascript::EcmascriptEnvironment::GetSize()) +DEFINE_VALUE(ECMASCRIPT_ENVIRONMENT_PREV_ENVIRONMENT_OFFSET, panda::ecmascript::EcmascriptEnvironment::GetPrevEnvironmentOffset()) +DEFINE_VALUE(ECMASCRIPT_ENVIRONMENT_CONSTANT_POOL_OFFSET, panda::ecmascript::EcmascriptEnvironment::GetConstantPoolOffset()) DEFINE_VALUE(ECMASCRIPT_ENVIRONMENT_LEXICAL_ENV_OFFSET, panda::ecmascript::EcmascriptEnvironment::GetLexicalEnvOffset()) +DEFINE_VALUE(ECMASCRIPT_ENVIRONMENT_THIS_FUNC_OFFSET, panda::ecmascript::EcmascriptEnvironment::GetThisFuncOffset()) DEFINE_VALUE(JSTYPE_JS_OBJECT_BEGIN, static_cast(panda::ecmascript::JSType::JS_OBJECT_BEGIN)) DEFINE_VALUE(JSTYPE_JS_OBJECT_END, static_cast(panda::ecmascript::JSType::JS_OBJECT_END)) DEFINE_VALUE(JSTYPE_STRING, static_cast(panda::ecmascript::JSType::STRING)) @@ -21,7 +25,7 @@ DEFINE_VALUE(JSHCLASS_BITFIELD_OFFSET, panda::ecmascript::JSHClass::BIT_FIELD_OF DEFINE_VALUE(JSHCLASS_BITFIELD_TYPE_MASK, panda::ecmascript::JSHClass::ObjectTypeBits::MaxValue()) DEFINE_VALUE(JSHCLASS_BITFIELD_TYPE_START_BIT, panda::ecmascript::JSHClass::ObjectTypeBits::START_BIT) DEFINE_VALUE(JSHCLASS_BITFIELD_IS_DICTIONARY_START_BIT, panda::ecmascript::JSHClass::IsDictionaryBit::START_BIT) -DEFINE_VALUE(JSHCLASS_BITFIELD_CONSTRUCTOR_START_BIT, panda::ecmascript::JSHClass::ConstructorBit::START_BIT) +DEFINE_VALUE(JSHCLASS_BITFIELD_CLASS_CONSTRUCTOR_START_BIT, panda::ecmascript::JSHClass::ClassConstructorBit::START_BIT) DEFINE_VALUE(JSHCLASS_BITFIELD_EXTENSIBLE_START_BIT, panda::ecmascript::JSHClass::ExtensibleBit::START_BIT) DEFINE_VALUE(JSHCLASS_BITFIELD_INLINED_PROPS_START_BITS_START_BIT, panda::ecmascript::JSHClass::InlinedPropsStartBits::START_BIT) DEFINE_VALUE(JSHCLASS_BITFIELD_INLINED_PROPS_START_BITS_MASK, panda::ecmascript::JSHClass::InlinedPropsStartBits::MaxValue()) @@ -31,6 +35,10 @@ DEFINE_VALUE(JSOBJECT_ELEMENTS_OFFSET, panda::ecmascript::JSObject::ELEMENTS_OFF DEFINE_VALUE(JSARRAY_LENGTH_OFFSET, panda::ecmascript::JSArray::LENGTH_OFFSET) DEFINE_VALUE(JSFUNCTION_METHOD_OFFSET, panda::ecmascript::JSFunction::METHOD_OFFSET) DEFINE_VALUE(JSFUNCTION_PROFILE_TYPE_INFO_OFFSET, panda::ecmascript::JSFunction::PROFILE_TYPE_INFO_OFFSET) +DEFINE_VALUE(JSFUNCTION_CONSTANT_POOL_OFFSET, panda::ecmascript::JSFunction::CONSTANT_POOL_OFFSET) +DEFINE_VALUE(JSFUNCTION_LEXICAL_ENV_OFFSET, panda::ecmascript::JSFunction::LEXICAL_ENV_OFFSET) +DEFINE_VALUE(JSFUNCTION_FUNCTION_INFO_FLAG_OFFSET, panda::ecmascript::JSFunction::FUNCTION_INFO_FLAG_OFFSET) +DEFINE_VALUE(JSFUNCTION_FUNCTION_INFO_FLAG_IS_STRICT_START_BIT, panda::ecmascript::JSFunction::StrictBit::START_BIT) DEFINE_VALUE(JSPROPERTY_BOX_VALUE_OFFSET, panda::ecmascript::PropertyBox::VALUE_OFFSET) DEFINE_VALUE(JSTRANSITION_HANDLER_HANDLER_INFO_OFFSET, panda::ecmascript::TransitionHandler::HANDLER_INFO_OFFSET) DEFINE_VALUE(JSTRANSITION_HANDLER_HCLASS_OFFSET, panda::ecmascript::TransitionHandler::TRANSITION_HCLASS_OFFSET) diff --git a/runtime/bridge.h b/runtime/bridge.h index cebc91152..fbecbf3a9 100644 --- a/runtime/bridge.h +++ b/runtime/bridge.h @@ -20,7 +20,8 @@ namespace panda { -extern "C" DecodedTaggedValue CompiledCodeToBuiltinBridge(Method *, uint32_t, DecodedTaggedValue *, ...); +// Uses DynCall calling convention +extern "C" DecodedTaggedValue CompiledCodeToBuiltinBridge(); } // namespace panda diff --git a/runtime/arch/aarch64/builtin_bridge_aarch64.S b/runtime/bridge/arch/aarch64/builtin_bridge_aarch64.S similarity index 86% rename from runtime/arch/aarch64/builtin_bridge_aarch64.S rename to runtime/bridge/arch/aarch64/builtin_bridge_aarch64.S index d92f90137..951a80b2d 100644 --- a/runtime/arch/aarch64/builtin_bridge_aarch64.S +++ b/runtime/bridge/arch/aarch64/builtin_bridge_aarch64.S @@ -16,11 +16,10 @@ #include "arch/asm_support.h" #include "arch/aarch64/helpers_aarch64.S" -// DecodedTaggedValue InvokeBuiltin(ManagedThread* thread, Method* method, uint32_t num_args, -// DecodedTaggedValue* gpr_args, DecodedTaggedValue* stack_args) +// extern "C" uint64_t InvokeBuiltin(JSThread *thread, Method *method, uint32_t numArgs, JSTaggedValue *stackArgs) .extern InvokeBuiltin -// DecodedTaggedValue CompiledCodeToBuiltinBridge(Method* method, uint32_t num_args, DecodedTaggedValue func_obj, ...); +// DecodedTaggedValue CompiledCodeToBuiltinBridge, follows DynamicMethod calling convention .global CompiledCodeToBuiltinBridge .type CompiledCodeToBuiltinBridge, %function CompiledCodeToBuiltinBridge: @@ -69,18 +68,17 @@ CompiledCodeToBuiltinBridge: CFI_REL_OFFSET(d8, -((CFRAME_CALLEE_REGS_START_SLOT + 17) * 8)) // save arguments to the stack - // stack walker will read them during stack unwinding - PUSH_ARGS_REGS + sub sp, sp, 6 * 8 // 6 unused caller gp + stp x0, x1, [sp, #-16]! - mov w2, w1 + mov x2, x1 mov x1, x0 mov x0, THREAD_REG - add x3, sp, #16 // skip Method* and uint32_t num_args arguments - add x4, fp, #16 + add x3, fp, #16 // pointer to stackArgs bl InvokeBuiltin - add sp, sp, #64 // skip args regs + add sp, sp, 8 * 8 // skip caller gp POP_CALLEE_REGS sp CFI_RESTORE(THREAD_REG) CFI_RESTORE(x27) diff --git a/runtime/bridge/arch/aarch64/handle_call_ecma_N_v8_aarch64.S b/runtime/bridge/arch/aarch64/handle_call_ecma_N_v8_aarch64.S index 0d95ea155..f5cb6ba01 100644 --- a/runtime/bridge/arch/aarch64/handle_call_ecma_N_v8_aarch64.S +++ b/runtime/bridge/arch/aarch64/handle_call_ecma_N_v8_aarch64.S @@ -20,11 +20,53 @@ // regs set as follow // x9 - frame.vregs, x10 - insn_ptr, x12 - method, x15 - number of passed arguments, x13, x14 - temp - ldrb w13, [x10], #1 - add x13, x9, x13, lsl #3 // log2(FRAME_VREGISTER_SIZE) - ldr x13, [x13] + // w15 <- num_args // + new.target + calculated argument + add w15, w15, 2 - // Compute second argument in C++ code + // x13 <- func (v0) + ldrb w13, [x10, 0] + ldr x13, [x9, x13, lsl 3] + + // x14 <- resolved this + ldr w14, [x13, JSFUNCTION_FUNCTION_INFO_FLAG_OFFSET] + tbz w14, JSFUNCTION_FUNCTION_INFO_FLAG_IS_STRICT_START_BIT, 3f + mov w14, TAGGED_VALUE_UNDEFINED +1: + + // ABI arg reg 0 <- panda::Method* + // ABI arg reg 1 <- num_args + mov x0, x12 + mov w1, w15 + + // Reserve stack args + // x12 <- stack pointer + sub x12, sp, x15, lsl 3 + and x12, x12, -16 + mov sp, x12 + + // stack arg0 <- func (v0) + // stack arg1 <- new_target (undefined) + // stack arg3 <- resolved this + str x13, [x12, 0 * 8] + mov x13, TAGGED_VALUE_UNDEFINED + str x13, [x12, 1 * 8] + str x14, [x12, 2 * 8] + + subs w15, w15, 3 + beq .Linvoke + + add x12, x12, ((3 - 1) * 8) +2: + ldrb w13, [x10, x15] + ldr x13, [x9, x13, lsl 3] + str x13, [x12, x15, lsl 3] + subs x15, x15, 1 + bhi 2b + + b .Linvoke + +3: + // !IsStrict slowpath stp x9, x10, [sp, #-16]! stp x12, x13, [sp, #-16]! stp x14, x15, [sp, #-16]! @@ -33,40 +75,5 @@ ldp x14, x15, [sp], #16 ldp x12, x13, [sp], #16 ldp x9, x10, [sp], #16 - - // ABI arg reg 1 (x1) <- number of arguments - add x1, x15, #2 // + new.target + calculated argument - // ABI arg reg 2 (x2) <- functional object - mov x2, x13 - sub w15, w15, #1 - // ABI arg reg 3 (x3) <- new.target (undefined for now) - mov x3, #TAGGED_VALUE_UNDEFINED - // ABI arg reg 4 (x4) <- computed - mov x4, x0 - // ABI arg reg 0 (x0) <- panda::Method* - mov x0, x12 - cbz w15, .Linvoke - - // ABI arg reg 5 (x5) <- boxed arg0 from user code - ldrb w13, [x10], #1 - add x13, x9, x13, lsl #3 // log2(FRAME_VREGISTER_SIZE) - ldr x5, [x13] - sub w15, w15, #1 - cbz w15, .Linvoke - - // ABI arg reg 6 (x6) <- boxed arg1 from user code - ldrb w13, [x10], #1 - add x13, x9, x13, lsl #3 // log2(FRAME_VREGISTER_SIZE) - ldr x6, [x13] - sub w15, w15, #1 - cbz w15, .Linvoke - - // ABI arg reg 7 (x7) <- boxed arg2 from user code - ldrb w13, [x10], #1 - add x13, x9, x13, lsl #3 // log2(FRAME_VREGISTER_SIZE) - ldr x7, [x13] - sub w15, w15, #1 - cbz w15, .Linvoke - - // Unreachable, other handler will be used in case of larger number of argument - b .Linvoke + mov x14, x0 + b 1b diff --git a/runtime/bridge/arch/aarch64/handle_call_ecma_callirangedyn_pref_imm16_v8_aarch64.S b/runtime/bridge/arch/aarch64/handle_call_ecma_callirangedyn_pref_imm16_v8_aarch64.S index e04684d37..4e8573464 100644 --- a/runtime/bridge/arch/aarch64/handle_call_ecma_callirangedyn_pref_imm16_v8_aarch64.S +++ b/runtime/bridge/arch/aarch64/handle_call_ecma_callirangedyn_pref_imm16_v8_aarch64.S @@ -20,56 +20,78 @@ // regs set as follow // x9 - frame.vregs, x10 - insn_ptr, x12 - method, x13-x15 - temp - ldrh w14, [x10], #2 + // w15 <- num_args + ldrh w15, [x10, 0] + add w15, w15, 3 // func + new.target + resolved this - ldrb w15, [x10], #1 - add x9, x9, x15, lsl #3 // log2(FRAME_VREGISTER_SIZE) - ldr x13, [x9], #FRAME_VREGISTER_SIZE + // x9 <- range in frame.vregs + ldrb w13, [x10, 2] + add x9, x9, x13, lsl 3 - // Compute second argument in C++ code - stp x9, x10, [sp, #-16]! - stp x12, x13, [sp, #-16]! - stp x14, x15, [sp, #-16]! - mov x0, x13 - bl EcmaResolveSecondArgument - ldp x14, x15, [sp], #16 - ldp x12, x13, [sp], #16 - ldp x9, x10, [sp], #16 + // x13 <- func (range0) + ldr x13, [x9, 0 * FRAME_VREGISTER_SIZE] - // ABI arg reg 1 (x1) <- number of arguments - add x1, x14, #3 // + functional object + new.target + calculated argument - // ABI arg reg 2 (x2) <- functional object - mov x2, x13 - // ABI arg reg 3 (x3) <- new.target (undefined for now) - mov x3, #TAGGED_VALUE_UNDEFINED - // ABI arg reg 4 (x4) <- computed - mov x4, x0 - // ABI arg reg 0 (x0) <- panda::Method* + // x14 <- resolved this + ldr w14, [x13, JSFUNCTION_FUNCTION_INFO_FLAG_OFFSET] + tbz w14, JSFUNCTION_FUNCTION_INFO_FLAG_IS_STRICT_START_BIT, 3f + mov w14, TAGGED_VALUE_UNDEFINED +1: + + // ABI arg reg 0 <- panda::Method* + // ABI arg reg 1 <- num_args + // x14 <- resolved this + mov x14, x0 mov x0, x12 + mov w1, w15 + + // Reserve stack args + // x12 <- stack pointer + sub x12, sp, x15, lsl 3 + and x12, x12, -16 + mov sp, x12 - // There's at least 4 remaining arguments (number is in w14) - // ABI arg reg 5 (x5) <- boxed arg0 from user code - ldr x5, [x9], #FRAME_VREGISTER_SIZE - sub w14, w14, #1 + // stack arg0 <- func (v0) + // stack arg1 <- new_target (undefined) + // stack arg3 <- resolved this + str x13, [x12, 0 * 8] + mov x13, TAGGED_VALUE_UNDEFINED + str x13, [x12, 1 * 8] + str x14, [x12, 2 * 8] - // ABI arg reg 6 (x6) <- boxed arg1 from user code - ldr x6, [x9], #FRAME_VREGISTER_SIZE - sub w14, w14, #1 + // There's at least 4 function arguments + // stack arg[3:6] <- range[1:4] + ldr x13, [x9, 1 * FRAME_VREGISTER_SIZE] + str x13, [x12, 3 * 8] + ldr x13, [x9, 2 * FRAME_VREGISTER_SIZE] + str x13, [x12, 4 * 8] + ldr x13, [x9, 3 * FRAME_VREGISTER_SIZE] + str x13, [x12, 5 * 8] + ldr x13, [x9, 4 * FRAME_VREGISTER_SIZE] + str x13, [x12, 6 * 8] - // ABI arg reg 7 (x7) <- boxed arg2 from user code - ldr x7, [x9], #FRAME_VREGISTER_SIZE - sub w14, w14, #1 + subs w15, w15, 7 + beq .Linvoke - // setup stack args - // reserve stack space - // x13 - stack pointer - sub x13, sp, x14, lsl #4 - mov sp, x13 - // copy arguments to the stack -.Larg_loop_: - ldr x10, [x9], #FRAME_VREGISTER_SIZE - str x10, [x13], #FRAME_VREGISTER_SIZE - sub w14, w14, #1 - cbnz w14, .Larg_loop_ + add x9, x9, 4 * FRAME_VREGISTER_SIZE + add x12, x12, 6 * 8 + lsl w15, w15, 3 +2: + ldr x13, [x9, x15] + str x13, [x12, x15] + subs w15, w15, FRAME_VREGISTER_SIZE + bhi 2b b .Linvoke + +3: + // !IsStrict slowpath + stp x9, x10, [sp, #-16]! + stp x12, x13, [sp, #-16]! + stp x14, x15, [sp, #-16]! + mov x0, x13 + bl EcmaResolveSecondArgument + ldp x14, x15, [sp], #16 + ldp x12, x13, [sp], #16 + ldp x9, x10, [sp], #16 + mov x14, x0 + b 1b diff --git a/runtime/bridge/arch/aarch64/handle_call_ecma_callithisrangedyn_pref_imm16_v8_aarch64.S b/runtime/bridge/arch/aarch64/handle_call_ecma_callithisrangedyn_pref_imm16_v8_aarch64.S index 4bd364436..3448a51cd 100644 --- a/runtime/bridge/arch/aarch64/handle_call_ecma_callithisrangedyn_pref_imm16_v8_aarch64.S +++ b/runtime/bridge/arch/aarch64/handle_call_ecma_callithisrangedyn_pref_imm16_v8_aarch64.S @@ -17,51 +17,45 @@ // regs set as follow // x9 - frame.vregs, x10 - insn_ptr, x12 - method, x13-x15 - temp - // ABI arg reg 0 (x0) <- panda::Method* - mov x0, x12 - - ldrh w14, [x10], #2 - // ABI arg reg 1 (x1) <- number of arguments - add x1, x14, #2 // + functional object + new.target - - // ABI arg reg 2 (x2) <- functional object - ldrb w15, [x10], #1 - add x9, x9, x15, lsl #3 // log2(FRAME_VREGISTER_SIZE) - ldr x2, [x9], #FRAME_VREGISTER_SIZE - - // ABI arg reg 3 (x3) <- new.target (undefined for now) - mov x3, #TAGGED_VALUE_UNDEFINED + // w15 <- num_args + ldrh w15, [x10, 0] + add w15, w15, 2 // func + new.target - // ABI arg reg 4 (x4) <- this - ldr x4, [x9], #FRAME_VREGISTER_SIZE - sub w14, w14, #1 - cbz w14, .Linvoke + // x9 <- range in frame.vregs + ldrb w13, [x10, 2] + add x9, x9, x13, lsl 3 - // ABI arg reg 5 (x5) <- boxed arg0 from user code - ldr x5, [x9], #FRAME_VREGISTER_SIZE - sub w14, w14, #1 - cbz w14, .Linvoke - - // ABI arg reg 6 (x6) <- boxed arg1 from user code - ldr x6, [x9], #FRAME_VREGISTER_SIZE - sub w14, w14, #1 - cbz w14, .Linvoke - - // ABI arg reg 7 (x7) <- boxed arg2 from user code - ldr x7, [x9], #FRAME_VREGISTER_SIZE - sub w14, w14, #1 - cbz w14, .Linvoke - - // setup stack args - // reserve stack space - // x13 - stack pointer - sub x13, sp, x14, lsl #4 - mov sp, x13 - // copy arguments to the stack -.Larg_loop: - ldr x10, [x9], #FRAME_VREGISTER_SIZE - str x10, [x13], #FRAME_VREGISTER_SIZE - sub w14, w14, #1 - cbnz w14, .Larg_loop + // ABI arg reg 0 <- panda::Method* + // ABI arg reg 1 <- num_args + mov x0, x12 + mov w1, w15 + + // Reserve stack args + // x12 <- stack pointer + sub x12, sp, x15, lsl 3 + and x12, x12, -16 + mov sp, x12 + + // stack arg0 <- func (range0) + // stack arg1 <- new_target (undefined) + // stack arg3 <- this (range1) + ldr x13, [x9, 0 * FRAME_VREGISTER_SIZE] + str x13, [x12, 0 * 8] + mov x13, TAGGED_VALUE_UNDEFINED + str x13, [x12, 1 * 8] + ldr x13, [x9, 1 * FRAME_VREGISTER_SIZE] + str x13, [x12, 2 * 8] + + subs w15, w15, 3 + beq .Linvoke + + add x9, x9, 1 * FRAME_VREGISTER_SIZE + add x12, x12, 2 * 8 + lsl w15, w15, 3 +1: + ldr x13, [x9, x15] + str x13, [x12, x15] + subs w15, w15, FRAME_VREGISTER_SIZE + bhi 1b b .Linvoke diff --git a/runtime/arch/amd64/builtin_bridge_amd64.S b/runtime/bridge/arch/amd64/builtin_bridge_amd64.S similarity index 80% rename from runtime/arch/amd64/builtin_bridge_amd64.S rename to runtime/bridge/arch/amd64/builtin_bridge_amd64.S index c5be19d8c..7fff4e6f0 100644 --- a/runtime/arch/amd64/builtin_bridge_amd64.S +++ b/runtime/bridge/arch/amd64/builtin_bridge_amd64.S @@ -17,11 +17,10 @@ #include "arch/asm_support.h" #include "arch/amd64/helpers_amd64.S" -// DecodedTaggedValue InvokeBuiltin(ManagedThread* thread, Method* method, uint32_t num_args, -// DecodedTaggedValue* gpr_args, DecodedTaggedValue* stack_args) +// extern "C" uint64_t InvokeBuiltin(JSThread *thread, Method *method, uint32_t numArgs, JSTaggedValue *stackArgs) .extern InvokeBuiltin -// DecodedTaggedValue CompiledCodeToBuiltinBridge(Method* method, uint32_t num_args, DecodedTaggedValue func_obj, ...); +// DecodedTaggedValue CompiledCodeToBuiltinBridge, follows DynamicMethod calling convention .global CompiledCodeToBuiltinBridge .type CompiledCodeToBuiltinBridge, %function CompiledCodeToBuiltinBridge: @@ -60,21 +59,14 @@ CompiledCodeToBuiltinBridge: CFI_REL_OFFSET(rbx, -((CFRAME_CALLEE_REGS_START_SLOT + 4) * 8)) // save arguments to the stack - // stack walker will read them during stack unwinding - pushq %r9 - pushq %r8 - pushq %rcx - pushq %rdx - pushq %rsi - pushq %rdi - - sub $8, %rsp // make %rsp 16 bytes aligned + subq $(7 * 8), %rsp // 6 caller gp + alignment + movq %rdi, (1 * 8)(%rsp) + movq %rsi, (2 * 8)(%rsp) movl %esi, %edx movq %rdi, %rsi movq %THREAD_REG, %rdi - leaq 24(%rsp), %rcx // skip Method* and uint32_t num_args arguments - leaq 16(%rbp), %r8 // skip return address + leaq 16(%rbp), %rcx // pointer to stackArgs callq InvokeBuiltin@plt diff --git a/runtime/bridge/arch/amd64/handle_call_ecma_N_v8_amd64.S b/runtime/bridge/arch/amd64/handle_call_ecma_N_v8_amd64.S index 18fed7d08..9654999f5 100644 --- a/runtime/bridge/arch/amd64/handle_call_ecma_N_v8_amd64.S +++ b/runtime/bridge/arch/amd64/handle_call_ecma_N_v8_amd64.S @@ -20,70 +20,56 @@ // regs set as follow // %rax - insn_ptr, %rbx - frame.vregs, %r12 - method, %r15 - number of passed arguments, %r13, %r14 - temp - movzbl (%rax), %r13d - addq $1, %rax - shlq $3, %r13 // log2(FRAME_VREGISTER_SIZE) - movq (%rbx,%r13), %r13 + // r15d <- num_args // + new.target + calculated argument + addl $2, %r15d - movq %rax, %r14 - movq %r13, %rdi - callq EcmaResolveSecondArgument@plt + // r13 <- func (v0) + movzbl 0(%rax), %r13d + movq (%rbx, %r13, FRAME_VREGISTER_SIZE), %r13 + + // r14 <- resolved this + movl JSFUNCTION_FUNCTION_INFO_FLAG_OFFSET(%r13), %r14d + andl $(1 << JSFUNCTION_FUNCTION_INFO_FLAG_IS_STRICT_START_BIT), %r14d + jz 3f + movq $TAGGED_VALUE_UNDEFINED, %r14 +1: // ABI arg reg 0 (rdi) <- panda::Method* + // ABI arg reg 1 (rsi) <- num_args movq %r12, %rdi - - // ABI arg reg 1 (rsi) <- number of arguments movq %r15, %rsi - addq $2, %rsi // + new.target + calculated argument - - // ABI arg reg 2 (rdx) <- functional object - movq %r13, %rdx - subq $1, %r15 - - // ABI arg reg 3 (rcx) <- new.target (undefined for now) - movq $TAGGED_VALUE_UNDEFINED, %rcx - - // ABI arg reg 4 (r8) <- computed - movq %rax, %r8 - cmpq $0, %r15 - je .Linvoke - - movq %r14, %rax // restore - // ABI arg reg 5 (r9) <- boxed arg0 from user code - movzbl (%rax), %r13d - addq $1, %rax - shlq $3, %r13 // log2(FRAME_VREGISTER_SIZE) - movq (%rbx,%r13), %r9 - subq $1, %r15 - jz .Linvoke - - // setup stack args - // reserve stack space - // %r12 - stack pointer - movq %r15, %r12 - shlq $4, %r12 + // Reserve stack args + // %r12 <- stack pointer + leal (, %r15d, 8), %r12d subq %r12, %rsp + andq $-16, %rsp movq %rsp, %r12 - // ABI arg stack <- boxed arg1 from user code - movzbl (%rax), %r13d - addq $1, %rax - shlq $3, %r13 // log2(FRAME_VREGISTER_SIZE) - movq (%rbx,%r13), %r13 - movq %r13, (%r12) - subq $1, %r15 - jz .Linvoke + // stack arg0 <- func (v0) + // stack arg1 <- new_target (undefined) + // stack arg3 <- resolved this + movq %r13, (0 * 8)(%r12) + movq $TAGGED_VALUE_UNDEFINED, (1 * 8)(%r12) + movq %r14, (2 * 8)(%r12) - // ABI arg stack <- boxed arg2 from user code - addq $FRAME_VREGISTER_SIZE, %r12 - movzbl (%rax), %r13d - addq $1, %rax - shlq $3, %r13 // log2(FRAME_VREGISTER_SIZE) - movq (%rbx,%r13), %r13 - movq %r13, (%r12) - subq $1, %r15 + subl $3, %r15d jz .Linvoke - // Unreachable, other handler will be used in case of larger number of argument + addq $((3 - 1) * 8), %r12 +2: + movzbl (%rax, %r15), %r13d + movq (%rbx, %r13, FRAME_VREGISTER_SIZE), %r13 + movq %r13, (%r12, %r15, 8) + subl $1, %r15d + ja 2b + jmp .Linvoke + +3: + // !IsStrict slowpath + movq %rax, %r14 + movq %r13, %rdi + callq EcmaResolveSecondArgument@plt + jmp 1b + xchgq %rax, %r14 diff --git a/runtime/bridge/arch/amd64/handle_call_ecma_callirangedyn_pref_imm16_v8_amd64.S b/runtime/bridge/arch/amd64/handle_call_ecma_callirangedyn_pref_imm16_v8_amd64.S index 3ddb0b27e..2909e5793 100644 --- a/runtime/bridge/arch/amd64/handle_call_ecma_callirangedyn_pref_imm16_v8_amd64.S +++ b/runtime/bridge/arch/amd64/handle_call_ecma_callirangedyn_pref_imm16_v8_amd64.S @@ -18,56 +18,74 @@ // handle ecma.callirangedyn // regs set as follow -// %rax - insn_ptr, %rbx - frame.vregs, %r12 - method, %r13, %r14 - temp +// %rax - insn_ptr, %rbx - frame.vregs, %r12 - method, %r13, %r14, %r15 - temp - movzwl (%rax), %r14d - addq $2, %rax + // r15d <- num_args + movzwl 0(%rax), %r15d + addl $3, %r15d // func + new.target + resolved this - movzbl (%rax), %r13d - addq $1, %rax - shlq $3, %r13 // log2(FRAME_VREGISTER_SIZE) - addq %r13, %rbx - movq (%rbx), %r13 - addq $FRAME_VREGISTER_SIZE, %rbx + // rbx <- range in frame.vregs + movzbl 2(%rax), %r13d + leaq (%rbx, %r13, FRAME_VREGISTER_SIZE), %rbx - // Compute second argument in C++ code - movq %r13, %rdi - callq EcmaResolveSecondArgument@plt + // r13 <- func (range0) + movq (0 * FRAME_VREGISTER_SIZE)(%rbx), %r13 + + // r14 <- resolved this + // rax <- corrupted + movl JSFUNCTION_FUNCTION_INFO_FLAG_OFFSET(%r13), %r14d + andl $(1 << JSFUNCTION_FUNCTION_INFO_FLAG_IS_STRICT_START_BIT), %r14d + jz 3f + movq $TAGGED_VALUE_UNDEFINED, %r14 +1: // ABI arg reg 0 (rdi) <- panda::Method* + // ABI arg reg 1 (rsi) <- num_args movq %r12, %rdi - // ABI arg reg 1 (rsi) <- number of arguments - movq %r14, %rsi - addq $3, %rsi // + functional object + new.target + calculated argument + movq %r15, %rsi - // ABI arg reg 2 (rdx) <- functional object - movq %r13, %rdx + // Reserve stack args + // r12 <- stack pointer + leal (, %r15d, 8), %r12d + subq %r12, %rsp + andq $-16, %rsp + movq %rsp, %r12 - // ABI arg reg 3 (rcx) <- new.target (undefined for now) - movq $TAGGED_VALUE_UNDEFINED, %rcx + // stack arg0 <- func (range0) + // stack arg1 <- new_target (undefined) + // stack arg3 <- resolved this + movq %r13, (0 * 8)(%r12) + movq $TAGGED_VALUE_UNDEFINED, (1 * 8)(%r12) + movq %r14, (2 * 8)(%r12) - // ABI arg reg 4 (r8) <- computed - movq %rax, %r8 + // There's at least 4 function arguments + // stack arg[3:6] <- range[1:4] + movq (1 * FRAME_VREGISTER_SIZE)(%rbx), %r13 + movq %r13, (3 * 8)(%r12) + movq (2 * FRAME_VREGISTER_SIZE)(%rbx), %r13 + movq %r13, (4 * 8)(%r12) + movq (3 * FRAME_VREGISTER_SIZE)(%rbx), %r13 + movq %r13, (5 * 8)(%r12) + movq (4 * FRAME_VREGISTER_SIZE)(%rbx), %r13 + movq %r13, (6 * 8)(%r12) - // There's at least 4 remaining arguments (number is in %r14d) - movq (%rbx), %r9 - addq $FRAME_VREGISTER_SIZE, %rbx - subl $1, %r14d + subl $7, %r15d + jz .Linvoke - // setup stack args - // reserve stack space - // %r12 - stack pointer - movl %r14d, %r12d - shll $4, %r12d - subq %r12, %rsp - movq %rsp, %r12 - -.Larg_loop_: - movq (%rbx), %r13 - movq %r13, (%r12) - addq $FRAME_VREGISTER_SIZE, %rbx - addq $FRAME_VREGISTER_SIZE, %r12 - subl $1, %r14d - ja .Larg_loop_ + addq $(4 * FRAME_VREGISTER_SIZE), %rbx + addq $(6 * 8), %r12 + shll $3, %r15d +2: + movq (%rbx, %r15), %r13 + movq %r13, (%r12, %r15) + subl $FRAME_VREGISTER_SIZE, %r15d + ja 2b jmp .Linvoke + +3: + // !IsStrict slowpath + movq %r13, %rdi + callq EcmaResolveSecondArgument@plt + jmp 1b + movq %rax, %r14 diff --git a/runtime/bridge/arch/amd64/handle_call_ecma_callithisrangedyn_pref_imm16_v8_amd64.S b/runtime/bridge/arch/amd64/handle_call_ecma_callithisrangedyn_pref_imm16_v8_amd64.S index 9327c0640..5d3c56950 100644 --- a/runtime/bridge/arch/amd64/handle_call_ecma_callithisrangedyn_pref_imm16_v8_amd64.S +++ b/runtime/bridge/arch/amd64/handle_call_ecma_callithisrangedyn_pref_imm16_v8_amd64.S @@ -17,53 +17,45 @@ // regs set as follow // %rax - insn_ptr, %rbx - frame.vregs, %r12 - method, %r13, %r14, %r15 - temp - // ABI arg reg 0 (rdi) <- panda::Method* - movq %r12, %rdi - - movzwl (%rax), %r14d - addq $2, %rax + // r15d <- num_args + movzwl (%rax), %r15d + addl $2, %r15d // func + new.target - // ABI arg reg 1 (rsi) <- number of arguments - movq %r14, %rsi - addq $2, %rsi // + functional object + new.target + // rbx <- range in frame.vregs + movzbl 2(%rax), %r13d + leaq (%rbx, %r13, FRAME_VREGISTER_SIZE), %rbx - // ABI arg reg 2 (rdx) <- functional object - movzbl (%rax), %r13d - addq $1, %rax - shlq $3, %r13 // log2(FRAME_VREGISTER_SIZE) - addq %r13, %rbx - movq (%rbx), %rdx - addq $FRAME_VREGISTER_SIZE, %rbx + // ABI arg reg 0 (rdi) <- panda::Method* + // ABI arg reg 1 (rsi) <- num_args + movq %r12, %rdi + movq %r15, %rsi - // ABI arg reg 3 (rcx) <- new.target (undefined for now) - movq $TAGGED_VALUE_UNDEFINED, %rcx + // Reserve stack args + // r12 <- stack pointer + leal (, %r15d, 8), %r12d + subq %r12, %rsp + andq $-16, %rsp + movq %rsp, %r12 - // ABI arg reg 4 (r8) <- this - movq (%rbx), %r8 - addq $FRAME_VREGISTER_SIZE, %rbx - subl $1, %r14d - jz .Linvoke + // stack arg0 <- func (range0) + // stack arg1 <- new_target (undefined) + // stack arg3 <- this (range1) + movq (0 * FRAME_VREGISTER_SIZE)(%rbx), %r13 + movq %r13, (0 * 8)(%r12) + movq $TAGGED_VALUE_UNDEFINED, (1 * 8)(%r12) + movq (1 * FRAME_VREGISTER_SIZE)(%rbx), %r13 + movq %r13, (2 * 8)(%r12) - // ABI arg reg 5 (r9) <- boxed arg0 from user code - movq (%rbx), %r9 - addq $FRAME_VREGISTER_SIZE, %rbx - subl $1, %r14d + subl $3, %r15d jz .Linvoke - // setup stack args - // reserve stack space - // %r12 - stack pointer - movl %r14d, %r12d - shll $4, %r12d - subq %r12, %rsp - movq %rsp, %r12 - - .Larg_loop: - movq (%rbx), %r13 - movq %r13, (%r12) - addq $FRAME_VREGISTER_SIZE, %r12 - addq $FRAME_VREGISTER_SIZE, %rbx - subl $1, %r14d - ja .Larg_loop + addq $(1 * FRAME_VREGISTER_SIZE), %rbx + addq $(2 * 8), %r12 + shll $3, %r15d +1: + movq (%rbx, %r15), %r13 + movq %r13, (%r12, %r15) + subl $FRAME_VREGISTER_SIZE, %r15d + ja 1b jmp .Linvoke diff --git a/runtime/arch/arm/builtin_bridge_arm.S b/runtime/bridge/arch/arm/builtin_bridge_arm.S similarity index 100% rename from runtime/arch/arm/builtin_bridge_arm.S rename to runtime/bridge/arch/arm/builtin_bridge_arm.S diff --git a/runtime/compiler/ecmascript_runtime_interface.cpp b/runtime/compiler/ecmascript_runtime_interface.cpp index 500d03b7e..f840ddf3d 100644 --- a/runtime/compiler/ecmascript_runtime_interface.cpp +++ b/runtime/compiler/ecmascript_runtime_interface.cpp @@ -25,33 +25,30 @@ namespace panda::ecmascript { EcmaRuntimeInterface::EcmaRuntimeInterface(const EcmaVM *ecma_vm) : ecma_vm_(ecma_vm) {} -size_t EcmaRuntimeInterface::GetConstantPoolOffset() +size_t EcmaRuntimeInterface::GetLanguageExtensionSize([[maybe_unused]] Arch arch) const { - return ecmascript::JSFunction::GetOffsetConstantPool(); + return cross_values::GetEcmascriptEnvironmentSize(arch); } -size_t EcmaRuntimeInterface::GetLexicalEnvOffset() +std::string EcmaRuntimeInterface::GetMethodFullName(MethodPtr method, [[maybe_unused]] bool with_signature) const { - return ecmascript::JSFunction::GetOffsetLexicalEnv(); + ASSERT(panda::panda_file::IsDynamicLanguage(MethodCast(method)->GetClass()->GetSourceLang())); + return std::string(static_cast(MethodCast(method))->GetFullName()); } -bool EcmaRuntimeInterface::IsEcmascriptRuntime() +uint64_t EcmaRuntimeInterface::DynamicCastDoubleToInt(double value, size_t bits) const { - auto lang = Thread::GetCurrent()->GetVM()->GetLanguageContext().GetLanguage(); - return lang == panda_file::SourceLang::ECMASCRIPT; + return ecmascript::base::NumberHelper::DoubleToInt(value, bits); } -size_t EcmaRuntimeInterface::GetEcmascriptLanguageExtensionSize() +uint8_t EcmaRuntimeInterface::GetDynamicNumFixedArgs() const { - if (IsEcmascriptRuntime()) { - return panda::ecmascript::EcmascriptEnvironment::GetSize(); - } - return 0; + return 3; // func, new_target, this } uint32_t EcmaRuntimeInterface::GetFunctionTargetOffset([[maybe_unused]] Arch arch) const { - return ecmascript::JSFunction::METHOD_OFFSET; + return cross_values::GetJsfunctionMethodOffset(arch); } uintptr_t EcmaRuntimeInterface::GetGlobalVarAddress(MethodPtr method, size_t id) diff --git a/runtime/compiler/ecmascript_runtime_interface.h b/runtime/compiler/ecmascript_runtime_interface.h index 868d7c0b2..2ac6184c3 100644 --- a/runtime/compiler/ecmascript_runtime_interface.h +++ b/runtime/compiler/ecmascript_runtime_interface.h @@ -25,31 +25,18 @@ class EcmaVM; class EcmaRuntimeInterface : public PandaRuntimeInterface { public: explicit EcmaRuntimeInterface(const EcmaVM *ecma_vm); - size_t GetConstantPoolOffset() override; + size_t GetLanguageExtensionSize(Arch arch) const override; - size_t GetLexicalEnvOffset() override; + std::string GetMethodFullName(MethodPtr method, [[maybe_unused]] bool with_signature) const override; - bool IsEcmascriptRuntime() override; + uint64_t DynamicCastDoubleToInt(double value, size_t bits) const override; - size_t GetEcmascriptLanguageExtensionSize(); + uint8_t GetDynamicNumFixedArgs() const override; - size_t GetLanguageExtensionSize() override - { - size_t ext_size = 0; - ext_size = GetEcmascriptLanguageExtensionSize(); - - return ext_size; - } + uint32_t GetFunctionTargetOffset(Arch arch) const override; uintptr_t GetGlobalVarAddress(MethodPtr method, size_t id) override; - std::string GetMethodFullName(MethodPtr method, [[maybe_unused]] bool with_signature) const override - { - ASSERT(panda::panda_file::IsDynamicLanguage(MethodCast(method)->GetClass()->GetSourceLang())); - return std::string(static_cast(MethodCast(method))->GetFullName()); - } - - uint32_t GetFunctionTargetOffset(Arch arch) const override; uint32_t GetTlsGlobalObjectOffset(Arch arch) const override { return panda::cross_values::GetJsthreadGlobalObjectOffset(arch); diff --git a/runtime/ecma_runtime.yaml b/runtime/ecma_runtime.yaml index 0f203ec95..6a2b4fab1 100644 --- a/runtime/ecma_runtime.yaml +++ b/runtime/ecma_runtime.yaml @@ -189,6 +189,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::Add2Dyn + set_flags: [heap_inv] fast_path: FastPathEcmaAdd - name: Sub2Dyn @@ -201,6 +202,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::Sub2Dyn + set_flags: [heap_inv] fast_path: FastPathEcmaSub - name: Mul2Dyn @@ -213,6 +215,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::Mul2Dyn + set_flags: [heap_inv] fast_path: FastPathEcmaMul - name: Div2Dyn @@ -225,6 +228,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::Div2Dyn + set_flags: [heap_inv] fast_path: FastPathEcmaDiv - name: Mod2Dyn @@ -237,6 +241,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::Mod2Dyn + set_flags: [heap_inv] - name: EqDyn space: ecmascript @@ -248,6 +253,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::EqDyn + set_flags: [heap_inv] - name: NotEqDyn space: ecmascript @@ -259,6 +265,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::NotEqDyn + set_flags: [heap_inv] - name: LessDyn space: ecmascript @@ -270,6 +277,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::LessDyn + set_flags: [heap_inv] - name: LessEqDyn space: ecmascript @@ -281,6 +289,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::LessEqDyn + set_flags: [heap_inv] - name: GreaterDyn space: ecmascript @@ -292,6 +301,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::GreaterDyn + set_flags: [heap_inv] - name: GreaterEqDyn space: ecmascript @@ -303,6 +313,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::GreaterEqDyn + set_flags: [heap_inv] - name: LdObjByValue space: ecmascript @@ -315,6 +326,7 @@ intrinsics: args: [any, any, u16] impl: panda::ecmascript::intrinsics::LdObjByValue fast_path: FastPathLdObjByValue + set_flags: [heap_inv] - name: TryLdGlobalByValue space: ecmascript @@ -326,6 +338,7 @@ intrinsics: ret: any args: [u16, any] impl: panda::ecmascript::intrinsics::TryLdGlobalByValue + set_flags: [heap_inv] - name: StObjByValue space: ecmascript @@ -338,6 +351,7 @@ intrinsics: args: [any, any, acc, u16] impl: panda::ecmascript::intrinsics::StObjByValue fast_path: FastPathStObjByValue + set_flags: [heap_inv] - name: Shl2Dyn space: ecmascript @@ -349,6 +363,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::Shl2Dyn + set_flags: [heap_inv] fast_path: FastPathEcmaShl - name: Shr2Dyn @@ -361,6 +376,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::Shr2Dyn + set_flags: [heap_inv] fast_path: FastPathEcmaShr - name: Ashr2Dyn @@ -373,6 +389,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::Ashr2Dyn + set_flags: [heap_inv] - name: And2Dyn space: ecmascript @@ -384,6 +401,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::And2Dyn + set_flags: [heap_inv] fast_path: FastPathEcmaAnd - name: Or2Dyn @@ -396,6 +414,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::Or2Dyn + set_flags: [heap_inv] fast_path: FastPathEcmaOr - name: Xor2Dyn @@ -408,6 +427,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::Xor2Dyn + set_flags: [heap_inv] fast_path: FastPathEcmaXor - name: Tonumber @@ -420,6 +440,7 @@ intrinsics: ret: any args: [any] impl: panda::ecmascript::intrinsics::Tonumber + set_flags: [heap_inv] - name: NegDyn space: ecmascript @@ -431,6 +452,7 @@ intrinsics: ret: any args: [any] impl: panda::ecmascript::intrinsics::NegDyn + set_flags: [heap_inv] fast_path: FastPathEcmaNeg - name: NotDyn @@ -443,6 +465,7 @@ intrinsics: ret: any args: [any] impl: panda::ecmascript::intrinsics::NotDyn + set_flags: [heap_inv] fast_path: FastPathEcmaNot - name: IncDyn @@ -455,6 +478,7 @@ intrinsics: ret: any args: [any] impl: panda::ecmascript::intrinsics::IncDyn + set_flags: [heap_inv] fast_path: FastPathEcmaInc - name: DecDyn @@ -467,6 +491,7 @@ intrinsics: ret: any args: [any] impl: panda::ecmascript::intrinsics::DecDyn + set_flags: [heap_inv] fast_path: FastPathEcmaDec - name: RethrowDyn @@ -479,6 +504,7 @@ intrinsics: ret: any args: [acc] impl: panda::ecmascript::intrinsics::RethrowDyn + set_flags: [heap_inv] - name: ThrowDyn space: ecmascript @@ -501,6 +527,7 @@ intrinsics: ret: any args: [any, any] impl: panda::ecmascript::intrinsics::Delobjprop + set_flags: [heap_inv] - name: Defineglobalvar space: ecmascript @@ -562,8 +589,22 @@ intrinsics: exception: true signature: ret: any - args: [u16, any] + args: [u16, any, any] + stackrange: true impl: panda::ecmascript::intrinsics::NewobjDynrange + set_flags: [heap_inv] + +- name: NewobjDynrangeInterp + space: ecmascript + class_name: Ecmascript.Intrinsics + method_name: newobjDynrangeInterp + static: true + exception: true + signature: + ret: any + args: [u16, any] + impl: panda::ecmascript::intrinsics::NewobjDynrangeInterp + set_flags: [heap_inv] - name: RefeqDyn space: ecmascript @@ -585,6 +626,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::ExpDyn + set_flags: [heap_inv] - name: TypeofDyn space: ecmascript @@ -617,6 +659,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::IsinDyn + set_flags: [heap_inv] - name: InstanceofDyn space: ecmascript @@ -628,6 +671,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::InstanceofDyn + set_flags: [heap_inv] - name: StrictNotEqDyn space: ecmascript @@ -638,6 +682,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::StrictNotEqDyn + set_flags: [heap_inv] clear_flags: [no_dce] use_thread: false @@ -650,6 +695,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::StrictEqDyn + set_flags: [heap_inv] use_thread: false - name: NewobjspreadDyn @@ -662,6 +708,7 @@ intrinsics: ret: any args: [any, any, acc] impl: panda::ecmascript::intrinsics::NewobjspreadDyn + set_flags: [heap_inv] - name: CallspreadDyn space: ecmascript @@ -673,6 +720,7 @@ intrinsics: ret: any args: [any, any, any] impl: panda::ecmascript::intrinsics::CallspreadDyn + set_flags: [heap_inv] - name: JfalseDyn space: ecmascript @@ -804,6 +852,7 @@ intrinsics: ret: any args: [acc] impl: panda::ecmascript::intrinsics::Toboolean + set_flags: [heap_inv] clear_flags: [no_dce] use_thread: false @@ -1050,6 +1099,7 @@ intrinsics: signature: ret: any args: [any, acc] + set_flags: [heap_inv] impl: panda::ecmascript::intrinsics::AsyncFunctionAwait - name: AsyncFunctionResolve @@ -1061,6 +1111,7 @@ intrinsics: signature: ret: any args: [any, acc] + set_flags: [heap_inv] impl: panda::ecmascript::intrinsics::AsyncFunctionResolve - name: AsyncFunctionReject @@ -1072,6 +1123,7 @@ intrinsics: signature: ret: any args: [any, acc] + set_flags: [heap_inv] impl: panda::ecmascript::intrinsics::AsyncFunctionReject - name: AsyncGeneratorResolve @@ -1083,6 +1135,7 @@ intrinsics: signature: ret: any args: [any, acc] + set_flags: [heap_inv] impl: panda::ecmascript::intrinsics::AsyncGeneratorResolve - name: AsyncGeneratorReject @@ -1094,6 +1147,7 @@ intrinsics: signature: ret: any args: [any, acc] + set_flags: [heap_inv] impl: panda::ecmascript::intrinsics::AsyncGeneratorReject - name: ThrowUndefined @@ -1173,6 +1227,7 @@ intrinsics: ret: void args: [u16, any, acc] impl: panda::ecmascript::intrinsics::TryStGlobalByValue + set_flags: [heap_inv] - name: GetMethod space: ecmascript @@ -1184,6 +1239,7 @@ intrinsics: ret: any args: [string_id, any] impl: panda::ecmascript::intrinsics::GetMethod + set_flags: [heap_inv] - name: GetTemplateObject space: ecmascript @@ -1195,6 +1251,7 @@ intrinsics: ret: any args: [any] impl: panda::ecmascript::intrinsics::GetTemplateObject + set_flags: [heap_inv] - name: TryLdGlobalByName space: ecmascript @@ -1206,6 +1263,7 @@ intrinsics: ret: any args: [string_id, u16] impl: panda::ecmascript::intrinsics::TryLdGlobalByName + set_flags: [heap_inv] - name: TryStGlobalByName space: ecmascript @@ -1217,6 +1275,7 @@ intrinsics: ret: any args: [string_id, acc, u16] impl: panda::ecmascript::intrinsics::TryStGlobalByName + set_flags: [heap_inv] - name: LdGlobalVar space: ecmascript @@ -1229,6 +1288,7 @@ intrinsics: args: [string_id, u16] impl: panda::ecmascript::intrinsics::LdGlobalVar fast_path: FastPathLdGlobalVar + set_flags: [heap_inv] - name: StGlobalVar space: ecmascript @@ -1241,6 +1301,7 @@ intrinsics: args: [string_id, acc, u16] impl: panda::ecmascript::intrinsics::StGlobalVar fast_path: FastPathStGlobalVar + set_flags: [heap_inv] - name: StGlobalLet space: ecmascript @@ -1252,6 +1313,7 @@ intrinsics: ret: any args: [string_id, acc] impl: panda::ecmascript::intrinsics::StGlobalLet + set_flags: [heap_inv] - name: LdObjByName space: ecmascript @@ -1264,6 +1326,7 @@ intrinsics: args: [string_id, any, u16] impl: panda::ecmascript::intrinsics::LdObjByName fast_path: FastPathLdObjByName + set_flags: [heap_inv] - name: StObjByName space: ecmascript @@ -1276,6 +1339,7 @@ intrinsics: args: [string_id, any, acc, u16] impl: panda::ecmascript::intrinsics::StObjByName fast_path: FastPathStObjByName + set_flags: [heap_inv] - name: LdObjByIndex space: ecmascript @@ -1287,6 +1351,7 @@ intrinsics: ret: any args: [u32, any] impl: panda::ecmascript::intrinsics::LdObjByIndex + set_flags: [heap_inv] - name: StObjByIndex space: ecmascript @@ -1298,6 +1363,7 @@ intrinsics: ret: any args: [u32, any, acc] impl: panda::ecmascript::intrinsics::StObjByIndex + set_flags: [heap_inv] - name: GetNextPropName space: ecmascript @@ -1309,6 +1375,7 @@ intrinsics: ret: any args: [any] impl: panda::ecmascript::intrinsics::GetNextPropName + set_flags: [heap_inv] - name: ReturnUndefined space: ecmascript @@ -1330,6 +1397,7 @@ intrinsics: ret: any args: [any] impl: panda::ecmascript::intrinsics::Call0Dyn + set_flags: [heap_inv] - name: Call1Dyn space: ecmascript @@ -1341,6 +1409,7 @@ intrinsics: ret: any args: [any, any] impl: panda::ecmascript::intrinsics::Call1Dyn + set_flags: [heap_inv] - name: Call2Dyn space: ecmascript @@ -1352,6 +1421,7 @@ intrinsics: ret: any args: [any, any, any] impl: panda::ecmascript::intrinsics::Call2Dyn + set_flags: [heap_inv] - name: Call3Dyn space: ecmascript @@ -1363,6 +1433,7 @@ intrinsics: ret: any args: [any, any, any, any] impl: panda::ecmascript::intrinsics::Call3Dyn + set_flags: [heap_inv] - name: CalliRangeDyn space: ecmascript @@ -1374,6 +1445,7 @@ intrinsics: ret: any args: [u16, any] impl: panda::ecmascript::intrinsics::CalliRangeDyn + set_flags: [heap_inv] - name: CalliRangeDynInterp space: ecmascript @@ -1385,6 +1457,7 @@ intrinsics: ret: any args: [u16, any] impl: panda::ecmascript::intrinsics::CalliRangeDynInterp + set_flags: [heap_inv] - name: CalliThisRangeDyn space: ecmascript @@ -1396,6 +1469,7 @@ intrinsics: ret: any args: [u16, any] impl: panda::ecmascript::intrinsics::CalliThisRangeDyn + set_flags: [heap_inv] - name: CreateEmptyObject space: ecmascript @@ -1430,6 +1504,7 @@ intrinsics: ret: any args: [any, any] impl: panda::ecmascript::intrinsics::CopyDataProperties + set_flags: [heap_inv] - name: DefineGetterSetterByValue space: ecmascript @@ -1441,6 +1516,7 @@ intrinsics: ret: any args: [any, any, any, any, acc] impl: panda::ecmascript::intrinsics::DefineGetterSetterByValue + set_flags: [heap_inv] - name: CreateEmptyArray space: ecmascript @@ -1475,6 +1551,7 @@ intrinsics: ret: any args: [string_id, any, acc] impl: panda::ecmascript::intrinsics::StOwnByName + set_flags: [heap_inv] - name: StOwnByIndex space: ecmascript @@ -1486,6 +1563,7 @@ intrinsics: ret: any args: [u32, any, acc] impl: panda::ecmascript::intrinsics::StOwnByIndex + set_flags: [heap_inv] - name: StOwnByValue space: ecmascript @@ -1497,6 +1575,7 @@ intrinsics: ret: any args: [any, any, acc] impl: panda::ecmascript::intrinsics::StOwnByValue + set_flags: [heap_inv] - name: StArraySpread space: ecmascript @@ -1508,6 +1587,7 @@ intrinsics: ret: any args: [any, any, acc] impl: panda::ecmascript::intrinsics::StArraySpread + set_flags: [heap_inv] - name: GetIterator space: ecmascript @@ -1519,6 +1599,7 @@ intrinsics: ret: any args: [acc] impl: panda::ecmascript::intrinsics::GetIterator + set_flags: [heap_inv] - name: GetAsyncIterator space: ecmascript @@ -1530,6 +1611,7 @@ intrinsics: ret: any args: [acc] impl: panda::ecmascript::intrinsics::GetAsyncIterator + set_flags: [heap_inv] - name: ThrowIfNotObject space: ecmascript @@ -1586,6 +1668,7 @@ intrinsics: ret: any args: [any, acc] impl: panda::ecmascript::intrinsics::CloseIterator + set_flags: [heap_inv] - name: ImportModule space: ecmascript @@ -1632,6 +1715,7 @@ intrinsics: args: [string_id, any] impl: panda::ecmascript::intrinsics::LdModvarByName clear_flags: [no_dce] + set_flags: [heap_inv] - name: DefineClassWithBuffer space: ecmascript @@ -1654,6 +1738,7 @@ intrinsics: ret: any args: [u16, any, any, acc] impl: panda::ecmascript::intrinsics::SuperCall + set_flags: [heap_inv] - name: SuperCallSpread space: ecmascript @@ -1665,6 +1750,7 @@ intrinsics: ret: any args: [any, any, acc] impl: panda::ecmascript::intrinsics::SuperCallSpread + set_flags: [heap_inv] - name: DefineMethod space: ecmascript @@ -1687,6 +1773,7 @@ intrinsics: ret: any args: [string_id, any] impl: panda::ecmascript::intrinsics::LdSuperByName + set_flags: [heap_inv] - name: StSuperByName space: ecmascript @@ -1698,6 +1785,7 @@ intrinsics: ret: any args: [string_id, any, any] impl: panda::ecmascript::intrinsics::StSuperByName + set_flags: [heap_inv] - name: StSuperByValue space: ecmascript @@ -1709,6 +1797,7 @@ intrinsics: ret: any args: [any, any, acc] impl: panda::ecmascript::intrinsics::StSuperByValue + set_flags: [heap_inv] - name: LdSuperByValue space: ecmascript @@ -1720,6 +1809,7 @@ intrinsics: ret: any args: [any, any] impl: panda::ecmascript::intrinsics::LdSuperByValue + set_flags: [heap_inv] - name: CreateObjectHavingMethod space: ecmascript diff --git a/runtime/ecma_runtime_call_info.h b/runtime/ecma_runtime_call_info.h index d3504ca60..4098c4c01 100644 --- a/runtime/ecma_runtime_call_info.h +++ b/runtime/ecma_runtime_call_info.h @@ -29,23 +29,10 @@ using EcmaEntrypoint = JSTaggedValue (*)(EcmaRuntimeCallInfo *); class EcmaRuntimeCallInfo { public: - // For builtins interpreter call - EcmaRuntimeCallInfo(JSThread *thread, uint32_t numArgs, interpreter::VRegister *args) - : thread_(thread), - numArgs_(numArgs), - gprArgs_(reinterpret_cast(args), numArgs), - stackArgs_(nullptr, static_cast(0)) + EcmaRuntimeCallInfo(JSThread *thread, uint32_t numArgs, JSTaggedValue *args) + : thread_(thread), args_(args), numArgs_(numArgs) { - ASSERT(numArgs_ >= NUM_MANDATORY_JSFUNC_ARGS); - } - - EcmaRuntimeCallInfo(JSThread *thread, uint32_t numArgs, JSTaggedValue *gprArgs, JSTaggedValue *stackArgs) - : thread_(thread), - numArgs_(numArgs), - gprArgs_(gprArgs, GetGprArgsCount(numArgs)), - stackArgs_(stackArgs, GetStackArgsCount(numArgs)) - { - ASSERT(numArgs_ >= NUM_MANDATORY_JSFUNC_ARGS); + ASSERT(numArgs >= NUM_MANDATORY_JSFUNC_ARGS); } ~EcmaRuntimeCallInfo() = default; @@ -76,11 +63,6 @@ public: SetArg(idx + FIRST_ARGS_INDEX, tagged); } - inline JSHandle GetArg(uint32_t idx) const - { - return JSHandle(GetArgAddress(idx)); - } - inline JSHandle GetFunction() const { return GetArg(FUNC_INDEX); @@ -98,6 +80,7 @@ public: inline JSHandle GetCallArg(uint32_t idx) const { + ASSERT_PRINT(idx < GetArgsNumber(), "Can not set values out of index range"); return GetArg(idx + FIRST_ARGS_INDEX); } @@ -112,10 +95,9 @@ public: inline uintptr_t GetArgAddress(uint32_t idx) const { - if (idx < gprArgs_.size()) { - return reinterpret_cast(&gprArgs_[idx]); - } - return reinterpret_cast(&stackArgs_[idx - gprArgs_.size()]); + ASSERT(idx < numArgs_); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + return reinterpret_cast(&args_[idx]); } private: @@ -126,28 +108,19 @@ private: inline void SetArg(uint32_t idx, JSTaggedValue tagged) { - *reinterpret_cast(GetArgAddress(idx)) = tagged; + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + args_[idx] = tagged; } - static size_t GetGprArgsCount(uint32_t numArgs) - { - static_assert(arch::ExtArchTraits::NUM_GP_ARG_REGS >= 2); - size_t numArgRegs = arch::ExtArchTraits::NUM_GP_ARG_REGS - - 2; // first two regs are occupied by Method* and numArgs - size_t maxGprArgs = numArgRegs * ArchTraits::POINTER_SIZE / sizeof(JSTaggedValue); - return std::min(static_cast(numArgs), maxGprArgs); - } - - static size_t GetStackArgsCount(uint32_t numArgs) + inline JSHandle GetArg(uint32_t idx) const { - return numArgs - GetGprArgsCount(numArgs); + return JSHandle(GetArgAddress(idx)); } private: JSThread *thread_; + JSTaggedValue *args_ {nullptr}; uint32_t numArgs_; - Span gprArgs_; - Span stackArgs_; }; } // namespace panda::ecmascript diff --git a/runtime/interpreter/ecma-interpreter-inl.h b/runtime/interpreter/ecma-interpreter-inl.h index 5fce35b04..053c1ef86 100644 --- a/runtime/interpreter/ecma-interpreter-inl.h +++ b/runtime/interpreter/ecma-interpreter-inl.h @@ -272,7 +272,7 @@ public: // Init EcmascriptEnvironment EcmascriptEnvironment *new_env = JSFrame::GetJSEnv(this->GetFrame()); - new (new_env) EcmascriptEnvironment(constant_pool, lexical_env.GetHeapObject(), this_func, prev_env); + new (new_env) EcmascriptEnvironment(prev_env, constant_pool, lexical_env.GetHeapObject(), this_func); // Update EcmascriptEnvironment js_thread->SetEcmascriptEnv(new_env); @@ -1208,11 +1208,10 @@ public: LOG_INST() << "newobjDynrange " << num_args << " v" << first_arg_reg_idx; - auto thread = JSThread::Cast(this->GetThread()); - JSTaggedValue res = SlowRuntimeStub::NewObjDynRange(thread, num_args, GetStkArgs(first_arg_reg_idx)); - INTERPRETER_RETURN_IF_ABRUPT(res); - - SetAccFromTaggedValue(res); + auto range_args = GetStkArgs(first_arg_reg_idx); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + INTRINSIC_CALL_CHECK_SETACC(intrinsics::NewobjDynrange(this->GetJSThread(), num_args - 2U, range_args[0], + range_args[1], range_args + 2U)); this->template MoveToNextInst(); } diff --git a/runtime/interpreter/interpreter-inl.h b/runtime/interpreter/interpreter-inl.h index 17942adc4..dc6cb69ab 100644 --- a/runtime/interpreter/interpreter-inl.h +++ b/runtime/interpreter/interpreter-inl.h @@ -50,7 +50,7 @@ public: // Init EcmascriptEnvironment EcmascriptEnvironment *new_env = JSFrame::GetJSEnv(frame); - new (new_env) EcmascriptEnvironment(constant_pool, lexical_env, func.GetHeapObject(), prev_env); + new (new_env) EcmascriptEnvironment(prev_env, constant_pool, lexical_env, func.GetHeapObject()); // Change EcmascriptEnvironment js_thread->SetEcmascriptEnv(new_env); @@ -155,7 +155,6 @@ JSTaggedValue EcmaInterpreter::Execute(JSThread *thread, JSHandle ca return ExecuteNative(thread, callTarget, numActualArgs, args); } ASSERT(!thread->HasPendingException()); - // TODO(vpukhov): create CFrame without i2c TaggedValue ret_value = method->InvokeDyn(thread, numActualArgs, reinterpret_cast(args)); return JSTaggedValue(ret_value); diff --git a/runtime/interpreter/js_frame-inl.h b/runtime/interpreter/js_frame-inl.h index 7ea0f9b00..f7c583fd7 100644 --- a/runtime/interpreter/js_frame-inl.h +++ b/runtime/interpreter/js_frame-inl.h @@ -57,7 +57,7 @@ inline JSTaggedValue JSFrame::ExecuteNativeMethod(JSThread *js_thread, Frame *fr { ASSERT(js_thread == JSThread::GetCurrent()); - EcmaRuntimeCallInfo call_info(js_thread, num_actual_args, &frame->GetVReg(0)); + EcmaRuntimeCallInfo call_info(js_thread, num_actual_args, reinterpret_cast(&frame->GetVReg(0))); auto ecma_entry_point = reinterpret_cast(method->GetNativePointer()); JSTaggedValue ret_value = ecma_entry_point(&call_info); diff --git a/runtime/interpreter/slow_runtime_helper.cpp b/runtime/interpreter/slow_runtime_helper.cpp index ce82a7dcd..4aa5bd8d1 100644 --- a/runtime/interpreter/slow_runtime_helper.cpp +++ b/runtime/interpreter/slow_runtime_helper.cpp @@ -24,6 +24,15 @@ #include "plugins/ecmascript/runtime/tagged_array-inl.h" namespace panda::ecmascript { + +#ifdef PANDA_QEMU_AARCH64_GCC_8 +// Build PANDA_QEMU_AARCH64_GCC_8 hangs without this workaround. Please check issue #8094. +JSTaggedValue GetGlobalObject(JSThread *thread) +{ + return thread->GetGlobalObject(); +} +#endif + JSTaggedValue SlowRuntimeHelper::CallBoundFunction(JSThread *thread, JSHandle boundFunc, JSHandle obj) { diff --git a/runtime/interpreter/slow_runtime_stub.cpp b/runtime/interpreter/slow_runtime_stub.cpp index 29bd992ca..5682c950e 100644 --- a/runtime/interpreter/slow_runtime_stub.cpp +++ b/runtime/interpreter/slow_runtime_stub.cpp @@ -430,22 +430,17 @@ JSTaggedValue SlowRuntimeStub::DelObjProp(JSThread *thread, JSTaggedValue obj, J return JSTaggedValue(ret); } -JSTaggedValue SlowRuntimeStub::NewObjDynRange(JSThread *thread, uint16_t argsCount, JSTaggedType *stkargs) +JSTaggedValue SlowRuntimeStub::NewObjDynRange(JSThread *thread, uint16_t args_count, JSTaggedValue func, + JSTaggedValue new_target, JSTaggedType *stkargs) { INTERPRETER_TRACE(thread, NewobjDynrange); [[maybe_unused]] EcmaHandleScope handleScope(thread); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - JSHandle funcHandle(thread, JSTaggedValue(stkargs[0])); // FUNC_INDEX - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - JSHandle newTargetHandle(thread, JSTaggedValue(stkargs[1])); // NEW_TARGET_INDEX - - argsCount -= 2; - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - stkargs = &stkargs[2]; + JSHandle funcHandle(thread, JSTaggedValue(func)); + JSHandle newTargetHandle(thread, JSTaggedValue(new_target)); JSHandle preArgs(thread, JSTaggedValue::Undefined()); - auto tagged = SlowRuntimeHelper::Construct(thread, funcHandle, newTargetHandle, preArgs, argsCount, stkargs); + auto tagged = SlowRuntimeHelper::Construct(thread, funcHandle, newTargetHandle, preArgs, args_count, stkargs); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return tagged; } diff --git a/runtime/interpreter/slow_runtime_stub.h b/runtime/interpreter/slow_runtime_stub.h index e57d74d61..dd24a72c1 100644 --- a/runtime/interpreter/slow_runtime_stub.h +++ b/runtime/interpreter/slow_runtime_stub.h @@ -53,7 +53,8 @@ public: static JSTaggedValue ToJSTaggedValueWithUint32(JSThread *thread, JSTaggedValue value); static JSTaggedValue DelObjProp(JSThread *thread, JSTaggedValue obj, JSTaggedValue prop); - static JSTaggedValue NewObjDynRange(JSThread *thread, uint16_t argsCount, JSTaggedType *stkargs); + static JSTaggedValue NewObjDynRange(JSThread *thread, uint16_t args_count, JSTaggedValue func, + JSTaggedValue new_target, JSTaggedType *stkargs); static JSTaggedValue CreateObjectWithExcludedKeys(JSThread *thread, uint16_t numKeys, JSTaggedValue objVal, JSTaggedType *stkargs); static JSTaggedValue ExpDyn(JSThread *thread, JSTaggedValue base, JSTaggedValue exponent); diff --git a/runtime/intrinsics-inl.h b/runtime/intrinsics-inl.h index d339bd8f7..2d9dc1454 100644 --- a/runtime/intrinsics-inl.h +++ b/runtime/intrinsics-inl.h @@ -559,9 +559,24 @@ INLINE_ECMA_INTRINSICS uint64_t DefinefuncDyn(JSThread *thread, uint32_t methodI } // NOLINTNEXTLINE(misc-definitions-in-headers) -INLINE_ECMA_INTRINSICS uint64_t NewobjDynrange(JSThread *thread, uint16_t args_num, uint64_t args) +INLINE_ECMA_INTRINSICS uint64_t NewobjDynrange(JSThread *thread, uint16_t num_args, uint64_t func, uint64_t new_target, + void *stkargs_raw) { - return SlowRuntimeStub::NewObjDynRange(thread, args_num, reinterpret_cast(args)).GetRawData(); + JSSpanHandle argsHandle(thread, Span(reinterpret_cast(stkargs_raw), num_args)); + + return SlowRuntimeStub::NewObjDynRange(thread, num_args, JSTaggedValue(func), JSTaggedValue(new_target), + argsHandle.dataTaggedType()) + .GetRawData(); +} + +// NOLINTNEXTLINE(misc-definitions-in-headers) +INLINE_ECMA_INTRINSICS uint64_t NewobjDynrangeInterp(JSThread *thread, uint16_t num_args, uint64_t args_raw) +{ + auto args = reinterpret_cast(args_raw); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + return SlowRuntimeStub::NewObjDynRange(thread, num_args - 2, JSTaggedValue(args[0]), JSTaggedValue(args[1]), + &args[2]) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + .GetRawData(); } // NOLINTNEXTLINE(misc-definitions-in-headers) diff --git a/runtime/js_function.h b/runtime/js_function.h index 13a703188..731025035 100644 --- a/runtime/js_function.h +++ b/runtime/js_function.h @@ -286,11 +286,6 @@ public: ACCESSORS(ConstantPool, CONSTANT_POOL_OFFSET, PROFILE_TYPE_INFO_OFFSET) ACCESSORS(ProfileTypeInfo, PROFILE_TYPE_INFO_OFFSET, SIZE) - // NOLINTNEXTLINE(readability-magic-numbers) - static_assert(LEXICAL_ENV_OFFSET == 0x30); - // NOLINTNEXTLINE(readability-magic-numbers) - static_assert(CONSTANT_POOL_OFFSET == 0x50); - static constexpr uint32_t FUNCTION_KIND_BIT_NUM = 5; using FunctionKindBit = BitField; using StrictBit = FunctionKindBit::NextFlag; diff --git a/runtime/js_handle.h b/runtime/js_handle.h index 796d2b967..1c0776692 100644 --- a/runtime/js_handle.h +++ b/runtime/js_handle.h @@ -197,6 +197,58 @@ public: *addr = handle.GetTaggedValue(); } }; + +class JSSpanHandle { +public: + JSSpanHandle(JSThread *thread, Span sp) : thread_(thread), sp_(sp) + { + AddToChain(); + } + + ~JSSpanHandle() + { + ASSERT(thread_->spanHandle_ == this); + thread_->spanHandle_ = prev_; + } + + JSTaggedValue *data() + { + return sp_.data(); + } + + JSTaggedType *dataTaggedType() + { + return reinterpret_cast(data()); + } + + JSTaggedValue &operator[](size_t idx) + { + return sp_[idx]; + } + + static void IterateChain(JSThread *thread, const RootRangeVisitor &v0) + { + for (auto head = thread->spanHandle_; head != nullptr; head = head->prev_) { + auto &sp = head->sp_; + v0(Root::ROOT_HANDLE, ObjectSlot(ToUintPtr(sp.begin())), ObjectSlot(ToUintPtr(sp.end()))); + } + } + +private: + NO_COPY_SEMANTIC(JSSpanHandle); + NO_MOVE_SEMANTIC(JSSpanHandle); + + void AddToChain() + { + prev_ = thread_->spanHandle_; + thread_->spanHandle_ = this; + } + + JSSpanHandle *prev_ {nullptr}; + JSThread *thread_ {nullptr}; + Span sp_ {}; +}; + } // namespace panda::ecmascript #endif // ECMASCRIPT_JSHANDLE_H diff --git a/runtime/js_invoker.cpp b/runtime/js_invoker.cpp index c1dd4ad6c..85f2975ed 100644 --- a/runtime/js_invoker.cpp +++ b/runtime/js_invoker.cpp @@ -29,10 +29,9 @@ JSTaggedValue JsInvoker::Invoke([[maybe_unused]] JSThread *thread) UNREACHABLE(); } -extern "C" uint64_t InvokeBuiltin(JSThread *thread, Method *method, uint32_t numArgs, JSTaggedValue *gprArgs, - JSTaggedValue *stackArgs) +extern "C" uint64_t InvokeBuiltin(JSThread *thread, Method *method, uint32_t numArgs, JSTaggedValue *stackArgs) { - EcmaRuntimeCallInfo ecmaRuntimeCallInfo(thread, numArgs, gprArgs, stackArgs); + EcmaRuntimeCallInfo ecmaRuntimeCallInfo(thread, numArgs, stackArgs); ASSERT(method->GetNativePointer() != nullptr); @@ -42,11 +41,13 @@ extern "C" uint64_t InvokeBuiltin(JSThread *thread, Method *method, uint32_t num if (thread->HasPendingException()) { auto stack = StackWalker::Create(thread); ASSERT(stack.IsCFrame() && stack.GetCFrame().IsNative()); - stack.NextFrame(); - // Native frames can handle exceptions as well - if (!stack.HasFrame() || !stack.IsCFrame() || stack.GetCFrame().IsNative()) { + + // Return to caller if there is a BYPASS bridge, otherwise skip current frame + auto prev = stack.GetCFrame().GetPrevFrame(); + if (stack.GetBoundaryFrameMethod(prev) == FrameBridgeKind::BYPASS) { return retValue.GetRawData(); } + stack.NextFrame(); FindCatchBlockInCFrames(thread, &stack, nullptr); UNREACHABLE(); diff --git a/runtime/js_thread.cpp b/runtime/js_thread.cpp index 227ecc619..6c6d126c1 100644 --- a/runtime/js_thread.cpp +++ b/runtime/js_thread.cpp @@ -121,6 +121,8 @@ void JSThread::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) v0(ecmascript::Root::ROOT_HANDLE, ecmascript::ObjectSlot(node->GetObjectAddress())); } }); + + JSSpanHandle::IterateChain(this, v1); } void JSThread::IterateWeakEcmaGlobalStorage(const WeakRootVisitor &visitor) diff --git a/runtime/js_thread.h b/runtime/js_thread.h index 0dc3acc6f..cc42cf978 100644 --- a/runtime/js_thread.h +++ b/runtime/js_thread.h @@ -30,6 +30,7 @@ class EcmaVM; class EcmascriptEnvironment; class InternalCallParams; class PropertiesCache; +class JSSpanHandle; class JSThread : public ManagedThread { public: @@ -326,6 +327,7 @@ private: std::vector *> handleStorageNodes_ {}; int32_t currentHandleStorageIndex_ {-1}; int32_t handleScopeCount_ {0}; + JSSpanHandle *spanHandle_ {nullptr}; JSTaggedValue stubCode_ {JSTaggedValue::Hole()}; // Run-time state @@ -350,6 +352,7 @@ private: JSTaggedValue invocationLexicalEnv_; friend class EcmaHandleScope; + friend class JSSpanHandle; friend class GlobalHandleCollection; }; } // namespace panda::ecmascript diff --git a/runtime/mem/mem.h b/runtime/mem/mem.h index 9f15c872e..804721737 100644 --- a/runtime/mem/mem.h +++ b/runtime/mem/mem.h @@ -32,27 +32,6 @@ enum class MemAlignment : uint8_t { MEM_ALIGN_REGION = 16, }; -template -constexpr inline bool IsAligned(T value, size_t alignment) -{ - return (value & (alignment - 1U)) == 0; -} - -template -inline T AlignDown(T x, size_t alignment) -{ - ASSERT(std::is_integral::value); - // alignment must be a power of two. - ASSERT(alignment != 0 && ((alignment & (alignment - 1U)) == 0)); - return x & ~(alignment - 1U); -} - -template -inline T AlignUp(T x, size_t alignment) -{ - ASSERT(std::is_integral::value); - return AlignDown(static_cast(x + alignment - 1U), alignment); -} } // namespace panda::ecmascript #endif // ECMASCRIPT_MEM_MEM_H diff --git a/runtime/runtime_sources.gn b/runtime/runtime_sources.gn index f7e065bee..1c21c2437 100644 --- a/runtime/runtime_sources.gn +++ b/runtime/runtime_sources.gn @@ -145,8 +145,8 @@ srcs = [ ] # Should be files deleted??? -#srcs_arm = [ "arch/arm/builtin_bridge_arm.S" ] -srcs_arm64 = [ "arch/aarch64/builtin_bridge_aarch64.S" ] -srcs_x86 = [ "arch/amd64/builtin_bridge_amd64.S" ] +#srcs_arm = [ "bridge/arch/arm/builtin_bridge_arm.S" ] +srcs_arm64 = [ "bridge/arch/aarch64/builtin_bridge_aarch64.S" ] +srcs_x86 = [ "bridge/arch/amd64/builtin_bridge_amd64.S" ] runtime_yamls = [ "ecma_runtime.yaml" ] diff --git a/runtime/templates/intrinsics_gen.cpp.erb b/runtime/templates/intrinsics_gen.cpp.erb index fb7188433..8404c3819 100644 --- a/runtime/templates/intrinsics_gen.cpp.erb +++ b/runtime/templates/intrinsics_gen.cpp.erb @@ -19,11 +19,13 @@ namespace panda::ecmascript::intrinsics { % Runtime::intrinsics.select(&:has_impl?).uniq { |i| i.impl }.each do |intrinsic| % funcname = intrinsic.impl.rpartition('::').last -% params = intrinsic.signature.args.map { |t| get_effective_type(t) }.flatten +% stackrange = intrinsic.signature.respond_to?(:stackrange) && intrinsic.signature.stackrange +% full_args = intrinsic.signature.args + (stackrange ? ['ptr'] : []) +% params = full_args.map { |t| get_effective_type(t) }.flatten % params = params.each_with_index.map {|cpp_type, index| cpp_type + " " + "arg#{index}" } % ret_type = get_ret_effective_type(intrinsic.signature.ret) % use_thread = !intrinsic.respond_to?(:use_thread) || intrinsic.use_thread -% nargs = intrinsic.signature.args.size +% nargs = full_args.size % arg_list = (0...nargs).map { |i| "arg#{i}" } % arg_list.insert(0, 'GetJSThread()') if use_thread % arg_list = arg_list.join(", ") diff --git a/tests/compiler/branch_elimination_ecma_test.cpp b/tests/compiler/branch_elimination_ecma_test.cpp index a19834dfc..a9c36da15 100644 --- a/tests/compiler/branch_elimination_ecma_test.cpp +++ b/tests/compiler/branch_elimination_ecma_test.cpp @@ -26,8 +26,7 @@ public: TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeVNDiffTypesTrue) { - auto graph = CreateGraphWithDefaultRuntime(); - graph->SetDynamicMethod(); + auto graph = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph) { PARAMETER(0, 0).any(); @@ -68,8 +67,7 @@ TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeVNDiffTypesTrue) GraphChecker(graph).Check(); - auto graph_opt = CreateGraphWithDefaultRuntime(); - graph_opt->SetDynamicMethod(); + auto graph_opt = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph_opt) { PARAMETER(0, 0).any(); @@ -98,8 +96,7 @@ TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeVNDiffTypesTrue) TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeVNDiffTypesFalse_1) { - auto graph = CreateGraphWithDefaultRuntime(); - graph->SetDynamicMethod(); + auto graph = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph) { PARAMETER(0, 0).any(); @@ -147,8 +144,7 @@ TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeVNDiffTypesFalse_1) TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeVNDiffTypesFalse_2) { - auto graph = CreateGraphWithDefaultRuntime(); - graph->SetDynamicMethod(); + auto graph = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph) { PARAMETER(0, 0).any(); @@ -196,8 +192,7 @@ TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeVNDiffTypesFalse_2) TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeVNEqTypesTrue_1) { - auto graph = CreateGraphWithDefaultRuntime(); - graph->SetDynamicMethod(); + auto graph = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph) { PARAMETER(0, 0).any(); @@ -238,8 +233,7 @@ TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeVNEqTypesTrue_1) GraphChecker(graph).Check(); - auto graph_opt = CreateGraphWithDefaultRuntime(); - graph_opt->SetDynamicMethod(); + auto graph_opt = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph_opt) { PARAMETER(0, 0).any(); @@ -268,8 +262,7 @@ TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeVNEqTypesTrue_1) TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeVNEqTypesTrue_2) { - auto graph = CreateGraphWithDefaultRuntime(); - graph->SetDynamicMethod(); + auto graph = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph) { PARAMETER(0, 0).any(); @@ -310,8 +303,7 @@ TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeVNEqTypesTrue_2) GraphChecker(graph).Check(); - auto graph_opt = CreateGraphWithDefaultRuntime(); - graph_opt->SetDynamicMethod(); + auto graph_opt = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph_opt) { PARAMETER(0, 0).any(); @@ -340,8 +332,7 @@ TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeVNEqTypesTrue_2) TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeVNEqTypesTrue_3) { - auto graph = CreateGraphWithDefaultRuntime(); - graph->SetDynamicMethod(); + auto graph = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph) { PARAMETER(0, 0).any(); @@ -381,8 +372,7 @@ TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeVNEqTypesTrue_3) GraphChecker(graph).Check(); - auto graph_opt = CreateGraphWithDefaultRuntime(); - graph_opt->SetDynamicMethod(); + auto graph_opt = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph_opt) { PARAMETER(0, 0).any(); @@ -411,8 +401,7 @@ TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeVNEqTypesTrue_3) TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeSubtype_1) { - auto graph = CreateGraphWithDefaultRuntime(); - graph->SetDynamicMethod(); + auto graph = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph) { PARAMETER(0, 0).any(); @@ -453,8 +442,7 @@ TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeSubtype_1) GraphChecker(graph).Check(); - auto graph_opt = CreateGraphWithDefaultRuntime(); - graph_opt->SetDynamicMethod(); + auto graph_opt = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph_opt) { PARAMETER(0, 0).any(); @@ -483,8 +471,7 @@ TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeSubtype_1) TEST_F(IrBranchEliminationTest, EliminateCompareAnyTypeSubtype_2) { - auto graph = CreateGraphWithDefaultRuntime(); - graph->SetDynamicMethod(); + auto graph = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph) { PARAMETER(0, 0).any(); diff --git a/tests/compiler/ir_builder_ecma_test.cpp b/tests/compiler/ir_builder_ecma_test.cpp index 8b6a07fb8..8ccf7ba63 100644 --- a/tests/compiler/ir_builder_ecma_test.cpp +++ b/tests/compiler/ir_builder_ecma_test.cpp @@ -28,8 +28,7 @@ TEST_F(IrBuilderTest, CompareAnyType) auto graph = CreateGraphDynWithDefaultRuntime(); GRAPH(graph) { - PARAMETER(0, 0); - INS(0).SetType(DataType::Type::ANY); + PARAMETER(0, 0).any(); BASIC_BLOCK(2, -1) { @@ -52,8 +51,7 @@ TEST_F(IrBuilderTest, CastAnyTypeValue) auto graph = CreateGraphDynWithDefaultRuntime(); GRAPH(graph) { - PARAMETER(0, 0); - INS(0).SetType(DataType::Type::ANY); + PARAMETER(0, 0).any(); BASIC_BLOCK(2, -1) { @@ -73,11 +71,10 @@ TEST_F(IrBuilderTest, CastAnyTypeValue) TEST_F(IrBuilderTest, CastValueToAnyType) { // no crash. - auto graph = CreateGraphDynWithDefaultRuntime(); + auto graph = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph) { - PARAMETER(0, 0); - INS(0).SetType(DataType::Type::INT32); + PARAMETER(0, 0).i32(); BASIC_BLOCK(2, -1) { diff --git a/tests/compiler/peepholes_ecma_test.cpp b/tests/compiler/peepholes_ecma_test.cpp index bd223f72d..956f754c6 100644 --- a/tests/compiler/peepholes_ecma_test.cpp +++ b/tests/compiler/peepholes_ecma_test.cpp @@ -27,7 +27,7 @@ public: TEST_F(PeepholesTest, CastTrueSimple) { - auto graph = CreateGraphDynWithDefaultRuntime(); + auto graph = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph) { PARAMETER(0, 0).any(); @@ -51,7 +51,7 @@ TEST_F(PeepholesTest, CastTrueSimple) ASSERT_TRUE(graph->RunPass()); GraphChecker(graph).Check(); - auto graph_opt = CreateGraphDynWithDefaultRuntime(); + auto graph_opt = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph_opt) { PARAMETER(0, 0).any(); @@ -74,7 +74,7 @@ TEST_F(PeepholesTest, CastTrueSimple) TEST_F(PeepholesTest, CastTrueComplex) { - auto graph = CreateGraphDynWithDefaultRuntime(); + auto graph = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph) { PARAMETER(0, 0).any(); @@ -110,7 +110,7 @@ TEST_F(PeepholesTest, CastTrueComplex) ASSERT_TRUE(graph->RunPass()); GraphChecker(graph).Check(); - auto graph_opt = CreateGraphDynWithDefaultRuntime(); + auto graph_opt = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph_opt) { PARAMETER(0, 0).any(); @@ -146,7 +146,7 @@ TEST_F(PeepholesTest, CastTrueComplex) TEST_F(PeepholesTest, CastFalse) { - auto graph = CreateGraphDynWithDefaultRuntime(); + auto graph = CreateGraphDynStubWithDefaultRuntime(); GRAPH(graph) { PARAMETER(0, 0).any(); diff --git a/tests/runtime/common/test_helper.cpp b/tests/runtime/common/test_helper.cpp index 9aa89f29b..e04bac096 100644 --- a/tests/runtime/common/test_helper.cpp +++ b/tests/runtime/common/test_helper.cpp @@ -46,7 +46,8 @@ std::unique_ptr TestHelper::CreateEcmaRuntimeCallInfo(JSThr Frame *frame = method->EnterNativeMethodFrame(thread, 0, numActualArgs, args.data()); - auto callInfo = std::make_unique(thread, numActualArgs, &frame->GetVReg(0)); + auto callInfo = std::make_unique(thread, numActualArgs, + reinterpret_cast(&frame->GetVReg(0))); callInfo->SetFunction(methodFunction_.GetTaggedValue()); callInfo->SetNewTarget(newTgt); -- Gitee