diff --git a/compiler/codegen_intrinsics_ecmascript.cpp b/compiler/codegen_intrinsics_ecmascript.cpp index 100024cbeeea5433934e8d803ffe224f5d851fc7..52582262bdbcf3027e295b0949844028f2491e40 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 0000000000000000000000000000000000000000..d1f473f383d85e1fdc1b3dfd3bc6ad6fbc56c6d4 --- /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 9f10af6e5ef921a51a8c66c75ad19cdacd46284e..b5e634248507fad851b2ac569e50a35d2c098599 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 43cacf59b15d9e8e695373a989c115ebaad3c23e..4b068f44c4f917bd0a67dc91bd3f2c2bf8c81ceb 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 16bdae24535706dcd179eac04e88dcfee28d78de..9122b43130d64c7c5b39d6e7a9302bfbbe770af1 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 ec2edf36e6d56512d7a2b48fd3287f1a736abbde..5facccee7e4a5fae3d2ce73a4212c1fb1c7a85a8 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 8ea97036907e1b64b06c622bcada4c7807d40306..2b12bc10b1de5fcf9c31fb91343d8ff0b23ed850 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 409c06f826c030e02ff8654daa8eed20c7ba2a24..d08c2a7019ea49b71b61b3c894751651e782a423 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 6e6597601171f8ae3038b469522488d6d96406e5..27f4c2c27be37013cfb57520f25df3803c5aa54e 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 c2b13a526d781b1e5c9b684a9530ce0b5d25fc48..b742a1c16e98f9b0a8909c0c06080245f0870cec 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 34cba78feee7a827a408c786f339579f858873a8..e6fcb318db2001c7fda6bd14d573de0916939360 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 b25370e1fb24d00c00abda4b007b7a63a2a2be9b..84faa434dc3009802ccbb69bb849d016dc55c2e9 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 b23e7bdfa26d5c155c34683e33460e8c66e3a13d..af23ad81ce402a03e442ed5f4567726b8f21f828 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 d202450806452181dc92988ff55e933a7c3e35dd..aedb4fe55177d57992e6542aeb19d3ff3ba28170 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 577ad2ccdce30871b883a1d5bbe9e48692ed7896..5f4cff34d981716f598e5bb54b9157a2c8b05e61 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 c0fca877e352b7dec930f3c9836828fb55c8d7f8..53a5d60e280e6379574a49f18a52c3294c887bec 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 cebc91152532d5251efe32d68b8733e43bcb7fef..fbecbf3a9cc5737f725e57486b838009710d099e 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 d92f90137bd432e7ad6523241bdb8ac2aae276d8..951a80b2dd28410ee6eceb1a946e9f198d9c8243 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 0d95ea155bcc40c20c4b28da2e69cbc81f8c34f9..f5cb6ba018b25a7aad4064dd6df51cf463c10266 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 e04684d37cbc4ec5e49e1f530402f8e7a1a281a3..4e857346482aadf99a023dd33a1d750eb4d9d689 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 4bd364436ccd35c60454120c7adb5a26012173bc..3448a51cd8466773775b741fe6eee295a7118bcf 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 c5be19d8cc5777409bea2b6e2c28c54a5ed6f7b5..7fff4e6f01b8e81a17607258d988866f7ccf5a53 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 18fed7d083004a96aab868a0a5f540f1373ffb72..9654999f506a9437b5f74569f92a2570afd93a71 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 3ddb0b27ecfff38ddd736b0e1e7c5135e9c40314..2909e57935b65b2f73c343fbfeb21ec9bbc51391 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 9327c06406ce146c2c4ce844943afa8e7b4fd0f9..5d3c5695028596979c0fd91cab759c5729a43a33 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 500d03b7e87efacba08547d3d18cf708b5438cd7..f840ddf3d94c8d3f9aea0f96ff5ecae1d7fc8296 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 868d7c0b2b10ad78a9ad01666c8374b5166059e0..2ac6184c39fe3bf7ce300749aa4dda8cc32eada7 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 0f203ec953cad8e5754e153a40948bf1efa1f4d1..6a2b4fab1298a16b12bbfaead7f072becff09103 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 d3504ca6061024040e87ba5ebb50b0cab891e340..4098c4c01e7bb40345f0f0045f73872d64d1665d 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 5fce35b048aa06922b59dd04de84d6bffdabd7f9..053c1ef8672b4e8d1072d4af88c0aa9b96fc2876 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 17942adc4679b6fc6fb94c7e4f152367ae18214b..dc6cb69ab623bb28ed8348087b3a6ee2a83a730b 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 7ea0f9b002c0374b6628793fc07e2afec3dad150..f7c583fd7d63cdb4b82eaa160fb63507b01f90e6 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 ce82a7dcd6d6a88beff394191f2f7c5ef009774e..4aa5bd8d131a782f1ce569795fb9c613418d3075 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 29bd992caa24d58862eaabb46971cc66274504f1..5682c950e0ffeaa3b097a6ba4b3e0c3d516d6f7c 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 e57d74d61b7630b8f4f582c5680b708d2a2c158d..dd24a72c15048632a70a7647e332a72a79dc398e 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 d339bd8f734f89bf725157cefdd66037f1a19168..2d9dc1454f4b12be443d6bd08c3259db47cfcf12 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 13a7031885dcc45512b14308baf9cc61e965f28e..7310250357c516dc3f35bb70b3794c5b1ed701e7 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 796d2b967593a511fa94975cceb32bba444a14c6..1c0776692c251b1481176407dca54fafe0b48b67 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 c1dd4ad6c74ddd318210de6406049a1277e25164..85f2975ed43c80cb06f53f8a497660e91b2520c2 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 227ecc6197bfe420d64faca367961e399ecd2cc9..6c6d126c1f97547d1d300b3d169c18e38fe2c35b 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 0dc3acc6fc154c9a5d899a1e582015e63ac934c5..cc42cf978546dede35a0040b372e54b30c706b57 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 9f15c872ecf4c7a2ccf64e8c86f2f255e105fea0..804721737eb82b17f7040f368d140d4c07ccb47c 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 f7e065bee4572bdb0a593ae28008d2ad02bfdb1e..1c21c24374de40cfdb4eb5e73542466b97d42dee 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 fb718843336f050ec3c689ba89b3a1bd4e334079..8404c3819367de2b7884f335b9d3e74cf9bcdba2 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 a19834dfc957755b670cdfa223e708086ba6d2d3..a9c36da158e462c80dca7f1ad31bd471adef9759 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 8b6a07fb8bbbab5d61a21c882b757ccccd6dbd5e..8ccf7ba63f6be1bb4685b633b99dcafb537087fe 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 bd223f72d31e808980257979d02bdb0079f8efe2..956f754c6c47c66bee4728de9bfd241cb0890650 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 9aa89f29b9716804d29a3186992cdc1be5e54753..e04bac0967e449fa552e639859516fa17f5b84ec 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);