/* * Copyright (c) 2023 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. */ #include "ecmascript/jspandafile/program_object.h" #include "ecmascript/layout_info-inl.h" #include "ecmascript/mem/heap-inl.h" #include "ecmascript/runtime.h" #include "ecmascript/symbol_table.h" #include "ecmascript/jspandafile/program_object.h" // class Object; namespace panda::ecmascript { void ObjectFactory::NewSObjectHook() const { CHECK_NO_HEAP_ALLOC; #ifndef NDEBUG static std::atomic count = 0; static uint32_t frequency = vm_->GetJSOptions().GetForceSharedGCFrequency(); static constexpr uint32_t CONCURRENT_MARK_FREQUENCY_FACTOR = 2; if (frequency == 0 || !vm_->GetJSOptions().EnableForceGC() || !vm_->IsInitialized() || !thread_->IsAllContextsInitialized()) { return; } if (count++ % frequency == 0) { if (count % (CONCURRENT_MARK_FREQUENCY_FACTOR * frequency) == 0) { sHeap_->CollectGarbage(thread_); } else if (sHeap_->CheckCanTriggerConcurrentMarking(thread_)) { sHeap_->TriggerConcurrentMarking(thread_); } if (!ecmascript::AnFileDataManager::GetInstance()->IsEnable()) { sHeap_->WaitGCFinished(thread_); sHeap_->CollectGarbage(thread_); } } #endif } JSHandle ObjectFactory::CreateSFunctionClass(uint32_t size, JSType type, const JSHandle &prototype, bool isAccessor, bool setProto) { const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); uint32_t fieldOrder = 0; ASSERT(JSFunction::LENGTH_INLINE_PROPERTY_INDEX == fieldOrder); PropertyAttributes attributes = PropertyAttributes::Default(false, false, false); attributes.SetIsAccessor(isAccessor); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::TAGGED); JSHandle layoutInfoHandle = CreateSLayoutInfo(JSFunction::LENGTH_OF_INLINE_PROPERTIES); { attributes.SetOffset(fieldOrder); layoutInfoHandle->AddKey(thread_, fieldOrder, globalConst->GetLengthString(), attributes); fieldOrder++; } ASSERT(JSFunction::NAME_INLINE_PROPERTY_INDEX == fieldOrder); { attributes.SetOffset(fieldOrder); layoutInfoHandle->AddKey(thread_, fieldOrder, globalConst->GetHandledNameString().GetTaggedValue(), attributes); fieldOrder++; } if (setProto) { ASSERT(JSFunction::PROTOTYPE_INLINE_PROPERTY_INDEX == fieldOrder); { attributes.SetOffset(fieldOrder); layoutInfoHandle->AddKey(thread_, fieldOrder, globalConst->GetPrototypeString(), attributes); fieldOrder++; } } JSHandle functionClass = NewSEcmaHClass(size, fieldOrder, type, prototype, JSHandle(layoutInfoHandle)); functionClass->SetCallable(true); return functionClass; } JSHandle ObjectFactory::NewSEcmaHClass(uint32_t size, JSType type, uint32_t inlinedProps) { return NewSEcmaHClass(JSHClass::Cast(thread_->GlobalConstants()->GetHClassClass().GetTaggedObject()), size, type, inlinedProps); } JSHandle ObjectFactory::NewSEcmaHClass(JSHClass *hclass, uint32_t size, JSType type, uint32_t inlinedProps) { NewSObjectHook(); uint32_t classSize = JSHClass::SIZE; auto *newClass = static_cast(sHeap_->AllocateNonMovableOrHugeObject(thread_, hclass, classSize)); newClass->Initialize(thread_, size, type, inlinedProps, thread_->GlobalConstants()->GetHandledEmptySLayoutInfo()); return JSHandle(thread_, newClass); } // This function don't UpdateProtoClass JSHandle ObjectFactory::NewSEcmaHClass(uint32_t size, uint32_t inlinedProps, JSType type, const JSHandle &prototype, const JSHandle &layout) { NewSObjectHook(); uint32_t classSize = JSHClass::SIZE; auto *newClass = static_cast(sHeap_->AllocateNonMovableOrHugeObject( thread_, JSHClass::Cast(thread_->GlobalConstants()->GetHClassClass().GetTaggedObject()), classSize)); newClass->Initialize(thread_, size, type, inlinedProps, layout); JSHandle hclass(thread_, newClass); if (prototype->IsJSObject()) { prototype->GetTaggedObject()->GetClass()->SetIsPrototype(true); } hclass->SetProto(thread_, prototype.GetTaggedValue()); hclass->SetNumberOfProps(inlinedProps); hclass->SetExtensible(false); return hclass; } JSHandle ObjectFactory::NewSEcmaHClassDictMode(uint32_t size, uint32_t inlinedProps, JSType type, const JSHandle &prototype) { NewSObjectHook(); uint32_t classSize = JSHClass::SIZE; auto *newClass = static_cast(sHeap_->AllocateNonMovableOrHugeObject(thread_, JSHClass::Cast(thread_->GlobalConstants()->GetHClassClass().GetTaggedObject()), classSize)); newClass->Initialize(thread_, size, type, inlinedProps, thread_->GlobalConstants()->GetHandledEmptySLayoutInfo()); JSHandle hclass(thread_, newClass); if (prototype->IsJSObject()) { prototype->GetTaggedObject()->GetClass()->SetIsPrototype(true); } hclass->SetProto(thread_, prototype.GetTaggedValue()); hclass->SetNumberOfProps(0); hclass->SetIsDictionaryMode(true); hclass->SetExtensible(false); return hclass; } JSHandle ObjectFactory::NewSEcmaHClassClass(JSHClass *hclass, uint32_t size, JSType type) { NewSObjectHook(); uint32_t classSize = JSHClass::SIZE; auto *newClass = static_cast(sHeap_->AllocateClassClass(thread_, hclass, classSize)); newClass->Initialize(thread_, size, type, 0, thread_->GlobalConstants()->GetHandledEmptySLayoutInfo()); return JSHandle(thread_, newClass); } JSHandle ObjectFactory::NewSEcmaReadOnlyHClass(JSHClass *hclass, uint32_t size, JSType type, uint32_t inlinedProps) { NewSObjectHook(); uint32_t classSize = JSHClass::SIZE; auto *newClass = static_cast(sHeap_->AllocateReadOnlyOrHugeObject(thread_, hclass, classSize)); ASSERT(newClass != nullptr); newClass->Initialize(thread_, size, type, inlinedProps, thread_->GlobalConstants()->GetHandledEmptySLayoutInfo()); return JSHandle(thread_, newClass); } JSHandle ObjectFactory::InitSClassClass() { JSHandle hClassHandle = NewSEcmaHClassClass(nullptr, JSHClass::SIZE, JSType::HCLASS); JSHClass *hclass = reinterpret_cast(hClassHandle.GetTaggedValue().GetTaggedObject()); hclass->SetClass(thread_, hclass); return hClassHandle; } JSHandle ObjectFactory::NewSAccessorData() { NewSObjectHook(); TaggedObject *header = sHeap_->AllocateOldOrHugeObject( thread_, JSHClass::Cast(thread_->GlobalConstants()->GetAccessorDataClass().GetTaggedObject())); JSHandle acc(thread_, AccessorData::Cast(header)); acc->SetGetter(thread_, JSTaggedValue::Undefined()); acc->SetSetter(thread_, JSTaggedValue::Undefined()); return acc; } JSHandle ObjectFactory::NewSMethod(const JSPandaFile *jsPandaFile, MethodLiteral *methodLiteral, JSHandle constpool, uint32_t entryIndex, bool needSetAotFlag, bool *canFastCall) { JSHandle method; if (jsPandaFile->IsNewVersion()) { method = Method::Create(thread_, jsPandaFile, methodLiteral); } else { method = NewSMethod(methodLiteral); method->SetConstantPool(thread_, constpool); } if (needSetAotFlag) { auto aotFileManager = thread_->GetEcmaVM()->GetAOTFileManager(); aotFileManager->SetAOTFuncEntry(jsPandaFile, nullptr, *method, entryIndex, canFastCall); } else { method->InitInterpreterStatusForCompiledMethod(thread_); } return method; } JSHandle ObjectFactory::NewSMethod(const MethodLiteral *methodLiteral, MemSpaceType spaceType) { ASSERT(spaceType == SHARED_NON_MOVABLE || spaceType == SHARED_OLD_SPACE); NewSObjectHook(); TaggedObject *header = nullptr; if (spaceType == SHARED_NON_MOVABLE) { header = sHeap_->AllocateNonMovableOrHugeObject(thread_, JSHClass::Cast(thread_->GlobalConstants()->GetMethodClass().GetTaggedObject())); } else { header = sHeap_->AllocateOldOrHugeObject(thread_, JSHClass::Cast(thread_->GlobalConstants()->GetMethodClass().GetTaggedObject())); } JSHandle method(thread_, header); InitializeMethod(methodLiteral, method); return method; } JSHandle ObjectFactory::NewSMethodForNativeFunction(const void *func, FunctionKind kind, kungfu::BuiltinsStubCSigns::ID builtinId, MemSpaceType spaceType) { uint32_t numArgs = 2; // function object and this auto method = NewSMethod(nullptr, spaceType); method->SetNativePointer(const_cast(func)); method->SetNativeBit(true); if (builtinId != kungfu::BuiltinsStubCSigns::INVALID) { bool isFast = kungfu::BuiltinsStubCSigns::IsFastBuiltin(builtinId); method->SetFastBuiltinBit(isFast); method->SetBuiltinId(static_cast(builtinId)); } method->SetNumArgsWithCallField(numArgs); method->SetFunctionKind(kind); return method; } JSHandle ObjectFactory::NewSFunctionByHClass(const JSHandle &method, const JSHandle &hclass) { JSHandle function(NewSharedOldSpaceJSObject(hclass)); hclass->SetCallable(true); JSFunction::InitializeSFunction(thread_, function, method->GetFunctionKind()); function->SetMethod(thread_, method); function->SetTaskConcurrentFuncFlag(0); // 0 : default value if (method->IsAotWithCallField()) { thread_->GetEcmaVM()->GetAOTFileManager()-> SetAOTFuncEntry(method->GetJSPandaFile(), *function, *method); } return function; } // new function with name/length accessor JSHandle ObjectFactory::NewSFunctionWithAccessor(const void *func, const JSHandle &hclass, FunctionKind kind, kungfu::BuiltinsStubCSigns::ID builtinId, MemSpaceType spaceType) { ASSERT(spaceType == SHARED_NON_MOVABLE || spaceType == SHARED_OLD_SPACE); JSHandle method = NewSMethodForNativeFunction(func, kind, builtinId, spaceType); return NewSFunctionByHClass(method, hclass); } // new function without name/length accessor JSHandle ObjectFactory::NewSFunctionByHClass(const void *func, const JSHandle &hclass, FunctionKind kind, kungfu::BuiltinsStubCSigns::ID builtinId, MemSpaceType spaceType) { ASSERT(spaceType == SHARED_NON_MOVABLE || spaceType == SHARED_OLD_SPACE); JSHandle method = NewSMethodForNativeFunction(func, kind, builtinId, spaceType); JSHandle function(NewSharedOldSpaceJSObject(hclass)); hclass->SetCallable(true); JSFunction::InitializeWithDefaultValue(thread_, function); function->SetMethod(thread_, method); return function; } TaggedObject *ObjectFactory::NewSharedOldSpaceObject(const JSHandle &hclass) { NewSObjectHook(); TaggedObject *header = sHeap_->AllocateOldOrHugeObject(thread_, *hclass); if (header == nullptr) { LOG_ECMA(FATAL) << "ObjectFactory::NewSharedOldSpaceObject:header is nullptr"; } uint32_t inobjPropCount = hclass->GetInlinedProperties(); if (inobjPropCount > 0) { InitializeExtraProperties(hclass, header, inobjPropCount); } return header; } JSHandle ObjectFactory::NewSharedOldSpaceJSObjectWithInit(const JSHandle &jshclass) { auto obj = NewSharedOldSpaceJSObject(jshclass); InitializeJSObject(obj, jshclass); return obj; } JSHandle ObjectFactory::NewSharedOldSpaceJSObject(const JSHandle &jshclass) { JSHandle obj(thread_, JSObject::Cast(NewSharedOldSpaceObject(jshclass))); JSHandle emptyArray = SharedEmptyArray(); obj->InitializeHash(); obj->SetElements(thread_, emptyArray); obj->SetProperties(thread_, emptyArray); return obj; } JSHandle ObjectFactory::CreateSObjectWithProperties(std::vector &descs) { JSHandle hclass = JSHClass::CreateSHClass(thread_, descs); JSHandle object = NewSharedOldSpaceJSObject(hclass); JSObject::SetSProperties(thread_, object, descs); JSHandle env = vm_->GetGlobalEnv(); JSHandle objFuncProto = env->GetSObjectFunctionPrototype(); hclass->SetPrototype(thread_, objFuncProto); hclass->SetExtensible(false); return JSHandle(object); } JSHandle ObjectFactory::SharedEmptyArray() const { return JSHandle(thread_->GlobalConstants()->GetHandledEmptyArray()); } JSHandle ObjectFactory::CopySArray(const JSHandle &old, uint32_t oldLength, uint32_t newLength, JSTaggedValue initVal, ElementsKind kind) { if (newLength == 0) { return SharedEmptyArray(); } if (newLength > oldLength) { return ExtendSArray(old, newLength, initVal, kind); } NewObjectHook(); // Shared-array does not support Mutantarray yet. ASSERT(!old->GetClass()->IsMutantTaggedArray()); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength); JSHClass *arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()); TaggedObject *header = sHeap_->AllocateOldOrHugeObject(thread_, arrayClass, size); JSHandle newArray(thread_, header); newArray->SetLength(newLength); newArray->SetExtraLength(old->GetExtraLength()); for (uint32_t i = 0; i < newLength; i++) { newArray->Set(thread_, i, old->Get(i)); } return newArray; } JSHandle ObjectFactory::ExtendSArray(const JSHandle &old, uint32_t length, JSTaggedValue initVal, [[maybe_unused]] ElementsKind kind) { ASSERT(length > old->GetLength()); NewObjectHook(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); JSHClass *arrayClass = nullptr; // Shared-array does not support Mutantarray yet. ASSERT(!old->GetClass()->IsMutantTaggedArray()); arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()); TaggedObject *header = sHeap_->AllocateOldOrHugeObject(thread_, arrayClass, size); JSHandle newArray(thread_, header); newArray->SetLength(length); newArray->SetExtraLength(old->GetExtraLength()); uint32_t oldLength = old->GetLength(); for (uint32_t i = 0; i < oldLength; i++) { newArray->Set(thread_, i, old->Get(i)); } for (uint32_t i = oldLength; i < length; i++) { newArray->Set(thread_, i, initVal); } return newArray; } JSHandle ObjectFactory::NewSTaggedArrayWithoutInit(uint32_t length, MemSpaceType spaceType) { NewSObjectHook(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); TaggedObject *header; auto arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()); switch (spaceType) { case MemSpaceType::SHARED_OLD_SPACE: header = sHeap_->AllocateOldOrHugeObject(thread_, arrayClass, size); break; case MemSpaceType::SHARED_READ_ONLY_SPACE: header = sHeap_->AllocateReadOnlyOrHugeObject(thread_, arrayClass, size); break; default: LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); } JSHandle array(thread_, header); array->SetLength(length); return array; } JSHandle ObjectFactory::CreateSLayoutInfo(uint32_t properties) { uint32_t arrayLength = LayoutInfo::ComputeArrayLength(properties); JSHandle layoutInfoHandle = JSHandle::Cast(NewSTaggedArrayWithoutInit(arrayLength)); layoutInfoHandle->Initialize(thread_); return layoutInfoHandle; } JSHandle ObjectFactory::NewSEmptyLayoutInfo() { JSHandle layoutInfoHandle = JSHandle::Cast( NewSTaggedArrayWithoutInit(0, MemSpaceType::SHARED_READ_ONLY_SPACE)); layoutInfoHandle->Initialize(thread_); return layoutInfoHandle; } JSHandle ObjectFactory::NewJSSArray() { JSHandle env = vm_->GetGlobalEnv(); JSHandle function(env->GetSharedArrayFunction()); return JSHandle(NewJSObjectByConstructor(function)); } JSHandle ObjectFactory::NewSJsonFixedArray(size_t start, size_t length, const std::vector> &vec) { if (length == 0) { return SharedEmptyArray(); } JSHandle array = NewTaggedArrayWithoutInit(length, MemSpaceType::SHARED_OLD_SPACE); array->SetExtraLength(0); for (size_t i = 0; i < length; i++) { array->Set(thread_, i, vec[start + i]); } return array; } JSHandle ObjectFactory::CopyAndReSortSLayoutInfo(const JSHandle &old, int end, int capacity) { ASSERT(capacity >= end); JSHandle newArr = CreateSLayoutInfo(capacity); Span sp(old->GetProperties(), end); for (int i = 0; i < end; i++) { newArr->AddKey(thread_, i, sp[i].key_, PropertyAttributes(sp[i].attr_)); } return newArr; } JSHandle ObjectFactory::NewSDictionaryArray(uint32_t length) { NewSObjectHook(); ASSERT(length > 0); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); auto header = sHeap_->AllocateOldOrHugeObject( thread_, JSHClass::Cast(thread_->GlobalConstants()->GetDictionaryClass().GetTaggedObject()), size); JSHandle array(thread_, header); array->InitializeWithSpecialValue(JSTaggedValue::Undefined(), length); return array; } JSHandle ObjectFactory::NewSEmptyProfileTypeInfoCell() { NewSObjectHook(); auto header = sHeap_->AllocateReadOnlyOrHugeObject(thread_, JSHClass::Cast(thread_->GlobalConstants()->GetProfileTypeInfoCell0Class().GetTaggedObject())); JSHandle profileTypeInfoCell(thread_, header); profileTypeInfoCell->SetValue(thread_, JSTaggedValue::Undefined()); profileTypeInfoCell->SetMachineCode(thread_, JSTaggedValue::Hole()); profileTypeInfoCell->SetHandle(thread_, JSTaggedValue::Undefined()); return profileTypeInfoCell; } JSHandle ObjectFactory::NewSFunctionTemplate( const JSHandle &method, const JSHandle &module, int32_t length) { NewSObjectHook(); auto globalConstants = thread_->GlobalConstants(); auto header = sHeap_->AllocateOldOrHugeObject(thread_, JSHClass::Cast(globalConstants->GetFunctionTemplateClass().GetTaggedObject())); JSHandle functionTemplate(thread_, header); functionTemplate->SetMethod(thread_, method); functionTemplate->SetModule(thread_, module); functionTemplate->SetRawProfileTypeInfo(thread_, globalConstants->GetEmptyProfileTypeInfoCell(), SKIP_BARRIER); functionTemplate->SetLength(length); return functionTemplate; } JSHandle ObjectFactory::NewSEmptyArray() { NewSObjectHook(); auto header = sHeap_->AllocateReadOnlyOrHugeObject(thread_, JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), TaggedArray::SIZE); JSHandle array(thread_, header); array->SetLength(0); array->SetExtraLength(0); return array; } JSHandle ObjectFactory::NewSEmptyMutantArray() { NewSObjectHook(); auto header = sHeap_->AllocateReadOnlyOrHugeObject(thread_, JSHClass::Cast(thread_->GlobalConstants()->GetMutantTaggedArrayClass().GetTaggedObject()), TaggedArray::SIZE); JSHandle array(thread_, header); array->SetLength(0); array->SetExtraLength(0); return array; } JSHandle ObjectFactory::NewSJSNativePointer(void *externalPointer, const NativePointerCallback &callBack, void *data, bool nonMovable, size_t nativeBindingsize, NativeFlag flag) { NewSObjectHook(); TaggedObject *header; auto jsNativePointerClass = JSHClass::Cast(thread_->GlobalConstants()->GetSJSNativePointerClass().GetTaggedObject()); jsNativePointerClass->SetIsJSShared(true); if (nonMovable) { header = sHeap_->AllocateNonMovableOrHugeObject(thread_, jsNativePointerClass); } else { header = sHeap_->AllocateOldOrHugeObject(thread_, jsNativePointerClass); } JSHandle obj(thread_, header); obj->SetExternalPointer(externalPointer); obj->SetDeleter(callBack); obj->SetData(data); uint32_t fixedNativeBindingsize = nativeBindingsize < UINT32_MAX ? nativeBindingsize : UINT32_MAX; obj->SetBindingSize(fixedNativeBindingsize); obj->SetNativeFlag(flag); if (callBack != nullptr) { sHeap_->IncNativeSizeAfterLastGC(fixedNativeBindingsize); Runtime::GetInstance()->PushToSharedNativePointerList(static_cast(header)); // In some cases, the size of JS/TS object is too small and the native binding size is too large. // Check and try trigger concurrent mark here. size_t nativeSizeAfterLastGC = sHeap_->GetNativeSizeAfterLastGC(); if (nativeSizeAfterLastGC > sHeap_->GetNativeSizeTriggerSharedGC()) { sHeap_->CollectGarbage(thread_); } else if (sHeap_->CheckCanTriggerConcurrentMarking(thread_) && nativeSizeAfterLastGC > sHeap_->GetNativeSizeTriggerSharedCM()) { sHeap_->TriggerConcurrentMarking(thread_); } } return obj; } JSHandle ObjectFactory::NewSReadOnlyJSNativePointer(void* externalPointer) { NewSObjectHook(); auto jsNativePointerClass = JSHClass::Cast(thread_->GlobalConstants()->GetSJSNativePointerClass().GetTaggedObject()); jsNativePointerClass->SetIsJSShared(true); TaggedObject* header = sHeap_->AllocateReadOnlyOrHugeObject(thread_, jsNativePointerClass); JSHandle obj(thread_, header); obj->SetExternalPointer(externalPointer); obj->SetDeleter(nullptr); obj->SetData(nullptr); obj->SetBindingSize(0U); obj->SetNativeFlag(NativeFlag::NO_DIV); return obj; } JSHandle ObjectFactory::NewSInternalAccessor(void *setter, void *getter) { NewSObjectHook(); TaggedObject *header = sHeap_->AllocateReadOnlyOrHugeObject(thread_, JSHClass::Cast(thread_->GlobalConstants()->GetInternalAccessorClass().GetTaggedObject())); JSHandle obj(thread_, InternalAccessor::Cast(header)); obj->SetSetter(reinterpret_cast(setter)); obj->SetGetter(reinterpret_cast(getter)); return JSHandle::Cast(obj); } JSHandle ObjectFactory::NewSConstantPool(uint32_t capacity) { NewSObjectHook(); size_t size = ConstantPool::ComputeSize(capacity); auto header = sHeap_->AllocateOldOrHugeObject( thread_, JSHClass::Cast(sHeap_->GetGlobalConst()->GetConstantPoolClass().GetTaggedObject()), size); JSHandle array(thread_, header); array->InitializeWithSpecialValue(thread_, JSTaggedValue::Hole(), capacity); return array; } JSHandle ObjectFactory::NewSCOWTaggedArray(uint32_t length, JSTaggedValue initVal) { NewSObjectHook(); ASSERT(length > 0); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); auto header = sHeap_->AllocateNonMovableOrHugeObject( thread_, JSHClass::Cast(sHeap_->GetGlobalConst()->GetCOWArrayClass().GetTaggedObject()), size); JSHandle cowArray(thread_, header); cowArray->InitializeWithSpecialValue(initVal, length); return cowArray; } JSHandle ObjectFactory::NewSClassLiteral() { NewSObjectHook(); TaggedObject *header = sHeap_->AllocateOldOrHugeObject( thread_, JSHClass::Cast(sHeap_->GetGlobalConst()->GetClassLiteralClass().GetTaggedObject())); JSHandle emptyArray = EmptyArray(); JSHandle classLiteral(thread_, header); classLiteral->SetArray(thread_, emptyArray); classLiteral->SetIsAOTUsed(false); return classLiteral; } JSHandle ObjectFactory::NewSClassInfoExtractor( JSHandle method) { NewSObjectHook(); TaggedObject *header = sHeap_->AllocateOldOrHugeObject( thread_, JSHClass::Cast(sHeap_->GetGlobalConst()->GetClassInfoExtractorHClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->ClearBitField(); obj->SetConstructorMethod(thread_, method.GetTaggedValue()); JSHandle emptyArray = EmptyArray(); obj->SetNonStaticKeys(thread_, emptyArray, SKIP_BARRIER); obj->SetNonStaticProperties(thread_, emptyArray, SKIP_BARRIER); obj->SetNonStaticElements(thread_, emptyArray, SKIP_BARRIER); obj->SetStaticKeys(thread_, emptyArray, SKIP_BARRIER); obj->SetStaticProperties(thread_, emptyArray, SKIP_BARRIER); obj->SetStaticElements(thread_, emptyArray, SKIP_BARRIER); return obj; } JSHandle ObjectFactory::NewSOldSpaceTaggedArray(uint32_t length, JSTaggedValue initVal) { return NewSTaggedArray(length, initVal, MemSpaceType::SHARED_OLD_SPACE); } JSHandle ObjectFactory::NewSTaggedArray(uint32_t length, JSTaggedValue initVal, MemSpaceType spaceType) { NewSObjectHook(); if (length == 0) { return EmptyArray(); } size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); TaggedObject *header = nullptr; JSHClass *arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()); switch (spaceType) { case MemSpaceType::SHARED_OLD_SPACE: header = sHeap_->AllocateOldOrHugeObject(thread_, arrayClass, size); break; case MemSpaceType::SHARED_NON_MOVABLE: header = sHeap_->AllocateNonMovableOrHugeObject(thread_, arrayClass, size); break; default: LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); } JSHandle array(thread_, header); array->InitializeWithSpecialValue(initVal, length); return array; } JSHandle ObjectFactory::NewSWellKnownSymbol(const JSHandle &name) { NewSObjectHook(); TaggedObject *header = sHeap_->AllocateNonMovableOrHugeObject( thread_, JSHClass::Cast(thread_->GlobalConstants()->GetSymbolClass().GetTaggedObject())); JSHandle obj(thread_, JSSymbol::Cast(header)); obj->SetFlags(0); obj->SetWellKnownSymbol(); obj->SetDescription(thread_, name); obj->SetHashField(SymbolTable::Hash(name.GetTaggedValue())); return obj; } JSHandle ObjectFactory::NewSPublicSymbol(const JSHandle &name) { NewObjectHook(); TaggedObject *header = sHeap_->AllocateNonMovableOrHugeObject( thread_, JSHClass::Cast(thread_->GlobalConstants()->GetSymbolClass().GetTaggedObject())); JSHandle obj(thread_, JSSymbol::Cast(header)); obj->SetFlags(0); obj->SetDescription(thread_, name); obj->SetHashField(SymbolTable::Hash(name.GetTaggedValue())); return obj; } JSHandle ObjectFactory::NewSEmptySymbol() { NewObjectHook(); TaggedObject *header = sHeap_->AllocateNonMovableOrHugeObject( thread_, JSHClass::Cast(thread_->GlobalConstants()->GetSymbolClass().GetTaggedObject())); JSHandle obj(thread_, JSSymbol::Cast(header)); obj->SetDescription(thread_, JSTaggedValue::Undefined()); obj->SetFlags(0); obj->SetHashField(0); return obj; } JSHandle ObjectFactory::NewSWellKnownSymbolWithChar(std::string_view description) { JSHandle string = NewFromUtf8(description); return NewSWellKnownSymbol(JSHandle(string)); } JSHandle ObjectFactory::NewSPublicSymbolWithChar(std::string_view description) { JSHandle string = NewFromUtf8(description); return NewSPublicSymbol(JSHandle(string)); } JSHandle ObjectFactory::NewSSourceTextModule() { NewObjectHook(); TaggedObject *header = sHeap_->AllocateOldOrHugeObject(thread_, JSHClass::Cast(thread_->GlobalConstants()->GetSourceTextModuleClass().GetTaggedObject())); JSHandle obj(thread_, header); JSTaggedValue undefinedValue = thread_->GlobalConstants()->GetUndefined(); obj->SetEnvironment(thread_, undefinedValue); obj->SetNamespace(thread_, undefinedValue); obj->SetRequestedModules(thread_, undefinedValue); obj->SetImportEntries(thread_, undefinedValue); obj->SetLocalExportEntries(thread_, undefinedValue); obj->SetIndirectExportEntries(thread_, undefinedValue); obj->SetStarExportEntries(thread_, undefinedValue); obj->SetNameDictionary(thread_, undefinedValue); // [[CycleRoot]]: For a module not in a cycle, this would be the module itself. obj->SetCycleRoot(thread_, obj); obj->SetTopLevelCapability(thread_, undefinedValue); obj->SetAsyncParentModules(thread_, undefinedValue); obj->SetHasTLA(false); obj->SetAsyncEvaluatingOrdinal(SourceTextModule::NOT_ASYNC_EVALUATED); obj->SetPendingAsyncDependencies(SourceTextModule::UNDEFINED_INDEX); obj->SetDFSIndex(SourceTextModule::UNDEFINED_INDEX); obj->SetDFSAncestorIndex(SourceTextModule::UNDEFINED_INDEX); obj->SetEvaluationError(SourceTextModule::UNDEFINED_INDEX); obj->SetStatus(ModuleStatus::UNINSTANTIATED); obj->SetTypes(ModuleTypes::UNKNOWN); obj->SetIsNewBcVersion(false); obj->SetRegisterCounts(UINT16_MAX); obj->SetLazyImportStatus(ToUintPtr(nullptr)); obj->SetEcmaModuleFilename(ToUintPtr(nullptr)); obj->SetEcmaModuleRecordName(ToUintPtr(nullptr)); obj->SetSharedType(SharedTypes::UNSENDABLE_MODULE); obj->SetSendableEnv(thread_, undefinedValue); return obj; } JSHandle ObjectFactory::NewSModuleNamespace() { NewObjectHook(); JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetSharedModuleNamespaceClass()); JSHandle obj = NewSharedOldSpaceJSObject(hclass); JSHandle moduleNamespace = JSHandle::Cast(obj); moduleNamespace->SetModule(thread_, JSTaggedValue::Undefined()); moduleNamespace->SetExports(thread_, JSTaggedValue::Undefined()); moduleNamespace->SetDeregisterProcession(thread_, JSTaggedValue::Undefined()); return moduleNamespace; } JSHandle ObjectFactory::NewSImportEntry(const JSHandle &moduleRequest, const JSHandle &importName, const JSHandle &localName) { NewObjectHook(); TaggedObject *header = sHeap_->AllocateOldOrHugeObject(thread_, JSHClass::Cast(thread_->GlobalConstants()->GetImportEntryClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetModuleRequest(thread_, moduleRequest); obj->SetImportName(thread_, importName); obj->SetLocalName(thread_, localName); return obj; } JSHandle ObjectFactory::NewSLocalExportEntry(const JSHandle &exportName, const JSHandle &localName, const uint32_t index) { NewObjectHook(); TaggedObject *header = sHeap_->AllocateOldOrHugeObject(thread_, JSHClass::Cast(thread_->GlobalConstants()->GetLocalExportEntryClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetExportName(thread_, exportName); obj->SetLocalName(thread_, localName); obj->SetLocalIndex(index); return obj; } JSHandle ObjectFactory::NewSIndirectExportEntry(const JSHandle &exportName, const JSHandle &moduleRequest, const JSHandle &importName) { NewObjectHook(); TaggedObject *header = sHeap_->AllocateOldOrHugeObject(thread_, JSHClass::Cast(thread_->GlobalConstants()->GetIndirectExportEntryClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetExportName(thread_, exportName); obj->SetModuleRequest(thread_, moduleRequest); obj->SetImportName(thread_, importName); return obj; } JSHandle ObjectFactory::NewSStarExportEntry(const JSHandle &moduleRequest) { NewObjectHook(); TaggedObject *header = sHeap_->AllocateOldOrHugeObject(thread_, JSHClass::Cast(thread_->GlobalConstants()->GetStarExportEntryClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetModuleRequest(thread_, moduleRequest); return obj; } JSHandle ObjectFactory::NewSResolvedIndexBindingRecord() { JSHandle undefinedValue = thread_->GlobalConstants()->GetHandledUndefined(); JSHandle ecmaModule(undefinedValue); int32_t index = 0; return NewSResolvedIndexBindingRecord(ecmaModule, index); } JSHandle ObjectFactory::NewSResolvedIndexBindingRecord(const JSHandle &module, int32_t index) { NewObjectHook(); TaggedObject *header = sHeap_->AllocateOldOrHugeObject(thread_, JSHClass::Cast(thread_->GlobalConstants()->GetResolvedIndexBindingClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetModule(thread_, module); obj->SetIndex(index); return obj; } JSHandle ObjectFactory::NewSResolvedBindingRecord() { JSHandle undefinedValue = thread_->GlobalConstants()->GetHandledUndefined(); JSHandle ecmaModule(undefinedValue); JSHandle bindingName(undefinedValue); return NewSResolvedBindingRecord(ecmaModule, bindingName); } JSHandle ObjectFactory::NewSResolvedBindingRecord(const JSHandle &module, const JSHandle &bindingName) { NewObjectHook(); TaggedObject *header = sHeap_->AllocateOldOrHugeObject(thread_, JSHClass::Cast(thread_->GlobalConstants()->GetResolvedBindingClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetModule(thread_, module); obj->SetBindingName(thread_, bindingName); return obj; } JSHandle ObjectFactory::NewSResolvedRecordIndexBindingRecord() { JSHandle undefinedValue = thread_->GlobalConstants()->GetHandledUndefined(); JSHandle ecmaModule(undefinedValue); JSHandle fileName(undefinedValue); int32_t index = 0; return NewSResolvedRecordIndexBindingRecord(ecmaModule, fileName, index); } JSHandle ObjectFactory::NewSResolvedRecordIndexBindingRecord( const JSHandle &moduleRecord, const JSHandle &abcFileName, int32_t index) { NewObjectHook(); TaggedObject *header = sHeap_->AllocateOldOrHugeObject(thread_, JSHClass::Cast(thread_->GlobalConstants()->GetResolvedRecordIndexBindingClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetModuleRecord(thread_, moduleRecord); obj->SetAbcFileName(thread_, abcFileName); obj->SetIndex(index); return obj; } JSHandle ObjectFactory::NewSResolvedRecordBindingRecord() { JSHandle undefinedValue = thread_->GlobalConstants()->GetHandledUndefined(); JSHandle ecmaModule(undefinedValue); JSHandle bindingName(undefinedValue); return NewSResolvedRecordBindingRecord(ecmaModule, bindingName); } JSHandle ObjectFactory::NewSResolvedRecordBindingRecord( const JSHandle &moduleRecord, const JSHandle &bindingName) { NewObjectHook(); TaggedObject *header = sHeap_->AllocateOldOrHugeObject(thread_, JSHClass::Cast(thread_->GlobalConstants()->GetResolvedRecordBindingClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetModuleRecord(thread_, moduleRecord); obj->SetBindingName(thread_, bindingName); return obj; } JSHandle ObjectFactory::NewSAOTLiteralInfo(uint32_t length, JSTaggedValue initVal) { NewObjectHook(); size_t size = AOTLiteralInfo::ComputeSize(length); auto header = sHeap_->AllocateOldOrHugeObject(thread_, JSHClass::Cast(sHeap_->GetGlobalConst()->GetAOTLiteralInfoClass().GetTaggedObject()), size); JSHandle aotLiteralInfo(thread_, header); aotLiteralInfo->InitializeWithSpecialValue(initVal, length); return aotLiteralInfo; } JSHandle ObjectFactory::NewSendableEnv(int numSlots) { NewObjectHook(); size_t size = SendableEnv::ComputeSize(numSlots); auto header = sHeap_->AllocateOldOrHugeObject(thread_, JSHClass::Cast(sHeap_->GetGlobalConst()->GetSendableEnvClass().GetTaggedObject()), size); JSHandle array(thread_, header); array->InitializeWithSpecialValue(JSTaggedValue::Hole(), numSlots + SendableEnv::SENDABLE_RESERVED_ENV_LENGTH); return array; } JSHandle ObjectFactory::NewJSSendableFunction(const JSHandle &methodHandle) { JSHandle env = vm_->GetGlobalEnv(); FunctionKind kind = methodHandle->GetFunctionKind(); JSHandle hclass; switch (kind) { case FunctionKind::ASYNC_FUNCTION: { hclass = JSHandle::Cast(env->GetSAsyncFunctionClass()); break; } case FunctionKind::BASE_CONSTRUCTOR: { hclass = JSHandle::Cast(env->GetSFunctionClassWithProto()); break; } default: LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); } JSHandle func = NewSFunctionByHClass(methodHandle, hclass); ASSERT_NO_ABRUPT_COMPLETION(thread_); return func; } } // namespace panda::ecmascript