diff --git a/bytecode_optimizer/templates/ecmascript_codegen_intrinsics_gen.inc.erb b/bytecode_optimizer/templates/ecmascript_codegen_intrinsics_gen.inc.erb index e699e5f2b40d91728ec30cf7db02afcf2347404f..0da5ef60e876ec98c81a71c335865b1fb50094c4 100644 --- a/bytecode_optimizer/templates/ecmascript_codegen_intrinsics_gen.inc.erb +++ b/bytecode_optimizer/templates/ecmascript_codegen_intrinsics_gen.inc.erb @@ -55,6 +55,11 @@ auto ir_id<%= id_index %> = static_cast(inst->GetImms()[<%= imm_index %>]); auto bc_id<%= id_index %> = enc->ir_interface_->GetStringIdByOffset(ir_id<%= id_index %>); % params_str = params_str + "bc_id#{id_index}, " +% elsif inst.properties.include?("literalarray_id") + ASSERT(inst->HasImms() && inst->GetImms().size() > <%= imm_index %>); // NOLINTNEXTLINE(readability-container-size-empty) + auto ir_id<%= id_index %> = static_cast(inst->GetImms()[<%= imm_index %>]); + auto bc_id<%= id_index %> = std::to_string(ir_id<%= id_index %>); +% params_str = params_str + "bc_id#{id_index}, " % end % id_index = id_index + 1 % imm_index = imm_index + 1 diff --git a/compiler/templates/ecmascript_inst_builder_gen.cpp.erb b/compiler/templates/ecmascript_inst_builder_gen.cpp.erb index 68f7e6f2128c2c6791d568283f53987e9704ec40..63de114eca59d190347c6e4b75aaf4b06a48f5e7 100644 --- a/compiler/templates/ecmascript_inst_builder_gen.cpp.erb +++ b/compiler/templates/ecmascript_inst_builder_gen.cpp.erb @@ -176,6 +176,10 @@ void InstBuilder::BuildEcmaAsIntrinsics(const BytecodeInstruction* bc_inst) // N } inst->AddImm(GetGraph()->GetAllocator(), m_idx<%= id16_index %>); % id16_index = id16_index + 1 +% elsif inst.properties.include?("literalarray_id") + auto literalarray_id<%= id16_index %> = bc_inst->template GetId<<%= format %>>().AsIndex(); + inst->AddImm(GetGraph()->GetAllocator(), literalarray_id<%= id16_index %>); +% id16_index = id16_index + 1 % elsif inst.properties.include?("string_id") auto string_id<%= id32_index %> = bc_inst->template GetId<<%= format %>>().AsFileId().GetOffset(); inst->AddImm(GetGraph()->GetAllocator(), string_id<%= id32_index %>); diff --git a/ecmastdlib/CMakeLists.txt b/ecmastdlib/CMakeLists.txt index e942e4f582abac94ab21837e5b3d8b40e01e3a7e..7af7b5e39d2d46a443bff8ef08f32d2f77c6fc2f 100644 --- a/ecmastdlib/CMakeLists.txt +++ b/ecmastdlib/CMakeLists.txt @@ -15,8 +15,23 @@ cmake_minimum_required(VERSION 3.10) project(ecmastdlib) +if(CMAKE_CROSSCOMPILING) + ExternalProject_Get_Property(panda_host_tools binary_dir) + set(arkquick_target panda_host_tools) + set(arkquick_bin "${binary_dir}/quickener/arkquick") +else() + set(arkquick_target arkquick) + set(arkquick_bin $) +endif() + add_panda_assembly(TARGET ecmastdlib SOURCE ecmastdlib.pa) +add_custom_command(TARGET ecmastdlib + POST_BUILD + COMMAND ${arkquick_bin} "${CMAKE_CURRENT_BINARY_DIR}/ecmastdlib.abc" "${CMAKE_CURRENT_BINARY_DIR}/ecmastdlib.abcq" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS arkquick) + set(ECMASTDLIB_INLINE_GEN "${CMAKE_CURRENT_BINARY_DIR}/ecmastdlib_inline_gen.h") set(ECMASTDLIB_INLINE_GEN_RB "${CMAKE_CURRENT_SOURCE_DIR}/ecmastdlib_inline_gen.rb") set(ECMASTDLIB_INLINE_GEN_ERB "${CMAKE_CURRENT_SOURCE_DIR}/ecmastdlib_inline_gen.h.erb") diff --git a/irtoc_scripts/interpreter_main_loop.irt b/irtoc_scripts/interpreter_main_loop.irt index af23ad81ce402a03e442ed5f4567726b8f21f828..d48f1757253d75c4e2955de86761739284b1fedb 100644 --- a/irtoc_scripts/interpreter_main_loop.irt +++ b/irtoc_scripts/interpreter_main_loop.irt @@ -122,10 +122,10 @@ ecma_intrinsic_setacc("IsinDyn", vreg_value(op[0]).any, acc.any) when "ECMA_ISCOERCIBLE_PREF_NONE" ecma_intrinsic_setacc("IsCoercible", acc.any) - when "ECMA_CREATEOBJECTWITHBUFFER_PREF_IMM16" - ecma_intrinsic_setacc("CreateObjectWithBuffer", as_imm(op[0])) - when "ECMA_CREATEOBJECTHAVINGMETHOD_PREF_IMM16" - ecma_intrinsic_setacc("CreateObjectHavingMethod", as_imm(op[0]), acc.any) + when "ECMA_CREATEOBJECTWITHBUFFER_PREF_ID16" + ecma_intrinsic_setacc("CreateObjectWithBuffer", as_id(op[0])) + when "ECMA_CREATEOBJECTHAVINGMETHOD_PREF_ID16" + ecma_intrinsic_setacc("CreateObjectHavingMethod", as_id(op[0]), acc.any) when "ECMA_CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8" ecma_intrinsic_setacc("CreateObjectWithExcludedKeys", as_imm(op[0]), vreg_value(op[1]).any, vreg_ptr(op[2])) when "ECMA_CREATEEMPTYOBJECT_PREF_NONE" @@ -226,8 +226,8 @@ Intrinsic(:INTERPRETER_RETURN).ptr when "ECMA_RETURN_DYN_PREF_NONE" Intrinsic(:INTERPRETER_RETURN).ptr - when "ECMA_CREATEARRAYWITHBUFFER_PREF_IMM16" - ecma_intrinsic_setacc("CreateArrayWithBuffer", as_imm(op[0])) + when "ECMA_CREATEARRAYWITHBUFFER_PREF_ID16" + ecma_intrinsic_setacc("CreateArrayWithBuffer", as_id(op[0])) when "ECMA_CREATEEMPTYARRAY_PREF_NONE" ecma_intrinsic_setacc("CreateEmptyArray") when "ECMA_STARRAYSPREAD_PREF_V8_V8" diff --git a/isa/isa.yaml b/isa/isa.yaml index aedb4fe55177d57992e6542aeb19d3ff3ba28170..00f3e91d6a587314bd0630354cfd5948ddeea2e7 100644 --- a/isa/isa.yaml +++ b/isa/isa.yaml @@ -27,6 +27,11 @@ properties: - tag: use_ic description: Instruction uses inline cache +namespaces: + - namespace: ecmascript + used_instructions: [nop, lda.str, call.short, call, call.range, call.acc.short, call.acc, mov.dyn, lda.dyn, sta.dyn, ldai.dyn, fldai.dyn, return.dyn, calli.dyn.short, calli.dyn, calli.dyn.range, jmp] + quickening: true + profiles_schema: name: string size: int @@ -723,25 +728,28 @@ groups: format: [pref_op_imm_16] properties: [not_compilable] intrinsic_name: INTRINSIC_COPYRESTARGS - - sig: ecma.createarraywithbuffer imm + - sig: ecma.createarraywithbuffer literalarray_id acc: out:top prefix: ecma - format: [pref_op_imm_16] + format: [pref_op_id_16] + properties: [literalarray_id] intrinsic_name: INTRINSIC_CREATE_ARRAY_WITH_BUFFER - - sig: ecma.createobjecthavingmethod imm + - sig: ecma.createobjecthavingmethod literalarray_id acc: inout:top prefix: ecma - format: [pref_op_imm_16] + format: [pref_op_id_16] + properties: [literalarray_id] intrinsic_name: INTRINSIC_CREATE_OBJECT_HAVING_METHOD - sig: ecma.throwifsupernotcorrectcall imm acc: in:top prefix: ecma format: [pref_op_imm_16] intrinsic_name: INTRINSIC_THROW_IF_SUPER_NOT_CORRECT_CALL - - sig: ecma.createobjectwithbuffer imm + - sig: ecma.createobjectwithbuffer literalarray_id acc: out:top prefix: ecma - format: [pref_op_imm_16] + format: [pref_op_id_16] + properties: [literalarray_id] intrinsic_name: INTRINSIC_CREATE_OBJECT_WITH_BUFFER - sig: ecma.ldlexvardyn imm1, imm2 acc: out:top diff --git a/runtime/class_linker/panda_file_translator.cpp b/runtime/class_linker/panda_file_translator.cpp index 7582a1b1f305b7523fec1be813f8e515446f7065..e94d1acdc3ba9d97dfd1782b4b8ef62dba947084 100644 --- a/runtime/class_linker/panda_file_translator.cpp +++ b/runtime/class_linker/panda_file_translator.cpp @@ -150,7 +150,11 @@ void PandaFileTranslator::TranslateMethod(const compiler::AotClass &aot_class, c const uint8_t *insns = codeDataAccessor.GetInstructions(); if (translated_code_.find(insns) == translated_code_.end()) { translated_code_.insert(insns); - TranslateBytecode(codeSize, insns, pf, method); + if (pf.GetHeader()->quickened_flag != 0U) { + TranslateBytecode(codeSize, insns, pf, method); + } else { + TranslateBytecode(codeSize, insns, pf, method); + } } } @@ -311,12 +315,18 @@ Program *PandaFileTranslator::GenerateProgram(const panda_file::File &pf) return *program; } +template void PandaFileTranslator::FixInstructionId32(const BytecodeInstruction &inst, [[maybe_unused]] uint32_t index, uint32_t fixOrder) const { + using EnumT = std::conditional_t; + using R = BytecodeInstructionResolver; + constexpr int payloadOffset = IsQuickened ? 1 : 2; + // NOLINTNEXTLINE(hicpp-use-auto) auto pc = const_cast(inst.GetAddress()); - switch (inst.GetFormat()) { + auto format = inst.GetFormat(); + switch (format) { case BytecodeInstruction::Format::ID32: { uint8_t size = sizeof(uint32_t); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -326,45 +336,53 @@ void PandaFileTranslator::FixInstructionId32(const BytecodeInstruction &inst, [[ } break; } - case BytecodeInstruction::Format::PREF_ID16_V8: { - uint16_t u16Index = index; + case BytecodeInstruction::Format::PREF_ID32: { + uint8_t size = sizeof(uint32_t); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + if (memcpy_s(pc + FixInstructionIndex::FIX_TWO, size, &index, size) != EOK) { + LOG_ECMA(FATAL) << "memcpy_s failed"; + UNREACHABLE(); + } + break; + } + case R::template Get(): { uint8_t size = sizeof(uint16_t); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - if (memcpy_s(pc + FixInstructionIndex::FIX_TWO, size, &u16Index, size) != EOK) { + if (memcpy_s(pc + payloadOffset, size, &index, size) != EOK) { LOG_ECMA(FATAL) << "memcpy_s failed"; UNREACHABLE(); } break; } - case BytecodeInstruction::Format::PREF_ID32: - case BytecodeInstruction::Format::PREF_ID32_V8: { + case R::template Get(): { uint8_t size = sizeof(uint32_t); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - if (memcpy_s(pc + FixInstructionIndex::FIX_TWO, size, &index, size) != EOK) { + if (memcpy_s(pc + payloadOffset, size, &index, size) != EOK) { LOG_ECMA(FATAL) << "memcpy_s failed"; UNREACHABLE(); } break; } - case BytecodeInstruction::Format::PREF_IMM16: { + case R::template Get(): + case R::template Get(): { ASSERT(static_cast(index) == index); uint16_t u16Index = index; uint8_t size = sizeof(uint16_t); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - if (memcpy_s(pc + FixInstructionIndex::FIX_TWO, size, &u16Index, size) != EOK) { + if (memcpy_s(pc + payloadOffset, size, &u16Index, size) != EOK) { LOG_ECMA(FATAL) << "memcpy_s failed"; UNREACHABLE(); } break; } - case BytecodeInstruction::Format::PREF_ID16_IMM16_V8_V8: { + case R::template Get(): { // Usually, we fix one part of instruction one time. But as for instruction DefineClassWithBuffer, // which use both method id and literal buffer id.Using fixOrder indicates fix Location. if (fixOrder == 0) { uint8_t size = sizeof(uint16_t); ASSERT(static_cast(index) == index); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - if (memcpy_s(pc + FixInstructionIndex::FIX_TWO, size, &index, size) != EOK) { + if (memcpy_s(pc + payloadOffset, size, &index, size) != EOK) { LOG_ECMA(FATAL) << "memcpy_s failed"; UNREACHABLE(); } @@ -375,7 +393,7 @@ void PandaFileTranslator::FixInstructionId32(const BytecodeInstruction &inst, [[ uint16_t u16Index = index; uint8_t size = sizeof(uint16_t); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - if (memcpy_s(pc + FixInstructionIndex::FIX_FOUR, size, &u16Index, size) != EOK) { + if (memcpy_s(pc + payloadOffset + 2, size, &u16Index, size) != EOK) { LOG_ECMA(FATAL) << "memcpy_s failed"; UNREACHABLE(); } @@ -388,100 +406,110 @@ void PandaFileTranslator::FixInstructionId32(const BytecodeInstruction &inst, [[ } } +template void PandaFileTranslator::TranslateBytecode(uint32_t insSz, const uint8_t *insArr, const panda_file::File &pf, const JSMethod *method) { + using EnumT = std::conditional_t; + using R = BytecodeInstructionResolver; + auto bcIns = BytecodeInstruction(insArr); auto bcInsLast = bcIns.JumpTo(insSz); while (bcIns.GetAddress() != bcInsLast.GetAddress()) { - if (bcIns.HasFlag(BytecodeInstruction::Flags::STRING_ID) && BytecodeInstruction::HasId(bcIns.GetFormat(), 0)) { - auto index = GetOrInsertConstantPool(ConstPoolType::STRING, bcIns.GetId().AsFileId().GetOffset()); - FixInstructionId32(bcIns, index); + if (bcIns.HasFlag(BytecodeInstruction::Flags::STRING_ID) && + BytecodeInstruction::HasId(bcIns.GetFormat(), 0)) { + auto index = GetOrInsertConstantPool(ConstPoolType::STRING, bcIns.GetId().AsFileId().GetOffset()); + FixInstructionId32(bcIns, index); } else { - auto opcode = static_cast(bcIns.GetOpcode()); + auto opcode = bcIns.GetOpcode(); switch (opcode) { uint32_t index; uint32_t methodId; - case BytecodeInstruction::Opcode::ECMA_DEFINEFUNCDYN_PREF_ID16_V8: - methodId = pf.ResolveMethodIndex(method->GetFileId(), bcIns.GetId().AsIndex()).GetOffset(); + case R::template Get(): + methodId = pf.ResolveMethodIndex(method->GetFileId(), bcIns.GetId().AsIndex()).GetOffset(); index = GetOrInsertConstantPool(ConstPoolType::BASE_FUNCTION, methodId); - FixInstructionId32(bcIns, index); + FixInstructionId32(bcIns, index); break; - case BytecodeInstruction::Opcode::ECMA_DEFINENCFUNCDYN_PREF_ID16_V8: - methodId = pf.ResolveMethodIndex(method->GetFileId(), bcIns.GetId().AsIndex()).GetOffset(); + case R::template Get(): + methodId = pf.ResolveMethodIndex(method->GetFileId(), bcIns.GetId().AsIndex()).GetOffset(); index = GetOrInsertConstantPool(ConstPoolType::NC_FUNCTION, methodId); - FixInstructionId32(bcIns, index); + FixInstructionId32(bcIns, index); break; - case BytecodeInstruction::Opcode::ECMA_DEFINEGENERATORFUNC_PREF_ID16_V8: - methodId = pf.ResolveMethodIndex(method->GetFileId(), bcIns.GetId().AsIndex()).GetOffset(); + case R::template Get(): + methodId = pf.ResolveMethodIndex(method->GetFileId(), bcIns.GetId().AsIndex()).GetOffset(); index = GetOrInsertConstantPool(ConstPoolType::GENERATOR_FUNCTION, methodId); - FixInstructionId32(bcIns, index); + FixInstructionId32(bcIns, index); break; - case BytecodeInstruction::Opcode::ECMA_DEFINEASYNCFUNC_PREF_ID16_V8: - methodId = pf.ResolveMethodIndex(method->GetFileId(), bcIns.GetId().AsIndex()).GetOffset(); + case R::template Get(): + methodId = pf.ResolveMethodIndex(method->GetFileId(), bcIns.GetId().AsIndex()).GetOffset(); index = GetOrInsertConstantPool(ConstPoolType::ASYNC_FUNCTION, methodId); - FixInstructionId32(bcIns, index); + FixInstructionId32(bcIns, index); break; - case BytecodeInstruction::Opcode::ECMA_DEFINEASYNCGENERATORFUNC_PREF_ID16_V8: - methodId = pf.ResolveMethodIndex(method->GetFileId(), bcIns.GetId().AsIndex()).GetOffset(); + case R::template Get(): + methodId = pf.ResolveMethodIndex(method->GetFileId(), bcIns.GetId().AsIndex()).GetOffset(); index = GetOrInsertConstantPool(ConstPoolType::ASYNC_GENERATOR_FUNCTION, methodId); - FixInstructionId32(bcIns, index); + FixInstructionId32(bcIns, index); break; - case BytecodeInstruction::Opcode::ECMA_DEFINEMETHOD_PREF_ID16_V8: - methodId = pf.ResolveMethodIndex(method->GetFileId(), bcIns.GetId().AsIndex()).GetOffset(); + case R::template Get(): + methodId = pf.ResolveMethodIndex(method->GetFileId(), bcIns.GetId().AsIndex()).GetOffset(); index = GetOrInsertConstantPool(ConstPoolType::METHOD, methodId); - FixInstructionId32(bcIns, index); + FixInstructionId32(bcIns, index); break; - case BytecodeInstruction::Opcode::ECMA_CREATEOBJECTWITHBUFFER_PREF_IMM16: - case BytecodeInstruction::Opcode::ECMA_CREATEOBJECTHAVINGMETHOD_PREF_IMM16: + case R::template Get(): + case R::template Get(): index = GetOrInsertConstantPool(ConstPoolType::OBJECT_LITERAL, - bcIns.GetImm()); - FixInstructionId32(bcIns, index); + bcIns.GetId().AsFileId().GetOffset()); + FixInstructionId32(bcIns, index); break; - case BytecodeInstruction::Opcode::ECMA_CREATEARRAYWITHBUFFER_PREF_IMM16: + case R::template Get(): index = GetOrInsertConstantPool(ConstPoolType::ARRAY_LITERAL, - bcIns.GetImm()); - FixInstructionId32(bcIns, index); + bcIns.GetId().AsFileId().GetOffset()); + FixInstructionId32(bcIns, index); break; - case BytecodeInstruction::Opcode::ECMA_DEFINECLASSWITHBUFFER_PREF_ID16_IMM16_V8_V8: - methodId = pf.ResolveMethodIndex(method->GetFileId(), bcIns.GetId().AsIndex()).GetOffset(); + case R::template Get(): + methodId = pf.ResolveMethodIndex(method->GetFileId(), bcIns.GetId().AsIndex()).GetOffset(); index = GetOrInsertConstantPool(ConstPoolType::CLASS_FUNCTION, methodId); - FixInstructionId32(bcIns, index); - index = GetOrInsertConstantPool(ConstPoolType::CLASS_LITERAL, - bcIns.GetImm()); - FixInstructionId32(bcIns, index, 1); + FixInstructionId32(bcIns, index); + index = GetOrInsertConstantPool( + ConstPoolType::CLASS_LITERAL, + bcIns.GetImm()>()); + FixInstructionId32(bcIns, index, 1); break; default: break; } } - UpdateICOffset(const_cast(method), insSz, bcIns); - bcIns = bcIns.GetNext(); + UpdateICOffset(const_cast(method), insSz, bcIns); + bcIns = bcIns.GetNext(); } } +template void PandaFileTranslator::UpdateICOffset(JSMethod *method, uint32_t insSz, const BytecodeInstruction &inst) const { - auto opcode = inst.GetOpcode(); + using EnumT = std::conditional_t; + using R = BytecodeInstructionResolver; + + auto opcode = inst.GetOpcode(); uint32_t bc_offset = inst.GetAddress() - method->GetInstructions(); uint32_t slotSize = 0; switch (opcode) { - case BytecodeInstruction::Opcode::ECMA_TRYLDGLOBALBYNAME_PREF_ID32: - case BytecodeInstruction::Opcode::ECMA_TRYSTGLOBALBYNAME_PREF_ID32: - case BytecodeInstruction::Opcode::ECMA_LDGLOBALVAR_PREF_ID32: - case BytecodeInstruction::Opcode::ECMA_STGLOBALVAR_PREF_ID32: + case R::template Get(): + case R::template Get(): + case R::template Get(): + case R::template Get(): slotSize = ICRuntimeStub::SlotSizeForGlobalICByName(); break; - case BytecodeInstruction::Opcode::ECMA_LDOBJBYVALUE_PREF_V8_V8: - case BytecodeInstruction::Opcode::ECMA_STOBJBYVALUE_PREF_V8_V8: - case BytecodeInstruction::Opcode::ECMA_STOWNBYVALUE_PREF_V8_V8: + case R::template Get(): + case R::template Get(): + case R::template Get(): slotSize = ICRuntimeStub::SlotSizeForICByValue(); break; - case BytecodeInstruction::Opcode::ECMA_LDOBJBYNAME_PREF_ID32_V8: - case BytecodeInstruction::Opcode::ECMA_STOBJBYNAME_PREF_ID32_V8: - case BytecodeInstruction::Opcode::ECMA_STOWNBYNAME_PREF_ID32_V8: + case R::template Get(): + case R::template Get(): + case R::template Get(): slotSize = ICRuntimeStub::SlotSizeForICByName(); break; default: diff --git a/runtime/class_linker/panda_file_translator.h b/runtime/class_linker/panda_file_translator.h index 3aca4ffbc6aa8cc61231be36cbf1720758a55bfc..9f66b9b4e233098a0ec27a717efb27f24d723487 100644 --- a/runtime/class_linker/panda_file_translator.h +++ b/runtime/class_linker/panda_file_translator.h @@ -95,8 +95,11 @@ private: void TranslateClasses(const panda_file::File &pf, const PandaString &methodName); void TranslateMethod(const compiler::AotClass &aot_class, const panda_file::File::StringData &sd, const panda_file::File &pf, const uint8_t *descriptor, panda_file::MethodDataAccessor &mda); + template void TranslateBytecode(uint32_t insSz, const uint8_t *insArr, const panda_file::File &pf, const JSMethod *method); + template void FixInstructionId32(const BytecodeInstruction &inst, uint32_t index, uint32_t fixOrder = 0) const; + template void UpdateICOffset(JSMethod *method, uint32_t insSz, const BytecodeInstruction &inst) const; void DefineClassInConstPool(const JSHandle &constpool) const; diff --git a/runtime/interpreter/ecma-interpreter-inl.h b/runtime/interpreter/ecma-interpreter-inl.h index 053c1ef8672b4e8d1072d4af88c0aa9b96fc2876..6bbb040f9e5b8bd429d9e1370ad9cf522e8c6010 100644 --- a/runtime/interpreter/ecma-interpreter-inl.h +++ b/runtime/interpreter/ecma-interpreter-inl.h @@ -68,14 +68,13 @@ namespace panda::ecmascript { UNUSED_VAR(lhs); \ UNUSED_VAR(rhs) #endif - -template +template class JSFrameHelper { public: template ALWAYS_INLINE static uint32_t GetNumberActualArgsDyn([[maybe_unused]] InstructionHandler *instr_handler) { - return JSGetNumberActualArgsDyn(instr_handler->GetInst()); + return JSGetNumberActualArgsDyn(instr_handler->GetInst()); } template @@ -87,7 +86,8 @@ public: BytecodeInstruction prev_inst = instr_handler->GetInst(); auto *thread = JSThread::Cast(instr_handler->GetThread()); - JSCopyArgumets(thread, prev_frame, prev_v0, prev_inst, new_frame, num_vregs, num_actual_args); + JSCopyArgumets(thread, prev_frame, prev_v0, prev_inst, new_frame, num_vregs, + num_actual_args); } template @@ -99,17 +99,17 @@ public: } }; -template -class InstructionHandler : public interpreter::InstructionHandler { +template +class InstructionHandler : public interpreter::InstructionHandler { public: ALWAYS_INLINE inline InstructionHandler(interpreter::InstructionHandlerState *state) - : interpreter::InstructionHandler(state) + : interpreter::InstructionHandler(state) { } ALWAYS_INLINE JSThread *GetJSThread() const { - return JSThread::Cast(interpreter::InstructionHandler::GetThread()); + return JSThread::Cast(interpreter::InstructionHandler::GetThread()); } ALWAYS_INLINE JSTaggedValue GetRegAsTaggedValue(uint16_t v) @@ -196,7 +196,7 @@ public: // Update EcmascirptEnv js_thread->SetEcmascriptEnv(js_thread->GetEcmascriptEnv()->GetPrevEnvironment()); - interpreter::InstructionHandler::HandleReturnStackless(); + interpreter::InstructionHandler::HandleReturnStackless(); } template @@ -221,7 +221,7 @@ public: ASSERT(method->GetNumVregs() == 0); uint32_t num_declared_args = method->GetNumArgs(); - uint32_t num_actual_args = JSGetNumberActualArgsDyn(this->GetInst()); + uint32_t num_actual_args = JSGetNumberActualArgsDyn(this->GetInst()); uint32_t num_args = std::max(num_declared_args, num_actual_args); Frame *prev_frame = this->GetFrame(); @@ -229,7 +229,8 @@ public: Frame *frame = JSFrame::CreateNativeFrame(js_thread, method, js_thread->GetCurrentFrame(), num_args, num_actual_args); - JSCopyArgumets(this->GetJSThread(), prev_frame, v0, prev_inst, frame, 0, num_actual_args); + JSCopyArgumets(this->GetJSThread(), prev_frame, v0, prev_inst, frame, 0, + num_actual_args); // Call native method JSTaggedValue ret_value = JSFrame::ExecuteNativeMethod(js_thread, frame, method, num_actual_args); @@ -265,7 +266,9 @@ public: EcmascriptEnvironment *prev_env = js_thread->GetEcmascriptEnv(); // Call stackless interpreter - this->template CallInterpreterStackless, format, true, false, false, false>(method); + this->template CallInterpreterStackless, format, /* is_dynamic= */ true, + /* is_range= */ false, /* accept_acc= */ false, + /* initobj= */ false>(method); ConstantPool *constant_pool = ConstantPool::Cast(js_function->GetConstantPool().GetHeapObject()); JSTaggedValue lexical_env = js_function->GetLexicalEnv(); @@ -1553,22 +1556,22 @@ public: template ALWAYS_INLINE void HandleEcmaCreateobjectwithbuffer() { - auto imm = this->GetInst().template GetImm(); + auto literalarray_id = this->GetInst().template GetId(); LOG_INST() << "createobjectwithbuffer" - << " imm:" << imm; + << " literalArrayId:" << literalarray_id.AsIndex(); - INTRINSIC_CALL_CHECK_SETACC(intrinsics::CreateObjectWithBuffer(this->GetJSThread(), imm)); + INTRINSIC_CALL_CHECK_SETACC(intrinsics::CreateObjectWithBuffer(this->GetJSThread(), literalarray_id.AsIndex())); this->template MoveToNextInst(); } template ALWAYS_INLINE void HandleEcmaCreatearraywithbuffer() { - auto imm = this->GetInst().template GetImm(); + auto literalarray_id = this->GetInst().template GetId(); LOG_INST() << "createarraywithbuffer" - << " imm:" << imm; + << " literalArrayId:" << literalarray_id.AsIndex(); - INTRINSIC_CALL_CHECK_SETACC(intrinsics::CreateArrayWithBuffer(this->GetJSThread(), imm)); + INTRINSIC_CALL_CHECK_SETACC(intrinsics::CreateArrayWithBuffer(this->GetJSThread(), literalarray_id.AsIndex())); this->template MoveToNextInst(); } @@ -2181,13 +2184,14 @@ public: template ALWAYS_INLINE void HandleEcmaCreateobjecthavingmethod() { - auto imm = this->GetInst().template GetImm(); + auto literalarray_id = this->GetInst().template GetId(); LOG_INST() << "createobjecthavingmethod" - << " imm:" << imm; + << " literalArrayId:" << literalarray_id.AsIndex(); uint64_t env = GetAccAsTaggedValue().GetRawData(); - INTRINSIC_CALL_CHECK_SETACC(intrinsics::CreateObjectHavingMethod(this->GetJSThread(), imm, env)); + INTRINSIC_CALL_CHECK_SETACC( + intrinsics::CreateObjectHavingMethod(this->GetJSThread(), literalarray_id.AsIndex(), env)); this->template MoveToNextInst(); } diff --git a/runtime/interpreter/interpreter-inl.h b/runtime/interpreter/interpreter-inl.h index dc6cb69ab623bb28ed8348087b3a6ee2a83a730b..b3cb8b34893c2c23ddbbc2b30558044f13133e17 100644 --- a/runtime/interpreter/interpreter-inl.h +++ b/runtime/interpreter/interpreter-inl.h @@ -177,9 +177,11 @@ JSTaggedValue EcmaInterpreter::GeneratorReEnterInterpreter(JSThread *thread, JSH Method *method = func->GetCallTarget(); JSTaggedValue pcOffset = context->GetBCOffset(); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - const uint8_t *resumePc = method->GetInstructions() + static_cast(pcOffset.GetInt()) + - BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8); + auto Format = method->GetPandaFile()->GetHeader()->quickened_flag != 0U ? BytecodeInstruction::Format::V8 + : BytecodeInstruction::Format::PREF_V8; + const uint8_t *resumePc = + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + method->GetInstructions() + static_cast(pcOffset.GetInt()) + BytecodeInstruction::Size(Format); TaggedValue acc(context->GetAcc().GetRawData()); uint32_t nregs = context->GetNRegs().GetInt(); diff --git a/runtime/interpreter/js_decode_call_instr.h b/runtime/interpreter/js_decode_call_instr.h index 0d20e9dc61817d37cbbd8c0fa8cecdc3c1287906..ffb0f25483ddd73ef1208db55343ee4e3123b4c9 100644 --- a/runtime/interpreter/js_decode_call_instr.h +++ b/runtime/interpreter/js_decode_call_instr.h @@ -11,27 +11,29 @@ #include "plugins/ecmascript/runtime/js_thread.h" namespace panda::ecmascript { -template +template ALWAYS_INLINE inline uint32_t JSGetNumberActualArgsDyn([[maybe_unused]] BytecodeInstruction inst) { - if constexpr (opcode == BytecodeInstruction::Opcode::ECMA_CALL0DYN_PREF_V8) { - static_assert(format == BytecodeInstruction::Format::PREF_V8); + using R = BytecodeInstructionResolver; + constexpr auto op = R::template Get(); + if constexpr (op == R::template Get()) { + static_assert(format == R::template Get()); return NUM_MANDATORY_JSFUNC_ARGS + 0; - } else if constexpr (opcode == BytecodeInstruction::Opcode::ECMA_CALL1DYN_PREF_V8_V8) { - static_assert(format == BytecodeInstruction::Format::PREF_V8_V8); + } else if constexpr (op == R::template Get()) { + static_assert(format == R::template Get()); return NUM_MANDATORY_JSFUNC_ARGS + 1; - } else if constexpr (opcode == BytecodeInstruction::Opcode::ECMA_CALL2DYN_PREF_V8_V8_V8) { - static_assert(format == BytecodeInstruction::Format::PREF_V8_V8_V8); + } else if constexpr (op == R::template Get()) { + static_assert(format == R::template Get()); return NUM_MANDATORY_JSFUNC_ARGS + 2; - } else if constexpr (opcode == BytecodeInstruction::Opcode::ECMA_CALL3DYN_PREF_V8_V8_V8_V8) { - static_assert(format == BytecodeInstruction::Format::PREF_V8_V8_V8_V8); + } else if constexpr (op == R::template Get()) { + static_assert(format == R::template Get()); return NUM_MANDATORY_JSFUNC_ARGS + 3; - } else if constexpr (opcode == BytecodeInstruction::Opcode::ECMA_CALLIRANGEDYN_PREF_IMM16_V8) { - static_assert(format == BytecodeInstruction::Format::PREF_IMM16_V8); + } else if constexpr (op == R::template Get()) { + static_assert(format == R::template Get()); auto imm = inst.GetImm(); return NUM_MANDATORY_JSFUNC_ARGS + imm; - } else if constexpr (opcode == BytecodeInstruction::Opcode::ECMA_CALLITHISRANGEDYN_PREF_IMM16_V8) { - static_assert(format == BytecodeInstruction::Format::PREF_IMM16_V8); + } else if constexpr (op == R::template Get()) { + static_assert(format == R::template Get()); auto imm = inst.GetImm(); ASSERT(imm >= 1); // 'this' is always passed to the function return NUM_MANDATORY_JSFUNC_ARGS - 1 + imm; @@ -44,10 +46,10 @@ ALWAYS_INLINE inline uint32_t JSGetNumberActualArgsDyn([[maybe_unused]] Bytecode return 0; } -template +template ALWAYS_INLINE inline static void JSCopyArgumets(JSThread *thread, Frame *prev_frame, uint16_t prev_v0, - BytecodeInstruction prev_inst, Frame *new_frame, uint32_t num_vregs, - uint32_t num_actual_args) + [[maybe_unused]] BytecodeInstruction prev_inst, Frame *new_frame, + uint32_t num_vregs, uint32_t num_actual_args) { // ecma.call0dyn // ecma.call1dyn @@ -72,13 +74,16 @@ ALWAYS_INLINE inline static void JSCopyArgumets(JSThread *thread, Frame *prev_fr // ... // dyn_arg[N] - vreg[N-1] [ args[N-3] ] + using R = BytecodeInstructionResolver; + constexpr auto op = R::template Get(); + ASSERT(num_actual_args >= 3); uint64_t raw_fn_object = prev_frame->GetVReg(prev_v0).GetValue(); new_frame->GetVReg(num_vregs + 0).SetValue(raw_fn_object); new_frame->GetVReg(num_vregs + 1).SetValue(JSTaggedValue::VALUE_UNDEFINED); - if constexpr (opcode != BytecodeInstruction::Opcode::ECMA_CALLITHISRANGEDYN_PREF_IMM16_V8) { + if constexpr (op != R::template Get()) { JSTaggedValue fn_object(raw_fn_object); uint64_t dyn_arg2 = JSTaggedValue::VALUE_UNDEFINED; if (fn_object.IsJSFunction() && !JSFunction::Cast(fn_object.GetHeapObject())->IsStrict()) { @@ -87,32 +92,32 @@ ALWAYS_INLINE inline static void JSCopyArgumets(JSThread *thread, Frame *prev_fr new_frame->GetVReg(num_vregs + 2).SetValue(dyn_arg2); } - if constexpr (opcode == BytecodeInstruction::Opcode::ECMA_CALL0DYN_PREF_V8) { - static_assert(format == BytecodeInstruction::Format::PREF_V8); + if constexpr (op == R::template Get()) { + static_assert(format == R::template Get()); ASSERT(num_actual_args == 3); // Do nothing - } else if constexpr (opcode == BytecodeInstruction::Opcode::ECMA_CALL1DYN_PREF_V8_V8) { - static_assert(format == BytecodeInstruction::Format::PREF_V8_V8); + } else if constexpr (op == R::template Get()) { + static_assert(format == R::template Get()); ASSERT(num_actual_args == 3 + 1); - new_frame->GetVReg(num_vregs + 3 + 0) = prev_frame->GetVReg(prev_inst.GetVReg(1)); - } else if constexpr (opcode == BytecodeInstruction::Opcode::ECMA_CALL2DYN_PREF_V8_V8_V8) { - static_assert(format == BytecodeInstruction::Format::PREF_V8_V8_V8); + new_frame->GetVReg(num_vregs + 3 + 0) = prev_frame->GetVReg(prev_inst.GetVReg(1)); + } else if constexpr (op == R::template Get()) { + static_assert(format == R::template Get()); ASSERT(num_actual_args == 3 + 2); - new_frame->GetVReg(num_vregs + 3 + 0) = prev_frame->GetVReg(prev_inst.GetVReg(1)); - new_frame->GetVReg(num_vregs + 3 + 1) = prev_frame->GetVReg(prev_inst.GetVReg(2)); - } else if constexpr (opcode == BytecodeInstruction::Opcode::ECMA_CALL3DYN_PREF_V8_V8_V8_V8) { - static_assert(format == BytecodeInstruction::Format::PREF_V8_V8_V8_V8); + new_frame->GetVReg(num_vregs + 3 + 0) = prev_frame->GetVReg(prev_inst.GetVReg(1)); + new_frame->GetVReg(num_vregs + 3 + 1) = prev_frame->GetVReg(prev_inst.GetVReg(2)); + } else if constexpr (op == R::template Get()) { + static_assert(format == R::template Get()); ASSERT(num_actual_args == 3 + 3); - new_frame->GetVReg(num_vregs + 3 + 0) = prev_frame->GetVReg(prev_inst.GetVReg(1)); - new_frame->GetVReg(num_vregs + 3 + 1) = prev_frame->GetVReg(prev_inst.GetVReg(2)); - new_frame->GetVReg(num_vregs + 3 + 2) = prev_frame->GetVReg(prev_inst.GetVReg(3)); - } else if constexpr (opcode == BytecodeInstruction::Opcode::ECMA_CALLIRANGEDYN_PREF_IMM16_V8) { - static_assert(format == BytecodeInstruction::Format::PREF_IMM16_V8); + new_frame->GetVReg(num_vregs + 3 + 0) = prev_frame->GetVReg(prev_inst.GetVReg(1)); + new_frame->GetVReg(num_vregs + 3 + 1) = prev_frame->GetVReg(prev_inst.GetVReg(2)); + new_frame->GetVReg(num_vregs + 3 + 2) = prev_frame->GetVReg(prev_inst.GetVReg(3)); + } else if constexpr (op == R::template Get()) { + static_assert(format == R::template Get()); for (uint16_t i = 1; i < (num_actual_args - 2); ++i) { new_frame->GetVReg(num_vregs + 2 + i) = prev_frame->GetVReg(prev_v0 + i); } - } else if constexpr (opcode == BytecodeInstruction::Opcode::ECMA_CALLITHISRANGEDYN_PREF_IMM16_V8) { - static_assert(format == BytecodeInstruction::Format::PREF_IMM16_V8); + } else if constexpr (op == R::template Get()) { + static_assert(format == R::template Get()); for (uint16_t i = 0; i < (num_actual_args - 2); ++i) { new_frame->GetVReg(num_vregs + 2 + i) = prev_frame->GetVReg(prev_v0 + 1 + i); }