diff --git a/irtoc_scripts/common.irt b/irtoc_scripts/common.irt index b6cf45fa9becc36ba6d3e0760b39a0a348ef70ca..f810c893678ccff90af62a311fee6c31b177cffc 100644 --- a/irtoc_scripts/common.irt +++ b/irtoc_scripts/common.irt @@ -51,6 +51,7 @@ module Constants JS_OBJECT_PROPERTIES_FIELD = "runtime->GetFieldByOffset(cross_values::GetJsobjectPropertiesOffset(graph->GetArch()))" JS_OBJECT_ELEMENTS_FIELD = "runtime->GetFieldByOffset(cross_values::GetJsobjectElementsOffset(graph->GetArch()))" JS_ARRAY_LENGTH_FIELD = "runtime->GetFieldByOffset(cross_values::GetJsarrayLengthOffset(graph->GetArch()))" + JS_FUNCTION_METHOD_FIELD = "runtime->GetFieldByOffset(cross_values::GetJsfunctionMethodOffset(graph->GetArch()))" JS_FUNCTION_PROFILE_TYPE_INFO_FIELD = "runtime->GetFieldByOffset(cross_values::GetJsfunctionProfileTypeInfoOffset(graph->GetArch()))" JS_PROPERTY_BOX_VALUE_FIELD = "runtime->GetFieldByOffset(cross_values::GetJspropertyBoxValueOffset(graph->GetArch()))" JS_TRANSITION_HANDLER_HANDLER_INFO_FEILD = "runtime->GetFieldByOffset(cross_values::GetJstransitionHandlerHandlerInfoOffset(graph->GetArch()))" diff --git a/irtoc_scripts/interpreter_handlers.irt b/irtoc_scripts/interpreter_handlers.irt index 31f6d2898939435de291a9092a5fabe14ca89d85..e89452af8fb0e3aac2853f848c8ca58ece129621 100644 --- a/irtoc_scripts/interpreter_handlers.irt +++ b/irtoc_scripts/interpreter_handlers.irt @@ -1039,10 +1039,17 @@ macro(:get_ic) do || LoadObject(get_this_func()).ObjField(Constants::JS_FUNCTION_PROFILE_TYPE_INFO_FIELD).any end +macro(:map_ic_slot) do |ic_slot| + method_ptr := LoadObject(get_this_func()).ObjField(Constants::JS_FUNCTION_METHOD_FIELD).ptr + mapping := Load(method_ptr, "JSMETHOD_IC_OFFSET_MAPPING_OFFSET").ptr + Load(mapping, ic_slot).u8 +end + macro(:access_global_var_ic) do |key, value, ic_slot, access| ic := get_ic() IfImm(cmpanyundefined(ic)).Imm(0).CC(:CC_EQ).b { - handler := LoadArray(anytoheapobj(ic), ic_slot).any + ic_idx := map_ic_slot(ic_slot) + handler := LoadArray(anytoheapobj(ic), ic_idx).any IfImm(cmpanyheapobj(handler)).Imm(0).CC(:CC_NE).b { r = access.call(anytoheapobj(handler), value) r00 := r @@ -1229,6 +1236,7 @@ macro(:access_obj_ic) do |obj, value, ic_slot, access| Goto(:Miss) } + ic_slot := map_ic_slot(ic_slot) ic_cls := LoadArray(anytoheapobj(ic), ic_slot).any IfImm(cmpanyheapobj(ic_cls)).Imm(0).CC(:CC_EQ).b { Goto(:Miss) diff --git a/runtime/asm_defines/asm_defines.def b/runtime/asm_defines/asm_defines.def index bb99f6c06a69ef8dd7455e59961a6db9df7709bd..c1c0cd340ef10f080b2e772b199329a075e3cd5e 100644 --- a/runtime/asm_defines/asm_defines.def +++ b/runtime/asm_defines/asm_defines.def @@ -27,6 +27,7 @@ DEFINE_VALUE(JSHCLASS_HCLASS_OFFSET, panda::ecmascript::JSHClass::GetHClassOffse DEFINE_VALUE(JSOBJECT_PROPERTIES_OFFSET, panda::ecmascript::JSObject::PROPERTIES_OFFSET) DEFINE_VALUE(JSOBJECT_ELEMENTS_OFFSET, panda::ecmascript::JSObject::ELEMENTS_OFFSET) 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(JSPROPERTY_BOX_VALUE_OFFSET, panda::ecmascript::PropertyBox::VALUE_OFFSET) DEFINE_VALUE(JSTRANSITION_HANDLER_HANDLER_INFO_OFFSET, panda::ecmascript::TransitionHandler::HANDLER_INFO_OFFSET) @@ -43,3 +44,4 @@ DEFINE_VALUE(IC_HANDLER_INLINED_PROPS_BIT_START_BIT, panda::ecmascript::HandlerB DEFINE_VALUE(IC_HANDLER_INLINED_PROPS_BIT_MASK, panda::ecmascript::HandlerBase::InlinedPropsBit::MaxValue()) DEFINE_VALUE(IC_HANDLER_HANDLER_KIND_FIELD, static_cast(panda::ecmascript::HandlerBase::HandlerKind::FIELD)) DEFINE_VALUE(HCLASS_DATA_OFFSET, HClass::GetDataOffset()) +DEFINE_VALUE(JSMETHOD_IC_OFFSET_MAPPING_OFFSET, panda::ecmascript::JSMethod::GetICOffsetMappingOffset()) diff --git a/runtime/asm_defines/defines.h b/runtime/asm_defines/defines.h index 975128eb9cb569613f1eab66d17fd6fd16679be5..e6bdbc86d1978916b0dcfd886794b916a2c3db52 100644 --- a/runtime/asm_defines/defines.h +++ b/runtime/asm_defines/defines.h @@ -27,5 +27,6 @@ #include "plugins/ecmascript/runtime/js_for_in_iterator.h" #include "plugins/ecmascript/runtime/tagged_array.h" #include "plugins/ecmascript/runtime/tagged_queue.h" +#include "plugins/ecmascript/runtime/js_method.h" #endif // PLUGINS_ECMASCRIPT_RUNTIME_ASM_DEFINES_DEFINES_H diff --git a/runtime/class_linker/panda_file_translator.cpp b/runtime/class_linker/panda_file_translator.cpp index d5b8862f8754caca442893e7b5cdf8951d33f78d..f1a5d999fb953205d6313dc0b75a9c84bd612ab3 100644 --- a/runtime/class_linker/panda_file_translator.cpp +++ b/runtime/class_linker/panda_file_translator.cpp @@ -22,6 +22,7 @@ #include "plugins/ecmascript/runtime/class_info_extractor.h" #include "plugins/ecmascript/runtime/class_linker/program_object-inl.h" #include "plugins/ecmascript/runtime/global_env.h" +#include "plugins/ecmascript/runtime/ic/profile_type_info.h" #include "plugins/ecmascript/runtime/interpreter/interpreter.h" #include "plugins/ecmascript/runtime/js_array.h" #include "plugins/ecmascript/runtime/js_function.h" @@ -29,6 +30,7 @@ #include "plugins/ecmascript/runtime/literal_data_extractor.h" #include "plugins/ecmascript/runtime/object_factory.h" #include "plugins/ecmascript/runtime/tagged_array.h" +#include "plugins/ecmascript/runtime/ic/ic_runtime_stub.h" #include "libpandabase/mem/mem.h" #include "libpandabase/utils/logger.h" #include "libpandabase/utils/utf.h" @@ -66,10 +68,9 @@ static T *InitializeMemory(T *mem, Args... args) const JSMethod *PandaFileTranslator::FindMethods(uint32_t offset) const { - Span methods = GetMethods(); auto pred = [offset](const JSMethod &method) { return method.GetFileId().GetOffset() == offset; }; - auto it = std::find_if(methods.begin(), methods.end(), pred); - if (it != methods.end()) { + auto it = std::find_if(methods_->begin(), methods_->end(), pred); + if (it != methods_->end()) { return &*it; } return nullptr; @@ -77,22 +78,8 @@ const JSMethod *PandaFileTranslator::FindMethods(uint32_t offset) const void PandaFileTranslator::TranslateClasses(const panda_file::File &pf, const CString &methodName) { - RegionFactory *factory = ecmaVm_->GetRegionFactory(); Span classIndexes = pf.GetClasses(); - uint32_t numMethods = 0; - - for (const uint32_t index : classIndexes) { - panda_file::File::EntityId classId(index); - if (pf.IsExternal(classId)) { - continue; - } - panda_file::ClassDataAccessor cda(pf, classId); - numMethods += cda.GetMethodsNumber(); - } - - auto methodsData = factory->AllocateBuffer(sizeof(JSMethod) * numMethods); - Span methods {static_cast(methodsData), numMethods}; - size_t methodIdx = 0; + methods_ = MakePandaUnique>(); panda_file::File::StringData sd = {static_cast(methodName.size()), reinterpret_cast(methodName.c_str())}; @@ -112,23 +99,19 @@ void PandaFileTranslator::TranslateClasses(const panda_file::File &pf, const CSt compiler::AotClass aot_class = (aot_pfile != nullptr) ? aot_pfile->GetClass(classId.GetOffset()) : compiler::AotClass::Invalid(); - cda.EnumerateMethods( - [this, &aot_class, &sd, &methods, &methodIdx, &pf, &descriptor](panda_file::MethodDataAccessor &mda) { - TranslateMethod(aot_class, sd, methods, &methodIdx, pf, descriptor, mda); - }); + cda.EnumerateMethods([this, &aot_class, &sd, &pf, &descriptor](panda_file::MethodDataAccessor &mda) { + TranslateMethod(aot_class, sd, pf, descriptor, mda); + }); } - - SetMethods(methods, numMethods); } void PandaFileTranslator::TranslateMethod(const compiler::AotClass &aot_class, const panda_file::File::StringData &sd, - Span &methods, size_t *methodIdx, const panda_file::File &pf, - const uint8_t *descriptor, panda_file::MethodDataAccessor &mda) + const panda_file::File &pf, const uint8_t *descriptor, + panda_file::MethodDataAccessor &mda) { auto codeId = mda.GetCodeId(); ASSERT(codeId.has_value()); - JSMethod *method = &methods[(*methodIdx)++]; panda_file::CodeDataAccessor codeDataAccessor(pf, codeId.value()); uint32_t codeSize = codeDataAccessor.GetCodeSize(); @@ -148,11 +131,12 @@ void PandaFileTranslator::TranslateMethod(const compiler::AotClass &aot_class, c ASSERT(klass != nullptr); // Very important assert. - InitializeMemory(method, klass, &pf, mda.GetMethodId(), codeDataAccessor.GetCodeId(), mda.GetAccessFlags(), - codeDataAccessor.GetNumArgs(), reinterpret_cast(pda.GetShorty().Data())); + methods_->emplace_back(klass, &pf, mda.GetMethodId(), codeDataAccessor.GetCodeId(), mda.GetAccessFlags(), + codeDataAccessor.GetNumArgs(), reinterpret_cast(pda.GetShorty().Data())); + JSMethod *method = &methods_->back(); if (aot_class.IsValid()) { - auto entry = aot_class.FindMethodCodeEntry(*methodIdx - 1); + auto entry = aot_class.FindMethodCodeEntry(methods_->size() - 1); if (entry != nullptr) { method->SetCompiledEntryPoint(entry); } else { @@ -318,9 +302,7 @@ Program *PandaFileTranslator::GenerateProgram(const panda_file::File &pf) factory_->NewJSFunctionByDynClass(method, dynclass, FunctionKind::BASE_CONSTRUCTOR); mainFunc->SetConstantPool(thread_, constpool.GetTaggedValue()); program->SetMainFunction(thread_, mainFunc.GetTaggedValue()); - program->SetMethodsData(methods_); - methods_ = nullptr; - program->SetNumberMethods(numMethods_); + program->SetMethodsData(methods_.release()); // link program constpool->Set(thread_, constpoolIndex_, program.GetTaggedValue()); } @@ -474,43 +456,48 @@ void PandaFileTranslator::TranslateBytecode(uint32_t insSz, const uint8_t *insAr break; } } + UpdateICOffset(const_cast(method), insSz, bcIns); bcIns = bcIns.GetNext(); - UpdateICOffset(const_cast(method), bcIns); } } -void PandaFileTranslator::UpdateICOffset(JSMethod *method, const BytecodeInstruction &inst) const +void PandaFileTranslator::UpdateICOffset(JSMethod *method, uint32_t insSz, const BytecodeInstruction &inst) const { - uint32_t offset = method->GetSlotSize(); - if (UNLIKELY(offset == JSMethod::MAX_SLOT_SIZE)) { - return; - } - 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: + 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: + 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 BytecodeInstruction::Opcode::ECMA_LDSUPERBYVALUE_PREF_V8_V8: - case BytecodeInstruction::Opcode::ECMA_STSUPERBYVALUE_PREF_V8_V8: - case BytecodeInstruction::Opcode::ECMA_LDSUPERBYNAME_PREF_ID32_V8: - case BytecodeInstruction::Opcode::ECMA_STSUPERBYNAME_PREF_ID32_V8: - case BytecodeInstruction::Opcode::ECMA_LDMODVARBYNAME_PREF_ID32_V8: - case BytecodeInstruction::Opcode::ECMA_STMODULEVAR_PREF_ID32: - method->SetSlotSize(bc_offset + inst.GetSize()); + slotSize = ICRuntimeStub::SlotSizeForICByName(); break; default: return; } + uint8_t *icOffsetMapping = method->GetICOffsetMapping(); + if (icOffsetMapping == nullptr && insSz < ProfileTypeInfo::INVALID_SLOT_INDEX) { + icOffsetMapping = mem::InternalAllocator<>::GetInternalAllocatorFromRuntime()->AllocArray(insSz); + memset_s(icOffsetMapping, insSz, 0, insSz); + method->SetICOffsetMapping(icOffsetMapping); + } + if (icOffsetMapping != nullptr) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + icOffsetMapping[bc_offset] = method->GetSlotSize(); + method->AddSlotSize(slotSize); + } } uint32_t PandaFileTranslator::GetOrInsertConstantPool(ConstPoolType type, uint32_t offset) diff --git a/runtime/class_linker/panda_file_translator.h b/runtime/class_linker/panda_file_translator.h index 1c77bb5a78151e20ebf8109c2efc1f1e46c41ed6..4803cbc740cdb5087a6c9a7e97b74c2f4ced2a53 100644 --- a/runtime/class_linker/panda_file_translator.h +++ b/runtime/class_linker/panda_file_translator.h @@ -32,10 +32,7 @@ public: enum FixInstructionIndex : uint8_t { FIX_ONE = 1, FIX_TWO = 2, FIX_FOUR = 4 }; explicit PandaFileTranslator(EcmaVM *vm); - ~PandaFileTranslator() - { - ecmaVm_->GetRegionFactory()->FreeBuffer(methods_); - } + ~PandaFileTranslator() = default; NO_COPY_SEMANTIC(PandaFileTranslator); NO_MOVE_SEMANTIC(PandaFileTranslator); static JSHandle TranslatePandaFile(EcmaVM *vm, const panda_file::File &pf, const CString &methodName); @@ -97,31 +94,18 @@ private: Program *GenerateProgram(const panda_file::File &pf); void TranslateClasses(const panda_file::File &pf, const CString &methodName); void TranslateMethod(const compiler::AotClass &aot_class, const panda_file::File::StringData &sd, - Span &methods, size_t *methodIdx, const panda_file::File &pf, - const uint8_t *descriptor, panda_file::MethodDataAccessor &mda); + const panda_file::File &pf, const uint8_t *descriptor, panda_file::MethodDataAccessor &mda); void TranslateBytecode(uint32_t insSz, const uint8_t *insArr, const panda_file::File &pf, const JSMethod *method); void FixInstructionId32(const BytecodeInstruction &inst, uint32_t index, uint32_t fixOrder = 0) const; - void UpdateICOffset(JSMethod *method, const BytecodeInstruction &inst) const; + void UpdateICOffset(JSMethod *method, uint32_t insSz, const BytecodeInstruction &inst) const; void DefineClassInConstPool(const JSHandle &constpool) const; - void SetMethods(Span methods, const uint32_t numMethods) - { - methods_ = methods.data(); - numMethods_ = numMethods; - } - - Span GetMethods() const - { - return {methods_, numMethods_}; - } - EcmaVM *ecmaVm_; ObjectFactory *factory_; JSThread *thread_; uint32_t constpoolIndex_ {0}; - uint32_t numMethods_ {0}; uint32_t mainMethodIndex_ {0}; - JSMethod *methods_ {nullptr}; + PandaUniquePtr> methods_; std::unordered_map constpoolMap_; std::set translated_code_; diff --git a/runtime/class_linker/program_object-inl.h b/runtime/class_linker/program_object-inl.h index f96c1a62530e897a733a1aac9bc8e434f029f8fc..47f284e12fd4e799c15b2d92343498b30ba0931e 100644 --- a/runtime/class_linker/program_object-inl.h +++ b/runtime/class_linker/program_object-inl.h @@ -32,9 +32,10 @@ JSTaggedValue ConstantPool::GetObjectFromCache(uint32_t index) const return Get(index); } -void Program::FreeMethodData(RegionFactory *factory) +void Program::FreeMethodData() { - factory->FreeBuffer(GetMethodsData()); + mem::InternalAllocator<>::GetInternalAllocatorFromRuntime()->Delete(GetMethodsData()); + SetMethodsData(nullptr); } } // namespace panda::ecmascript #endif // ECMASCRIPT_CLASS_LINKER_PROGRAM_INL_H diff --git a/runtime/class_linker/program_object.h b/runtime/class_linker/program_object.h index 17996eae41a2870cf4a8dd8775323dc263c9595e..dd0bc09999cbeaf10879abda66b10d37c3ba49fe 100644 --- a/runtime/class_linker/program_object.h +++ b/runtime/class_linker/program_object.h @@ -31,10 +31,9 @@ public: ACCESSORS(Location, LOCATION_OFFSET, CONSTANT_POOL_OFFSET) ACCESSORS(ConstantPool, CONSTANT_POOL_OFFSET, MAIN_FUNCTION_OFFSET) ACCESSORS(MainFunction, MAIN_FUNCTION_OFFSET, METHODS_DATA_OFFSET) - SET_GET_NATIVE_FIELD(MethodsData, JSMethod, METHODS_DATA_OFFSET, NUMBER_METHODS_OFFSET) - SET_GET_PRIMITIVE_FIELD(NumberMethods, uint32_t, NUMBER_METHODS_OFFSET, SIZE); + SET_GET_NATIVE_FIELD(MethodsData, PandaList, METHODS_DATA_OFFSET, SIZE) - inline void FreeMethodData(RegionFactory *factory); + inline void FreeMethodData(); DECL_VISIT_OBJECT(LOCATION_OFFSET, METHODS_DATA_OFFSET) DECL_DUMP() diff --git a/runtime/dump.cpp b/runtime/dump.cpp index 36b7f3fdf3156c54e6ae38e288406f7a13c05ed7..50c6be37aa33e201629291c56bc2f281bd86f97f 100644 --- a/runtime/dump.cpp +++ b/runtime/dump.cpp @@ -947,8 +947,8 @@ void Program::Dump([[maybe_unused]] JSThread *thread, std::ostream &os) const os << " - MainFunction: "; GetMainFunction().D(); os << "\n"; - os << " - MethodsData: " << GetMethodsData() << "\n"; - os << " - NumberMethods: " << GetNumberMethods() << "\n"; + PandaList *methods = GetMethodsData(); + os << " - NumberMethods: " << methods->size() << "\n"; } void ConstantPool::Dump(JSThread *thread, std::ostream &os) const @@ -2477,7 +2477,7 @@ void Program::DumpForSnapshot([[maybe_unused]] JSThread *thread, vec.emplace_back(std::make_pair(CString("ConstantPool"), GetConstantPool())); vec.emplace_back(std::make_pair(CString("MainFunction"), GetMainFunction())); // MethodsData is another native field, and we don't dump it for JS heap. - vec.emplace_back(std::make_pair(CString("NumberMethods"), JSTaggedValue(GetNumberMethods()))); + vec.emplace_back(std::make_pair(CString("NumberMethods"), JSTaggedValue(GetMethodsData()->size()))); } void ConstantPool::DumpForSnapshot([[maybe_unused]] JSThread *thread, diff --git a/runtime/ecma_vm.cpp b/runtime/ecma_vm.cpp index fe51b35443311ea983f49609b28289ea92e1ee9e..1bb33f3c1879d830c8e065b40a44e4c2f5043f68 100644 --- a/runtime/ecma_vm.cpp +++ b/runtime/ecma_vm.cpp @@ -79,6 +79,8 @@ namespace panda::ecmascript { // NOLINTNEXTLINE(fuchsia-statically-constructed-objects) static const std::string_view ENTRY_POINTER = "_GLOBAL::func_main_0"; +// NOLINTNEXTLINE(fuchsia-statically-constructed-objects) +static const std::string_view ENTRY_METHOD_POINTER = "func_main_0"; JSRuntimeOptions EcmaVM::options_; // NOLINT(fuchsia-statically-constructed-objects) void EcmaRendezvous::SafepointBegin() @@ -807,7 +809,7 @@ void EcmaVM::ProcessPrograms(const WeakRootVisitor &v0) if (object != nullptr) { auto fwd = v0(object); if (fwd == nullptr) { - object->FreeMethodData(regionFactory_.get()); + object->FreeMethodData(); auto pf = std::get<1>(*iter); extractorCache_.erase(pf); delete pf; @@ -877,7 +879,7 @@ void EcmaVM::ClearBufferData() os::memory::LockHolder lock(pandaFileWithProgramLock_); for (auto iter = pandaFileWithProgram_.begin(); iter != pandaFileWithProgram_.end();) { - std::get<0>(*iter)->FreeMethodData(regionFactory_.get()); + std::get<0>(*iter)->FreeMethodData(); iter = pandaFileWithProgram_.erase(iter); } pandaFileWithProgram_.clear(); @@ -997,7 +999,12 @@ std::unique_ptr EcmaVM::OpenPandaFile(std::string_view l auto pf = panda_file::OpenPandaFile(location, "", open_mode); // PandaFileTranslator can trigger GC. ScopedManagedCodeThread s(thread_); - PandaFileTranslator::QuickPandaFile(this, *pf); + [[maybe_unused]] EcmaHandleScope handleScope(GetJSThread()); + auto program = PandaFileTranslator::TranslatePandaFile(this, *pf, ENTRY_METHOD_POINTER.data()); + { + os::memory::LockHolder lock(pandaFileWithProgramLock_); + pandaFileWithProgram_.emplace_back(program.GetObject(), pf.get(), false); + } return pf; } diff --git a/runtime/global_env_constants.cpp b/runtime/global_env_constants.cpp index 016a5c4fe837b131e26a82661d3b94f060e344a7..496267feccefca3c50c941b7e4ceacf1b31e1651 100644 --- a/runtime/global_env_constants.cpp +++ b/runtime/global_env_constants.cpp @@ -150,7 +150,6 @@ void GlobalEnvConstants::InitRootsClass([[maybe_unused]] JSThread *thread, JSHCl .GetTaggedValue()); JSHClass *programClass = *factory->NewEcmaDynClass(dynClassClass, Program::SIZE, JSType::PROGRAM); programClass->GetHClass()->MarkFieldAsNative(Program::METHODS_DATA_OFFSET); - programClass->GetHClass()->MarkFieldAsNative(Program::NUMBER_METHODS_OFFSET); SetConstant(ConstantIndex::PROGRAM_CLASS_INDEX, JSTaggedValue(programClass)); SetConstant(ConstantIndex::ECMA_MODULE_CLASS_INDEX, factory->NewEcmaDynClass(dynClassClass, EcmaModule::SIZE, JSType::ECMA_MODULE).GetTaggedValue()); diff --git a/runtime/ic/ic_runtime_stub-inl.h b/runtime/ic/ic_runtime_stub-inl.h index ce4114ea4cf6f5be27c429e804758091b7cb9e44..6998d9b8a4604633505b4d8b266a4669244ad7e6 100644 --- a/runtime/ic/ic_runtime_stub-inl.h +++ b/runtime/ic/ic_runtime_stub-inl.h @@ -42,6 +42,15 @@ bool ICRuntimeStub::HaveICForFunction(JSThread *thread) return !func->GetProfileTypeInfo().IsUndefined(); } +uint32_t ICRuntimeStub::MapSlotId(JSThread *thread, uint32_t slotId) +{ + auto *func = JSFunction::Cast(GetThisFunc(thread).GetHeapObject()); + uint8_t *mapping = func->GetMethod()->GetICOffsetMapping(); + ASSERT(mapping != nullptr); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + return mapping[slotId]; +} + ProfileTypeInfo *ICRuntimeStub::GetRuntimeProfileTypeInfo(JSThread *thread) { auto *func = JSFunction::Cast(GetThisFunc(thread).GetHeapObject()); @@ -54,6 +63,7 @@ JSTaggedValue ICRuntimeStub::LoadGlobalICByName(JSThread *thread, JSTaggedValue { INTERPRETER_TRACE(thread, LoadGlobalICByName); ASSERT(HaveICForFunction(thread)); + slotId = MapSlotId(thread, slotId); ProfileTypeInfo *profileTypeInfo = GetRuntimeProfileTypeInfo(thread); JSTaggedValue handler = profileTypeInfo->Get(slotId); if (handler.IsHeapObject()) { @@ -77,6 +87,7 @@ JSTaggedValue ICRuntimeStub::StoreGlobalICByName(JSThread *thread, JSTaggedValue { INTERPRETER_TRACE(thread, StoreGlobalICByName); ASSERT(HaveICForFunction(thread)); + slotId = MapSlotId(thread, slotId); ProfileTypeInfo *profileTypeInfo = GetRuntimeProfileTypeInfo(thread); JSTaggedValue handler = profileTypeInfo->Get(slotId); if (handler.IsHeapObject()) { @@ -116,6 +127,7 @@ JSTaggedValue ICRuntimeStub::LoadICByName(JSThread *thread, JSTaggedValue receiv { INTERPRETER_TRACE(thread, LoadICByName); ASSERT(HaveICForFunction(thread)); + slotId = MapSlotId(thread, slotId); ProfileTypeInfo *profileTypeInfo = GetRuntimeProfileTypeInfo(thread); JSTaggedValue hclassValue = profileTypeInfo->Get(slotId); if (hclassValue.IsHole()) { @@ -137,7 +149,7 @@ JSTaggedValue ICRuntimeStub::LoadICByName(JSThread *thread, JSTaggedValue receiv } index += 2U; hclassValue = profileTypeInfo->Get(index); - } while (index < slotId + 4U); + } while (index < slotId + SlotSizeForICByName()); } return LoadMissedICByName(thread, profileTypeInfo, receiver, key, slotId); } @@ -146,6 +158,7 @@ JSTaggedValue ICRuntimeStub::LoadICByValue(JSThread *thread, JSTaggedValue recei { INTERPRETER_TRACE(thread, LoadICByValue); ASSERT(HaveICForFunction(thread)); + slotId = MapSlotId(thread, slotId); ProfileTypeInfo *profileTypeInfo = GetRuntimeProfileTypeInfo(thread); JSTaggedValue firstValue = profileTypeInfo->Get(slotId); if (firstValue.IsHole()) { @@ -174,6 +187,7 @@ JSTaggedValue ICRuntimeStub::StoreICByValue(JSThread *thread, JSTaggedValue rece { INTERPRETER_TRACE(thread, StoreICByValue); ASSERT(HaveICForFunction(thread)); + slotId = MapSlotId(thread, slotId); ProfileTypeInfo *profileTypeInfo = GetRuntimeProfileTypeInfo(thread); JSTaggedValue firstValue = profileTypeInfo->Get(slotId); if (firstValue.IsHole()) { @@ -204,6 +218,7 @@ JSTaggedValue ICRuntimeStub::StoreICByName(JSThread *thread, JSTaggedValue recei { INTERPRETER_TRACE(thread, StoreICByName); ASSERT(HaveICForFunction(thread)); + slotId = MapSlotId(thread, slotId); ProfileTypeInfo *profileTypeInfo = GetRuntimeProfileTypeInfo(thread); JSTaggedValue hclassValue = profileTypeInfo->Get(slotId); if (hclassValue.IsHole()) { @@ -225,7 +240,7 @@ JSTaggedValue ICRuntimeStub::StoreICByName(JSThread *thread, JSTaggedValue recei } index += 2U; hclassValue = profileTypeInfo->Get(index); - } while (index < slotId + 4U); + } while (index < slotId + SlotSizeForICByName()); } return StoreMissedICByName(thread, profileTypeInfo, receiver, key, value, slotId); } diff --git a/runtime/ic/ic_runtime_stub.h b/runtime/ic/ic_runtime_stub.h index 9bb4a1b9e248720cc5079df72bec9ec0ef1be049..811e4d1fb9a9bf59c7c2653381d3365de847481b 100644 --- a/runtime/ic/ic_runtime_stub.h +++ b/runtime/ic/ic_runtime_stub.h @@ -25,6 +25,21 @@ class ProfileTypeInfo; class ICRuntimeStub { public: + static inline constexpr uint32_t SlotSizeForGlobalICByName() + { + return 1U; + } + + static inline constexpr uint32_t SlotSizeForICByName() + { + return 4U; + } + + static inline constexpr uint32_t SlotSizeForICByValue() + { + return 3U; + } + ARK_INLINE static inline bool HaveICForFunction(JSThread *thread); ARK_INLINE static inline JSTaggedValue LoadGlobalICByName(JSThread *thread, JSTaggedValue globalValue, JSTaggedValue key, uint32_t slotId, @@ -62,6 +77,7 @@ public: ARK_INLINE static inline uint32_t TryToElementsIndex(JSTaggedValue key); private: + static inline uint32_t MapSlotId(JSThread *thread, uint32_t slotId); static inline ProfileTypeInfo *GetRuntimeProfileTypeInfo(JSThread *thread); ARK_NOINLINE static JSTaggedValue LoadMissedICByName(JSThread *thread, ProfileTypeInfo *profileTypeArray, JSTaggedValue receiver, JSTaggedValue key, uint32_t slotId); diff --git a/runtime/interpreter/slow_runtime_stub.cpp b/runtime/interpreter/slow_runtime_stub.cpp index 17baf84df65648fd299fe5d72b588801069e960d..3add8462e55c15a11d11bba1082db66b3b31c5ff 100644 --- a/runtime/interpreter/slow_runtime_stub.cpp +++ b/runtime/interpreter/slow_runtime_stub.cpp @@ -1882,17 +1882,17 @@ void SlowRuntimeStub::ThrowDeleteSuperProperty(JSThread *thread) JSTaggedValue SlowRuntimeStub::NotifyInlineCache(JSThread *thread, JSFunction *func, JSMethod *method) { INTERPRETER_TRACE(thread, NotifyInlineCache); - uint32_t icSlotSize = method->GetSlotSize(); - if (icSlotSize > 0 && icSlotSize < ProfileTypeInfo::INVALID_SLOT_INDEX) { - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - [[maybe_unused]] EcmaHandleScope handleScope(thread); - - JSHandle funcHandle(thread, func); - JSHandle profileTypeInfo = factory->NewProfileTypeInfo(icSlotSize); - funcHandle->SetProfileTypeInfo(thread, profileTypeInfo.GetTaggedValue()); - return profileTypeInfo.GetTaggedValue(); + if (method->GetICOffsetMapping() == nullptr) { + return JSTaggedValue::Undefined(); } - return JSTaggedValue::Undefined(); + uint32_t icSlotSize = method->GetSlotSize(); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + + JSHandle funcHandle(thread, func); + JSHandle profileTypeInfo = factory->NewProfileTypeInfo(icSlotSize); + funcHandle->SetProfileTypeInfo(thread, profileTypeInfo.GetTaggedValue()); + return profileTypeInfo.GetTaggedValue(); } JSTaggedValue SlowRuntimeStub::ResolveClass(JSThread *thread, JSTaggedValue ctor, TaggedArray *literal, diff --git a/runtime/js_method.cpp b/runtime/js_method.cpp index 510c42960b9a1fc8a5cb9b38f16e77aa69a203b0..c180ec2242ec5ac23817f27e70484938d9a22d1a 100644 --- a/runtime/js_method.cpp +++ b/runtime/js_method.cpp @@ -18,6 +18,11 @@ #include "libpandafile/method_data_accessor-inl.h" namespace panda::ecmascript { +JSMethod::~JSMethod() +{ + mem::InternalAllocator<>::GetInternalAllocatorFromRuntime()->Free(icOffsetMapping_); +} + // It's not allowed '#' token appear in ECMA function(method) name, which discriminates same names in panda methods. CString JSMethod::ParseFunctionName() const { diff --git a/runtime/js_method.h b/runtime/js_method.h index ab212165c4bbfcbbff2e1cfdc8ca3762c70dfcc8..85471ddee79d33917c6fe31b013756872af27540 100644 --- a/runtime/js_method.h +++ b/runtime/js_method.h @@ -55,7 +55,7 @@ public: } JSMethod() = delete; - ~JSMethod() = default; + ~JSMethod(); JSMethod(const JSMethod &) = delete; JSMethod(JSMethod &&) = delete; JSMethod &operator=(const JSMethod &) = delete; @@ -86,23 +86,29 @@ public: return slotSize_; } - void UpdateSlotSize(uint32_t size) + void AddSlotSize(uint32_t size) { - uint64_t end = GetSlotSize() + size; - if (end >= MAX_SLOT_SIZE) { - slotSize_ = MAX_SLOT_SIZE; - return; - } - slotSize_ = static_cast(end); + slotSize_ += size; } - void SetSlotSize(uint32_t size) + uint8_t *GetICOffsetMapping() { - if (size >= MAX_SLOT_SIZE) { - slotSize_ = MAX_SLOT_SIZE; - return; - } - slotSize_ = size; + return icOffsetMapping_; + } + + const uint8_t *GetICOffsetMapping() const + { + return icOffsetMapping_; + } + + void SetICOffsetMapping(uint8_t *mapping) + { + icOffsetMapping_ = mapping; + } + + static constexpr size_t GetICOffsetMappingOffset() + { + return MEMBER_OFFSET(JSMethod, icOffsetMapping_); } uint32_t GetCallType() const @@ -120,6 +126,7 @@ private: const uint8_t *bytecodeArray_ {nullptr}; uint32_t bytecodeArraySize_ {0}; uint32_t slotSize_ {0}; + uint8_t *icOffsetMapping_ {nullptr}; uint32_t callType_ {UINT32_MAX}; // UINT32_MAX means not found }; } // namespace panda::ecmascript diff --git a/runtime/snapshot/mem/snapshot_serialize.cpp b/runtime/snapshot/mem/snapshot_serialize.cpp index 69d83bd37d80349f34b86db2cac1b1201df8b313..4f07d05d724e58c749afb6178a8bb1a8959400c5 100644 --- a/runtime/snapshot/mem/snapshot_serialize.cpp +++ b/runtime/snapshot/mem/snapshot_serialize.cpp @@ -1195,8 +1195,7 @@ void SnapShotSerialize::DynProgramSerialize(TaggedObject *objectHeader, uintptr_ auto fieldAddr = reinterpret_cast(startAddr + i * TAGGED_SIZE); SetObjectSlotField(snapshotObj, beginOffset + i * TAGGED_SIZE, HandleTaggedField(fieldAddr, queue, data)); } - SetObjectSlotField(snapshotObj, Program::METHODS_DATA_OFFSET, 0); // methods - SetObjectSlotField(snapshotObj, Program::NUMBER_METHODS_OFFSET, 0); // method_number + SetObjectSlotField(snapshotObj, Program::METHODS_DATA_OFFSET, 0); // methods } void SnapShotSerialize::DynProgramDeserialize(uint64_t *objectHeader, [[maybe_unused]] size_t objectSize) @@ -1216,7 +1215,6 @@ void SnapShotSerialize::DynProgramDeserialize(uint64_t *objectHeader, [[maybe_un auto program = reinterpret_cast(objectHeader); program->SetMethodsData(nullptr); - program->SetNumberMethods(0); } void SnapShotSerialize::SerializePandaFileMethod()