/* * Copyright (c) 2021-2022 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/js_function_kind.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/mem/heap.h" #include "ecmascript/object_factory-inl.h" #include "ecmascript/accessor_data.h" #include "ecmascript/base/error_helper.h" #include "ecmascript/builtins/builtins.h" #include "ecmascript/builtins/builtins_async_from_sync_iterator.h" #include "ecmascript/builtins/builtins_errors.h" #include "ecmascript/compiler/aot_file/aot_file_manager.h" #include "ecmascript/compiler/builtins/builtins_call_signature.h" #include "ecmascript/ecma_macros.h" #include "ecmascript/ecma_string_table.h" #include "ecmascript/ecma_string.h" #include "ecmascript/ecma_string-inl.h" #include "ecmascript/ecma_vm.h" #include "ecmascript/element_accessor.h" #include "ecmascript/element_accessor-inl.h" #include "ecmascript/free_object.h" #include "ecmascript/global_env.h" #include "ecmascript/global_env_constants-inl.h" #include "ecmascript/global_env_constants.h" #include "ecmascript/ic/ic_handler.h" #include "ecmascript/ic/profile_type_info.h" #include "ecmascript/ic/property_box.h" #include "ecmascript/ic/proto_change_details.h" #include "ecmascript/interpreter/frame_handler.h" #include "ecmascript/jobs/micro_job_queue.h" #include "ecmascript/jobs/pending_job.h" #include "ecmascript/js_api/js_api_arraylist.h" #include "ecmascript/js_api/js_api_arraylist_iterator.h" #include "ecmascript/js_api/js_api_deque.h" #include "ecmascript/js_api/js_api_deque_iterator.h" #include "ecmascript/js_api/js_api_hashmap.h" #include "ecmascript/js_api/js_api_hashmap_iterator.h" #include "ecmascript/js_api/js_api_hashset.h" #include "ecmascript/js_api/js_api_hashset_iterator.h" #include "ecmascript/js_api/js_api_lightweightmap.h" #include "ecmascript/js_api/js_api_lightweightmap_iterator.h" #include "ecmascript/js_api/js_api_lightweightset.h" #include "ecmascript/js_api/js_api_lightweightset_iterator.h" #include "ecmascript/js_api/js_api_linked_list.h" #include "ecmascript/js_api/js_api_linked_list_iterator.h" #include "ecmascript/js_api/js_api_list.h" #include "ecmascript/js_api/js_api_list_iterator.h" #include "ecmascript/js_api/js_api_plain_array.h" #include "ecmascript/js_api/js_api_plain_array_iterator.h" #include "ecmascript/js_api/js_api_queue.h" #include "ecmascript/js_api/js_api_queue_iterator.h" #include "ecmascript/js_api/js_api_stack.h" #include "ecmascript/js_api/js_api_stack_iterator.h" #include "ecmascript/js_api/js_api_tree_map.h" #include "ecmascript/js_api/js_api_tree_map_iterator.h" #include "ecmascript/js_api/js_api_tree_set.h" #include "ecmascript/js_api/js_api_tree_set_iterator.h" #include "ecmascript/js_api/js_api_vector.h" #include "ecmascript/js_api/js_api_vector_iterator.h" #include "ecmascript/js_arguments.h" #include "ecmascript/js_array.h" #include "ecmascript/js_array_iterator.h" #include "ecmascript/js_arraybuffer.h" #include "ecmascript/js_async_from_sync_iterator.h" #include "ecmascript/js_async_function.h" #include "ecmascript/js_async_generator_object.h" #include "ecmascript/js_bigint.h" #include "ecmascript/js_dataview.h" #include "ecmascript/js_date.h" #include "ecmascript/js_finalization_registry.h" #include "ecmascript/js_for_in_iterator.h" #include "ecmascript/js_generator_object.h" #include "ecmascript/js_hclass-inl.h" #include "ecmascript/js_hclass.h" #include "ecmascript/js_iterator.h" #include "ecmascript/js_map.h" #include "ecmascript/js_map_iterator.h" #include "ecmascript/js_object-inl.h" #include "ecmascript/js_primitive_ref.h" #include "ecmascript/js_promise.h" #include "ecmascript/js_proxy.h" #include "ecmascript/js_realm.h" #include "ecmascript/js_regexp.h" #include "ecmascript/js_regexp_iterator.h" #include "ecmascript/js_set.h" #include "ecmascript/js_set_iterator.h" #include "ecmascript/js_string_iterator.h" #include "ecmascript/js_symbol.h" #include "ecmascript/js_tagged_value-inl.h" #include "ecmascript/js_thread.h" #include "ecmascript/js_typed_array.h" #include "ecmascript/js_weak_container.h" #include "ecmascript/js_weak_ref.h" #include "ecmascript/jspandafile/class_info_extractor.h" #include "ecmascript/jspandafile/class_literal.h" #include "ecmascript/jspandafile/js_pandafile.h" #include "ecmascript/jspandafile/program_object.h" #include "ecmascript/layout_info-inl.h" #include "ecmascript/linked_hash_table.h" #include "ecmascript/marker_cell.h" #include "ecmascript/mem/heap-inl.h" #include "ecmascript/mem/region.h" #include "ecmascript/mem/space.h" #include "ecmascript/module/js_module_namespace.h" #include "ecmascript/module/js_module_source_text.h" #include "ecmascript/module/js_shared_module.h" #include "ecmascript/object_factory.h" #include "ecmascript/record.h" #include "ecmascript/require/js_cjs_exports.h" #include "ecmascript/require/js_cjs_module.h" #include "ecmascript/require/js_cjs_require.h" #include "ecmascript/shared_mm/shared_mm.h" #include "ecmascript/shared_objects/js_shared_array.h" #include "ecmascript/shared_objects/js_sendable_arraybuffer.h" #include "ecmascript/shared_objects/js_shared_array_iterator.h" #include "ecmascript/shared_objects/js_shared_json_value.h" #include "ecmascript/shared_objects/js_shared_map.h" #include "ecmascript/shared_objects/js_shared_map_iterator.h" #include "ecmascript/shared_objects/js_shared_set.h" #include "ecmascript/shared_objects/js_shared_set_iterator.h" #include "ecmascript/shared_objects/js_shared_typed_array.h" #include "ecmascript/symbol_table.h" #include "ecmascript/tagged_hash_array.h" #include "ecmascript/tagged_list.h" #include "ecmascript/tagged_node.h" #include "ecmascript/tagged_tree.h" #include "ecmascript/template_map.h" #include "ecmascript/ts_types/ts_obj_layout_info.h" #include "ecmascript/ts_types/ts_type.h" #include "ecmascript/ts_types/ts_type_table.h" #include "ecmascript/vtable.h" #ifdef ARK_SUPPORT_INTL #include "ecmascript/js_collator.h" #include "ecmascript/js_date_time_format.h" #include "ecmascript/js_displaynames.h" #include "ecmascript/js_list_format.h" #include "ecmascript/js_number_format.h" #include "ecmascript/js_plural_rules.h" #include "ecmascript/js_relative_time_format.h" #include "ecmascript/js_segmenter.h" #include "ecmascript/js_segments.h" #include "ecmascript/js_segment_iterator.h" #endif namespace panda::ecmascript { using Error = builtins::BuiltinsError; using RangeError = builtins::BuiltinsRangeError; using ReferenceError = builtins::BuiltinsReferenceError; using TypeError = builtins::BuiltinsTypeError; using AggregateError = builtins::BuiltinsAggregateError; using URIError = builtins::BuiltinsURIError; using SyntaxError = builtins::BuiltinsSyntaxError; using EvalError = builtins::BuiltinsEvalError; using OOMError = builtins::BuiltinsOOMError; using ErrorType = base::ErrorType; using ErrorHelper = base::ErrorHelper; ObjectFactory::ObjectFactory(JSThread *thread, Heap *heap, SharedHeap *sHeap) : thread_(thread), vm_(thread->GetEcmaVM()), heap_(heap), sHeap_(sHeap) {} JSHandle ObjectFactory::NewMethodForNativeFunction(const void *func, FunctionKind kind, kungfu::BuiltinsStubCSigns::ID builtinId, MemSpaceType methodSpaceType) { uint32_t numArgs = 2; // function object and this auto method = NewSMethod(nullptr, methodSpaceType); 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::NewEcmaHClassClass(JSHClass *hclass, uint32_t size, JSType type) { NewObjectHook(); uint32_t classSize = JSHClass::SIZE; auto *newClass = static_cast(heap_->AllocateClassClass(hclass, classSize)); newClass->Initialize(thread_, size, type, 0); return JSHandle(thread_, newClass); } JSHandle ObjectFactory::InitClassClass() { JSHandle hClassHandle = NewEcmaHClassClass(nullptr, JSHClass::SIZE, JSType::HCLASS); JSHClass *hclass = reinterpret_cast(hClassHandle.GetTaggedValue().GetTaggedObject()); hclass->SetClass(thread_, hclass); return hClassHandle; } JSHandle ObjectFactory::NewEcmaHClass(JSHClass *hclass, uint32_t size, JSType type, uint32_t inlinedProps) { NewObjectHook(); uint32_t classSize = JSHClass::SIZE; auto *newClass = static_cast(heap_->AllocateNonMovableOrHugeObject(hclass, classSize)); newClass->Initialize(thread_, size, type, inlinedProps); return JSHandle(thread_, newClass); } JSHandle ObjectFactory::NewEcmaReadOnlyHClass(JSHClass *hclass, uint32_t size, JSType type, uint32_t inlinedProps) { NewObjectHook(); uint32_t classSize = JSHClass::SIZE; auto *newClass = static_cast(heap_->AllocateReadOnlyOrHugeObject(hclass, classSize)); newClass->Initialize(thread_, size, type, inlinedProps); return JSHandle(thread_, newClass); } JSHandle ObjectFactory::NewEcmaHClass(uint32_t size, JSType type, uint32_t inlinedProps) { return NewEcmaHClass(JSHClass::Cast(thread_->GlobalConstants()->GetHClassClass().GetTaggedObject()), size, type, inlinedProps); } void ObjectFactory::InitObjectFields(const TaggedObject *object) { auto *klass = object->GetClass(); auto objBodySize = klass->GetObjectSize() - TaggedObject::TaggedObjectSize(); ASSERT(objBodySize % JSTaggedValue::TaggedTypeSize() == 0); uint32_t numOfFields = objBodySize / JSTaggedValue::TaggedTypeSize(); size_t addr = reinterpret_cast(object) + TaggedObject::TaggedObjectSize(); for (uint32_t i = 0; i < numOfFields; i++) { auto *fieldAddr = reinterpret_cast(addr + i * JSTaggedValue::TaggedTypeSize()); *fieldAddr = JSTaggedValue::Undefined().GetRawData(); } } void ObjectFactory::NewJSArrayBufferData(const JSHandle &array, int32_t length) { if (length == 0) { return; } JSTaggedValue data = array->GetArrayBufferData(); size_t size = static_cast(length) * sizeof(uint8_t); if (!data.IsUndefined()) { auto *pointer = JSNativePointer::Cast(data.GetTaggedObject()); auto newData = vm_->GetNativeAreaAllocator()->AllocateBuffer(size); if (memset_s(newData, length, 0, length) != EOK) { LOG_FULL(FATAL) << "memset_s failed"; UNREACHABLE(); } pointer->ResetExternalPointer(newData); vm_->GetNativeAreaAllocator()->ModifyNativeSizeStats(pointer->GetBindingSize(), size, NativeFlag::ARRAY_BUFFER); return; } auto newData = vm_->GetNativeAreaAllocator()->AllocateBuffer(size); if (memset_s(newData, length, 0, length) != EOK) { LOG_FULL(FATAL) << "memset_s failed"; UNREACHABLE(); } JSHandle pointer = NewJSNativePointer(newData, NativeAreaAllocator::FreeBufferFunc, vm_->GetNativeAreaAllocator(), false, size, Concurrent::NO, NativeFlag::ARRAY_BUFFER); array->SetArrayBufferData(thread_, pointer); array->SetWithNativeAreaAllocator(true); vm_->GetNativeAreaAllocator()->IncreaseNativeSizeStats(length, NativeFlag::ARRAY_BUFFER); } void ObjectFactory::NewJSSendableArrayBufferData(const JSHandle &array, int32_t length) { if (length == 0) { return; } JSTaggedValue data = array->GetArrayBufferData(); size_t size = static_cast(length) * sizeof(uint8_t); NativeAreaAllocator *nativeAreaAllocator = sHeap_->GetNativeAreaAllocator(); if (!data.IsUndefined()) { auto *pointer = JSNativePointer::Cast(data.GetTaggedObject()); auto newData = nativeAreaAllocator->AllocateBuffer(size); if (memset_s(newData, length, 0, length) != EOK) { LOG_FULL(FATAL) << "memset_s failed"; UNREACHABLE(); } pointer->ResetExternalPointer(newData); nativeAreaAllocator->ModifyNativeSizeStats(pointer->GetBindingSize(), size, NativeFlag::ARRAY_BUFFER); return; } auto newData = nativeAreaAllocator->AllocateBuffer(size); if (memset_s(newData, length, 0, length) != EOK) { LOG_FULL(FATAL) << "memset_s failed"; UNREACHABLE(); } JSHandle pointer = NewSJSNativePointer(newData, NativeAreaAllocator::FreeBufferFunc, nativeAreaAllocator, false, size, NativeFlag::ARRAY_BUFFER); array->SetArrayBufferData(thread_, pointer); array->SetWithNativeAreaAllocator(true); nativeAreaAllocator->IncreaseNativeSizeStats(length, NativeFlag::ARRAY_BUFFER); } JSHandle ObjectFactory::NewJSSendableArrayBuffer(int32_t length) { JSHandle env = vm_->GetGlobalEnv(); JSHandle constructor(env->GetSBuiltininArrayBufferFunction()); JSHandle sendableArrayBuffer(NewJSObjectByConstructor(constructor)); sendableArrayBuffer->SetArrayBufferByteLength(length); if (length > 0) { NewJSSendableArrayBufferData(sendableArrayBuffer, length); sendableArrayBuffer->SetShared(true); } return sendableArrayBuffer; } void ObjectFactory::NewJSSharedArrayBufferData(const JSHandle &array, int32_t length) { if (length == 0) { return; } void *newData = nullptr; size_t size = JSSharedMemoryManager::GetInstance()->CreateOrLoad(&newData, length) ? static_cast(length) : 0U; if (memset_s(newData, length, 0, length) != EOK) { LOG_FULL(FATAL) << "memset_s failed"; UNREACHABLE(); } JSHandle pointer = NewJSNativePointer(newData, JSSharedMemoryManager::RemoveSharedMemory, JSSharedMemoryManager::GetInstance(), false, size); array->SetArrayBufferData(thread_, pointer); array->SetWithNativeAreaAllocator(false); } JSHandle ObjectFactory::NewJSArrayBuffer(int32_t length) { JSHandle env = vm_->GetGlobalEnv(); JSHandle constructor(env->GetArrayBufferFunction()); JSHandle arrayBuffer(NewJSObjectByConstructor(constructor)); arrayBuffer->SetArrayBufferByteLength(length); if (length > 0) { auto newData = vm_->GetNativeAreaAllocator()->AllocateBuffer(length); if (memset_s(newData, length, 0, length) != EOK) { LOG_FULL(FATAL) << "memset_s failed"; UNREACHABLE(); } JSHandle pointer = NewJSNativePointer(newData, NativeAreaAllocator::FreeBufferFunc, vm_->GetNativeAreaAllocator(), false, length, Concurrent::NO, NativeFlag::ARRAY_BUFFER); arrayBuffer->SetArrayBufferData(thread_, pointer.GetTaggedValue()); arrayBuffer->SetWithNativeAreaAllocator(true); vm_->GetNativeAreaAllocator()->IncreaseNativeSizeStats(length, NativeFlag::ARRAY_BUFFER); } return arrayBuffer; } JSHandle ObjectFactory::NewJSArrayBuffer(void *buffer, int32_t length, const DeleteEntryPoint &deleter, void *data, bool share) { JSHandle env = vm_->GetGlobalEnv(); JSHandle constructor(env->GetArrayBufferFunction()); JSHandle arrayBuffer(NewJSObjectByConstructor(constructor)); length = buffer == nullptr ? 0 : length; arrayBuffer->SetArrayBufferByteLength(length); if (length > 0) { JSHandle pointer = NewJSNativePointer(buffer, deleter, data, false, length); arrayBuffer->SetArrayBufferData(thread_, pointer.GetTaggedValue()); arrayBuffer->SetShared(share); arrayBuffer->SetWithNativeAreaAllocator(deleter == NativeAreaAllocator::FreeBufferFunc && data == vm_->GetNativeAreaAllocator()); } return arrayBuffer; } JSHandle ObjectFactory::NewJSDataView(JSHandle buffer, uint32_t offset, uint32_t length) { uint32_t arrayLength = buffer->GetArrayBufferByteLength(); if (arrayLength - offset < length) { THROW_TYPE_ERROR_AND_RETURN(thread_, "offset or length error", JSHandle(thread_, JSTaggedValue::Undefined())); } JSHandle env = vm_->GetGlobalEnv(); JSHandle constructor(env->GetDataViewFunction()); JSHandle arrayBuffer(NewJSObjectByConstructor(constructor)); arrayBuffer->SetDataView(thread_, JSTaggedValue::True()); arrayBuffer->SetViewedArrayBuffer(thread_, buffer.GetTaggedValue()); arrayBuffer->SetByteLength(length); arrayBuffer->SetByteOffset(offset); return arrayBuffer; } JSHandle ObjectFactory::NewJSSharedArrayBuffer(int32_t length) { JSHandle env = vm_->GetGlobalEnv(); JSHandle constructor(env->GetSharedArrayBufferFunction()); JSHandle sharedArrayBuffer(NewJSObjectByConstructor(constructor)); sharedArrayBuffer->SetArrayBufferByteLength(length); if (length > 0) { NewJSSharedArrayBufferData(sharedArrayBuffer, length); sharedArrayBuffer->SetShared(true); } return sharedArrayBuffer; } JSHandle ObjectFactory::NewJSSharedArrayBuffer(void *buffer, int32_t length) { JSHandle env = vm_->GetGlobalEnv(); JSHandle constructor(env->GetSharedArrayBufferFunction()); JSHandle sharedArrayBuffer(NewJSObjectByConstructor(constructor)); length = buffer == nullptr ? 0 : length; sharedArrayBuffer->SetArrayBufferByteLength(length); if (length > 0) { JSHandle pointer = NewJSNativePointer(buffer, JSSharedMemoryManager::RemoveSharedMemory, JSSharedMemoryManager::GetInstance(), false, length); sharedArrayBuffer->SetArrayBufferData(thread_, pointer); sharedArrayBuffer->SetShared(true); sharedArrayBuffer->SetWithNativeAreaAllocator(false); } return sharedArrayBuffer; } void ObjectFactory::NewJSRegExpByteCodeData(const JSHandle ®exp, void *buffer, size_t size) { if (buffer == nullptr) { return; } auto newBuffer = vm_->GetNativeAreaAllocator()->AllocateBuffer(size); if (memcpy_s(newBuffer, size, buffer, size) != EOK) { LOG_FULL(FATAL) << "memcpy_s failed"; UNREACHABLE(); } JSTaggedValue data = regexp->GetByteCodeBuffer(); if (!data.IsUndefined()) { JSNativePointer *native = JSNativePointer::Cast(data.GetTaggedObject()); native->ResetExternalPointer(newBuffer); return; } JSHandle pointer = NewJSNativePointer(newBuffer, NativeAreaAllocator::FreeBufferFunc, vm_->GetNativeAreaAllocator(), false, size, Concurrent::NO, NativeFlag::REGEXP_BTYECODE); regexp->SetByteCodeBuffer(thread_, pointer.GetTaggedValue()); regexp->SetLength(static_cast(size)); vm_->GetNativeAreaAllocator()->IncreaseNativeSizeStats(size, NativeFlag::REGEXP_BTYECODE); } JSHandle ObjectFactory::NewEcmaHClass(uint32_t size, JSType type, const JSHandle &prototype) { const int inlinedProps = JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS; return NewEcmaHClass(size, inlinedProps, type, prototype); } JSHandle ObjectFactory::NewEcmaHClass(uint32_t size, uint32_t inlinedProps, JSType type, const JSHandle &prototype) { NewObjectHook(); uint32_t classSize = JSHClass::SIZE; auto *newClass = static_cast(heap_->AllocateNonMovableOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetHClassClass().GetTaggedObject()), classSize)); newClass->Initialize(thread_, size, type, inlinedProps); JSHandle hclass(thread_, newClass); hclass->SetPrototype(thread_, prototype.GetTaggedValue()); return hclass; } JSHandle ObjectFactory::NewJSObject(const JSHandle &jshclass) { JSHandle obj(thread_, JSObject::Cast(NewObject(jshclass))); JSHandle emptyArray = EmptyArray(); obj->InitializeHash(); obj->SetElements(thread_, emptyArray, SKIP_BARRIER); obj->SetProperties(thread_, emptyArray, SKIP_BARRIER); return obj; } JSHandle ObjectFactory::CloneProperties(const JSHandle &old) { uint32_t newLength = old->GetLength(); if (newLength == 0) { return EmptyArray(); } NewObjectHook(); auto klass = old->GetClass(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength); auto header = heap_->AllocateYoungOrHugeObject(klass, size); JSHandle newArray(thread_, header); newArray->InitializeWithSpecialValue(JSTaggedValue::Hole(), newLength, old->GetExtraLength()); for (uint32_t i = 0; i < newLength; i++) { JSTaggedValue value = old->Get(i); newArray->Set(thread_, i, value); } return newArray; } JSHandle ObjectFactory::CloneObjectLiteral(JSHandle object) { NewObjectHook(); auto klass = JSHandle(thread_, object->GetClass()); JSHandle cloneObject = NewJSObject(klass); JSHandle elements(thread_, object->GetElements()); auto newElements = CloneProperties(elements); cloneObject->SetElements(thread_, newElements.GetTaggedValue()); JSHandle properties(thread_, object->GetProperties()); auto newProperties = CloneProperties(properties); cloneObject->SetProperties(thread_, newProperties.GetTaggedValue()); uint32_t length = std::min(klass->GetInlinedProperties(), klass->NumberOfProps()); for (uint32_t i = 0; i < length; i++) { cloneObject->SetPropertyInlinedPropsWithRep(thread_, i, object->GetPropertyInlinedProps(i)); } return cloneObject; } JSHandle ObjectFactory::CloneArrayLiteral(JSHandle object) { NewObjectHook(); auto klass = JSHandle(thread_, object->GetClass()); JSHandle cloneObject(NewJSObject(klass)); cloneObject->SetArrayLength(thread_, object->GetArrayLength()); cloneObject->SetTrackInfo(thread_, JSTaggedValue::Undefined()); JSHandle elements(thread_, object->GetElements()); static constexpr uint8_t MAX_READ_ONLY_ARRAY_LENGTH = 10; uint32_t elementsLength = elements->GetLength(); MemSpaceType type = elementsLength > MAX_READ_ONLY_ARRAY_LENGTH ? MemSpaceType::SEMI_SPACE : MemSpaceType::NON_MOVABLE; #if !defined ENABLE_COW_ARRAY type = MemSpaceType::SEMI_SPACE; #endif if (type == MemSpaceType::NON_MOVABLE && elements.GetTaggedValue().IsCOWArray()) { // share the same elements array in nonmovable space. cloneObject->SetElements(thread_, elements.GetTaggedValue()); } else { auto newElements = CopyArray(elements, elementsLength, elementsLength, JSTaggedValue::Hole(), type); cloneObject->SetElements(thread_, newElements.GetTaggedValue()); } if (type == MemSpaceType::NON_MOVABLE && !object->GetElements().IsCOWArray()) { ASSERT(!Region::ObjectAddressToRange(object->GetElements().GetTaggedObject())->InNonMovableSpace()); // Set the first shared elements into the old object. object->SetElements(thread_, cloneObject->GetElements()); } JSHandle properties(thread_, object->GetProperties()); uint32_t propertiesLength = properties->GetLength(); type = propertiesLength > MAX_READ_ONLY_ARRAY_LENGTH ? MemSpaceType::SEMI_SPACE : MemSpaceType::NON_MOVABLE; #if !defined ENABLE_COW_ARRAY type = MemSpaceType::SEMI_SPACE; #endif if (type == MemSpaceType::NON_MOVABLE && properties.GetTaggedValue().IsCOWArray()) { // share the same properties array in nonmovable space. cloneObject->SetProperties(thread_, properties.GetTaggedValue()); } else { auto newProperties = CopyArray(properties, propertiesLength, propertiesLength, JSTaggedValue::Hole(), type); cloneObject->SetProperties(thread_, newProperties.GetTaggedValue()); } if (type == MemSpaceType::NON_MOVABLE && !object->GetProperties().IsCOWArray()) { ASSERT(!Region::ObjectAddressToRange(object->GetProperties().GetTaggedObject())->InNonMovableSpace()); // Set the first shared properties into the old object. object->SetProperties(thread_, cloneObject->GetProperties()); } for (uint32_t i = 0; i < klass->GetInlinedProperties(); i++) { cloneObject->SetPropertyInlinedPropsWithRep(thread_, i, object->GetPropertyInlinedProps(i)); } return cloneObject; } JSHandle ObjectFactory::CloneProperties(const JSHandle &old, const JSHandle &env, const JSHandle &obj) { uint32_t newLength = old->GetLength(); if (newLength == 0) { return EmptyArray(); } NewObjectHook(); auto klass = old->GetClass(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength); auto header = heap_->AllocateYoungOrHugeObject(klass, size); JSHandle newArray(thread_, header); newArray->InitializeWithSpecialValue(JSTaggedValue::Hole(), newLength, old->GetExtraLength()); for (uint32_t i = 0; i < newLength; i++) { JSTaggedValue value = old->Get(i); if (!value.IsJSFunction()) { newArray->Set(thread_, i, value); } else { JSHandle valueHandle(thread_, value); JSHandle newFunc = CloneJSFunction(valueHandle); newFunc->SetLexicalEnv(thread_, env); newFunc->SetHomeObject(thread_, obj); newArray->Set(thread_, i, newFunc); } } return newArray; } JSHandle ObjectFactory::CloneObjectLiteral(JSHandle object, const JSHandle &env, bool canShareHClass) { NewObjectHook(); auto klass = JSHandle(thread_, object->GetClass()); if (!canShareHClass) { klass = JSHClass::Clone(thread_, klass); } JSHandle cloneObject = NewJSObject(klass); JSHandle elements(thread_, object->GetElements()); auto newElements = CloneProperties(elements, env, cloneObject); cloneObject->SetElements(thread_, newElements.GetTaggedValue()); JSHandle properties(thread_, object->GetProperties()); auto newProperties = CloneProperties(properties, env, cloneObject); cloneObject->SetProperties(thread_, newProperties.GetTaggedValue()); uint32_t length = std::min(klass->GetInlinedProperties(), klass->NumberOfProps()); for (uint32_t i = 0; i < length; i++) { auto layout = LayoutInfo::Cast(klass->GetLayout().GetTaggedObject()); JSTaggedValue value = object->GetPropertyInlinedProps(i); if (!layout->GetAttr(i).IsTaggedRep() || !value.IsJSFunction()) { cloneObject->SetPropertyInlinedPropsWithRep(thread_, i, value); } else { JSHandle valueHandle(thread_, value); JSHandle newFunc = CloneJSFunction(valueHandle); newFunc->SetLexicalEnv(thread_, env); newFunc->SetHomeObject(thread_, cloneObject); cloneObject->SetPropertyInlinedProps(thread_, i, newFunc.GetTaggedValue()); } } return cloneObject; } JSHandle ObjectFactory::CloneJSFunction(JSHandle func) { JSHandle jshclass(thread_, func->GetJSHClass()); JSHandle method(thread_, func->GetMethod()); JSHandle cloneFunc = NewJSFunctionByHClass(method, jshclass); JSTaggedValue length = func->GetPropertyInlinedProps(JSFunction::LENGTH_INLINE_PROPERTY_INDEX); cloneFunc->SetPropertyInlinedProps(thread_, JSFunction::LENGTH_INLINE_PROPERTY_INDEX, length); cloneFunc->SetLength(func->GetLength()); cloneFunc->SetModule(thread_, func->GetModule()); return cloneFunc; } JSHandle ObjectFactory::CloneSFunction(JSHandle func) { ASSERT(func.GetTaggedValue().IsJSSharedFunction()); JSHandle jshclass(thread_, func->GetJSHClass()); JSHandle method(thread_, func->GetMethod()); JSHandle cloneFunc = NewSFunctionByHClass(method, jshclass); JSTaggedValue length = func->GetPropertyInlinedProps(JSFunction::LENGTH_INLINE_PROPERTY_INDEX); cloneFunc->SetPropertyInlinedProps(thread_, JSFunction::LENGTH_INLINE_PROPERTY_INDEX, length); cloneFunc->SetLength(func->GetLength()); cloneFunc->SetModule(thread_, func->GetModule()); return cloneFunc; } JSHandle ObjectFactory::CloneClassCtor(JSHandle ctor, const JSHandle &lexenv, bool canShareHClass) { NewObjectHook(); JSHandle hclass(thread_, ctor->GetClass()); if (!canShareHClass) { hclass = JSHClass::Clone(thread_, hclass); } JSHandle method(thread_, ctor->GetMethod()); ASSERT_PRINT(method->GetFunctionKind() == FunctionKind::CLASS_CONSTRUCTOR || method->GetFunctionKind() == FunctionKind::DERIVED_CONSTRUCTOR, "cloned function is not class"); JSHandle cloneCtor = NewJSFunctionByHClass(method, hclass); uint32_t length = std::min(hclass->GetInlinedProperties(), hclass->NumberOfProps()); for (uint32_t i = 0; i < length; i++) { auto layout = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject()); JSTaggedValue value = ctor->GetPropertyInlinedProps(i); if (!layout->GetAttr(i).IsTaggedRep() || !value.IsJSFunction()) { cloneCtor->SetPropertyInlinedPropsWithRep(thread_, i, value); } else { JSHandle valueHandle(thread_, value); JSHandle newFunc = CloneJSFunction(valueHandle); newFunc->SetLexicalEnv(thread_, lexenv); newFunc->SetHomeObject(thread_, cloneCtor); cloneCtor->SetPropertyInlinedProps(thread_, i, newFunc.GetTaggedValue()); } } JSHandle elements(thread_, ctor->GetElements()); auto newElements = CloneProperties(elements, lexenv, JSHandle(cloneCtor)); cloneCtor->SetElements(thread_, newElements.GetTaggedValue()); JSHandle properties(thread_, ctor->GetProperties()); auto newProperties = CloneProperties(properties, lexenv, JSHandle(cloneCtor)); cloneCtor->SetProperties(thread_, newProperties.GetTaggedValue()); return cloneCtor; } JSHandle ObjectFactory::NewNonMovableJSObject(const JSHandle &jshclass) { JSHandle obj(thread_, JSObject::Cast(NewNonMovableObject(jshclass, jshclass->GetInlinedProperties()))); obj->InitializeHash(); obj->SetElements(thread_, EmptyArray(), SKIP_BARRIER); obj->SetProperties(thread_, EmptyArray(), SKIP_BARRIER); return obj; } JSHandle ObjectFactory::NewJSPrimitiveRef(const JSHandle &hclass, const JSHandle &object) { JSHandle obj = JSHandle::Cast(NewJSObject(hclass)); obj->SetValue(thread_, object); return obj; } JSHandle ObjectFactory::NewJSArray() { JSHandle env = vm_->GetGlobalEnv(); JSHandle function(env->GetArrayFunction()); return JSHandle(NewJSObjectByConstructor(function)); } JSHandle ObjectFactory::NewJSArray(size_t length, JSHandle &hclass) { JSHandle obj = NewJSObject(hclass); JSArray::Cast(*obj)->SetLength(length); JSArray::Cast(*obj)->SetTrackInfo(thread_, JSTaggedValue::Undefined()); auto accessor = thread_->GlobalConstants()->GetArrayLengthAccessor(); JSArray::Cast(*obj)->SetPropertyInlinedProps(thread_, JSArray::LENGTH_INLINE_PROPERTY_INDEX, accessor); return JSHandle(obj); } JSHandle ObjectFactory::NewJsonFixedArray(size_t start, size_t length, const std::vector> &vec) { if (length == 0) { return EmptyArray(); } MemSpaceType spaceType = length < LENGTH_THRESHOLD ? MemSpaceType::SEMI_SPACE : MemSpaceType::OLD_SPACE; JSHandle array = NewTaggedArrayWithoutInit(length, spaceType); array->SetExtraLength(0); for (size_t i = 0; i < length; i++) { array->Set(thread_, i, vec[start + i]); } return array; } JSHandle ObjectFactory::NewJSForinIterator(const JSHandle &obj, const JSHandle keys, const JSHandle cachedHclass) { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass(env->GetForinIteratorClass()); JSHandle it = JSHandle::Cast(NewJSObject(hclass)); it->SetObject(thread_, obj); it->SetCachedHclass(thread_, cachedHclass); it->SetKeys(thread_, keys); it->SetIndex(EnumCache::ENUM_CACHE_HEADER_SIZE); uint32_t enumLength = JSHandle::Cast(keys)->GetLength(); it->SetLength(enumLength); return it; } JSHandle ObjectFactory::CreateJSRegExpInstanceClass(JSHandle proto) { const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle regexpClass = NewEcmaHClass(JSRegExp::SIZE, JSType::JS_REG_EXP, proto); uint32_t fieldOrder = 0; JSHandle layoutInfoHandle = CreateLayoutInfo(1); { PropertyAttributes attributes = PropertyAttributes::Default(true, false, false); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(fieldOrder++); layoutInfoHandle->AddKey(thread_, 0, globalConst->GetLastIndexString(), attributes); } { regexpClass->SetLayout(thread_, layoutInfoHandle); regexpClass->SetNumberOfProps(fieldOrder); } return regexpClass; } JSHandle ObjectFactory::CreateJSArrayInstanceClass(JSHandle proto, uint32_t inlinedProps) { const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle arrayClass = NewEcmaHClass(JSArray::SIZE, inlinedProps, JSType::JS_ARRAY, proto); uint32_t fieldOrder = 0; ASSERT(JSArray::LENGTH_INLINE_PROPERTY_INDEX == fieldOrder); JSHandle layoutInfoHandle = CreateLayoutInfo(1); { PropertyAttributes attributes = PropertyAttributes::DefaultAccessor(true, false, false); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(fieldOrder++); layoutInfoHandle->AddKey(thread_, 0, globalConst->GetLengthString(), attributes); } { arrayClass->SetLayout(thread_, layoutInfoHandle); arrayClass->SetNumberOfProps(fieldOrder); } arrayClass->SetIsStableElements(true); arrayClass->SetHasConstructor(false); return arrayClass; } JSHandle ObjectFactory::CreateJSArguments(const JSHandle &env) { const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle proto = env->GetObjectFunctionPrototype(); JSHandle argumentsClass = NewEcmaHClass(JSArguments::SIZE, JSType::JS_ARGUMENTS, proto); uint32_t fieldOrder = 0; ASSERT(JSArguments::LENGTH_INLINE_PROPERTY_INDEX == fieldOrder); JSHandle layoutInfoHandle = CreateLayoutInfo(JSArguments::LENGTH_OF_INLINE_PROPERTIES); { PropertyAttributes attributes = PropertyAttributes::Default(true, false, true); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(fieldOrder++); layoutInfoHandle->AddKey(thread_, JSArguments::LENGTH_INLINE_PROPERTY_INDEX, globalConst->GetLengthString(), attributes); } ASSERT(JSArguments::ITERATOR_INLINE_PROPERTY_INDEX == fieldOrder); { PropertyAttributes attributes = PropertyAttributes::Default(true, false, true); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(fieldOrder++); layoutInfoHandle->AddKey(thread_, JSArguments::ITERATOR_INLINE_PROPERTY_INDEX, env->GetIteratorSymbol().GetTaggedValue(), attributes); } { ASSERT(JSArguments::CALLER_INLINE_PROPERTY_INDEX == fieldOrder); PropertyAttributes attributes = PropertyAttributes::Default(false, false, false); attributes.SetIsInlinedProps(true); attributes.SetIsAccessor(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(fieldOrder++); layoutInfoHandle->AddKey(thread_, JSArguments::CALLER_INLINE_PROPERTY_INDEX, thread_->GlobalConstants()->GetHandledCallerString().GetTaggedValue(), attributes); } { ASSERT(JSArguments::CALLEE_INLINE_PROPERTY_INDEX == fieldOrder); PropertyAttributes attributes = PropertyAttributes::Default(false, false, false); attributes.SetIsInlinedProps(true); attributes.SetIsAccessor(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(fieldOrder++); layoutInfoHandle->AddKey(thread_, JSArguments::CALLEE_INLINE_PROPERTY_INDEX, thread_->GlobalConstants()->GetHandledCalleeString().GetTaggedValue(), attributes); } { argumentsClass->SetLayout(thread_, layoutInfoHandle); argumentsClass->SetNumberOfProps(fieldOrder); } argumentsClass->SetIsStableElements(true); return argumentsClass; } JSHandle ObjectFactory::NewJSArguments() { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetArgumentsClass()); JSHandle obj = JSHandle::Cast(NewJSObject(hclass)); return obj; } JSHandle ObjectFactory::GetJSError(const ErrorType &errorType, const char *data, bool needCheckStack) { ASSERT_PRINT(errorType == ErrorType::ERROR || errorType == ErrorType::EVAL_ERROR || errorType == ErrorType::RANGE_ERROR || errorType == ErrorType::REFERENCE_ERROR || errorType == ErrorType::SYNTAX_ERROR || errorType == ErrorType::TYPE_ERROR || errorType == ErrorType::URI_ERROR || errorType == ErrorType::OOM_ERROR || errorType == ErrorType::TERMINATION_ERROR, "The error type is not in the valid range."); if (data != nullptr) { JSHandle handleMsg = NewFromUtf8(data); return NewJSError(errorType, handleMsg, needCheckStack); } JSHandle emptyString(thread_->GlobalConstants()->GetHandledEmptyString()); return NewJSError(errorType, emptyString, needCheckStack); } JSHandle ObjectFactory::NewJSError(const ErrorType &errorType, const JSHandle &message, bool needCheckStack) { // if there have exception in thread, then return current exception, no need to new js error. if (thread_->HasPendingException()) { JSHandle obj(thread_, thread_->GetException()); return obj; } // current frame may be entry frame, exception happened in JSFunction::Call and JSFunction::Construct, // in this case sp = the prev frame (interpreter frame). if (!thread_->IsAsmInterpreter()) { FrameHandler frameHandler(thread_); if (frameHandler.IsInterpretedEntryFrame()) { thread_->SetCurrentSPFrame(frameHandler.GetPrevJSFrame()); } } JSHandle env = vm_->GetGlobalEnv(); JSHandle nativeConstructor; switch (errorType) { case ErrorType::RANGE_ERROR: nativeConstructor = env->GetRangeErrorFunction(); break; case ErrorType::EVAL_ERROR: nativeConstructor = env->GetEvalErrorFunction(); break; case ErrorType::REFERENCE_ERROR: nativeConstructor = env->GetReferenceErrorFunction(); break; case ErrorType::TYPE_ERROR: nativeConstructor = env->GetTypeErrorFunction(); break; case ErrorType::URI_ERROR: nativeConstructor = env->GetURIErrorFunction(); break; case ErrorType::SYNTAX_ERROR: nativeConstructor = env->GetSyntaxErrorFunction(); break; case ErrorType::OOM_ERROR: nativeConstructor = env->GetOOMErrorFunction(); break; case ErrorType::TERMINATION_ERROR: nativeConstructor = env->GetTerminationErrorFunction(); break; default: nativeConstructor = env->GetErrorFunction(); break; } JSHandle nativeFunc = JSHandle::Cast(nativeConstructor); JSHandle nativePrototype(thread_, nativeFunc->GetFunctionPrototype()); JSHandle undefined = thread_->GlobalConstants()->GetHandledUndefined(); EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread_, nativeConstructor, nativePrototype, undefined, 1, needCheckStack); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSObject, thread_); info->SetCallArg(message.GetTaggedValue()); Method *method = JSHandle::Cast(nativeConstructor)->GetCallTarget(); JSTaggedValue obj = reinterpret_cast(const_cast(method->GetNativePointer()))(info); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSObject, thread_); JSHandle handleNativeInstanceObj(thread_, obj); auto sp = const_cast(thread_->GetCurrentSPFrame()); ASSERT(FrameHandler::GetFrameType(sp) == FrameType::INTERPRETER_ENTRY_FRAME); auto prevEntry = InterpretedEntryFrame::GetFrameFromSp(sp)->GetPrevFrameFp(); thread_->SetCurrentSPFrame(prevEntry); return handleNativeInstanceObj; } JSHandle ObjectFactory::NewJSAggregateError() { JSHandle env = vm_->GetGlobalEnv(); JSHandle constructor(env->GetAggregateErrorFunction()); return NewJSObjectByConstructor(constructor); } JSHandle ObjectFactory::NewJSObjectByConstructor(const JSHandle &constructor, uint32_t inlinedProps) { JSHandle env = vm_->GetGlobalEnv(); if (!constructor->HasFunctionPrototype() || (constructor->GetProtoOrHClass().IsHeapObject() && constructor->GetFunctionPrototype().IsECMAObject())) { JSHandle jshclass; if (LIKELY(inlinedProps == JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS)) { jshclass = JSHandle(thread_, JSFunction::GetOrCreateInitialJSHClass(thread_, constructor)); } else { jshclass = NewEcmaHClass(JSObject::SIZE, inlinedProps, JSType::JS_OBJECT, env->GetObjectFunctionPrototype()); } JSHandle obj; if (jshclass->IsJSShared()) { obj = NewSharedOldSpaceJSObject(jshclass); if (jshclass->IsDictionaryMode()) { auto fieldLayout = jshclass->GetLayout(); ASSERT(fieldLayout.IsDictionary()); auto dict = JSHandle(thread_, fieldLayout); auto properties = NewAndCopySNameDictionary(dict, dict->GetLength()); obj->SetProperties(thread_, properties); } InitializeJSObject(obj, jshclass); } else { obj = NewJSObjectWithInit(jshclass); } return obj; } JSHandle result = NewJSObjectByConstructor(JSHandle(env->GetObjectFunction()), JSHandle(constructor)); if (thread_->HasPendingException()) { LOG_FULL(FATAL) << "NewJSObjectByConstructor should not throw Exception! "; } return result; } JSHandle ObjectFactory::NewJSObjectByConstructor(const JSHandle &constructor, const JSHandle &newTarget) { JSHandle jshclass; if (!constructor->HasFunctionPrototype() || (constructor->GetProtoOrHClass().IsHeapObject() && constructor->GetFunctionPrototype().IsECMAObject())) { jshclass = JSFunction::GetInstanceJSHClass(thread_, constructor, newTarget); } else { JSHandle env = vm_->GetGlobalEnv(); jshclass = JSFunction::GetInstanceJSHClass(thread_, JSHandle(env->GetObjectFunction()), newTarget); } // Check this exception elsewhere RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSObject, thread_); JSHandle obj; if (jshclass->IsJSShared()) { obj = NewSharedOldSpaceJSObject(jshclass); if (jshclass->IsDictionaryMode()) { auto fieldLayout = jshclass->GetLayout(); ASSERT(fieldLayout.IsDictionary()); auto dict = JSHandle(thread_, fieldLayout); auto properties = NewAndCopySNameDictionary(dict, dict->GetLength()); obj->SetProperties(thread_, properties); } InitializeJSObject(obj, jshclass); } else { obj = NewJSObjectWithInit(jshclass); } return obj; } JSHandle ObjectFactory::NewJSObjectWithInit(const JSHandle &jshclass) { JSHandle obj = NewJSObject(jshclass); InitializeJSObject(obj, jshclass); return obj; } void ObjectFactory::InitializeJSObject(const JSHandle &obj, const JSHandle &jshclass) { JSType type = jshclass->GetObjectType(); switch (type) { case JSType::JS_OBJECT: case JSType::JS_ERROR: case JSType::JS_EVAL_ERROR: case JSType::JS_RANGE_ERROR: case JSType::JS_REFERENCE_ERROR: case JSType::JS_TYPE_ERROR: case JSType::JS_AGGREGATE_ERROR: case JSType::JS_URI_ERROR: case JSType::JS_SYNTAX_ERROR: case JSType::JS_OOM_ERROR: case JSType::JS_TERMINATION_ERROR: case JSType::JS_ASYNCITERATOR: case JSType::JS_SHARED_OBJECT: case JSType::JS_SHARED_FUNCTION: case JSType::JS_ITERATOR: { break; } case JSType::JS_SHARED_JSON_OBJECT: case JSType::JS_SHARED_JSON_NULL: case JSType::JS_SHARED_JSON_TRUE: case JSType::JS_SHARED_JSON_FALSE: case JSType::JS_SHARED_JSON_NUMBER: case JSType::JS_SHARED_JSON_STRING: case JSType::JS_SHARED_JSON_ARRAY: { JSSharedJSONValue::Cast(*obj)->SetValue(thread_, JSTaggedValue::Null()); break; } #ifdef ARK_SUPPORT_INTL case JSType::JS_INTL: { JSIntl::Cast(*obj)->SetFallbackSymbol(thread_, JSTaggedValue::Undefined()); JSHandle jsSymbol = NewPublicSymbolWithChar("IntlLegacyConstructedSymbol"); JSIntl::Cast(*obj)->SetFallbackSymbol(thread_, jsSymbol); break; } case JSType::JS_LOCALE: { JSLocale::Cast(*obj)->SetIcuField(thread_, JSTaggedValue::Undefined()); break; } case JSType::JS_DATE_TIME_FORMAT: { JSDateTimeFormat::Cast(*obj)->SetLocale(thread_, JSTaggedValue::Undefined()); JSDateTimeFormat::Cast(*obj)->SetCalendar(thread_, JSTaggedValue::Undefined()); JSDateTimeFormat::Cast(*obj)->SetNumberingSystem(thread_, JSTaggedValue::Undefined()); JSDateTimeFormat::Cast(*obj)->SetTimeZone(thread_, JSTaggedValue::Undefined()); JSDateTimeFormat::Cast(*obj)->SetLocaleIcu(thread_, JSTaggedValue::Undefined()); JSDateTimeFormat::Cast(*obj)->SetSimpleDateTimeFormatIcu(thread_, JSTaggedValue::Undefined()); JSDateTimeFormat::Cast(*obj)->SetIso8601(thread_, JSTaggedValue::Undefined()); JSDateTimeFormat::Cast(*obj)->SetBoundFormat(thread_, JSTaggedValue::Undefined()); JSDateTimeFormat::Cast(*obj)->SetHourCycle(HourCycleOption::EXCEPTION); JSDateTimeFormat::Cast(*obj)->SetDateStyle(DateTimeStyleOption::EXCEPTION); JSDateTimeFormat::Cast(*obj)->SetTimeStyle(DateTimeStyleOption::EXCEPTION); break; } case JSType::JS_NUMBER_FORMAT: { JSNumberFormat::Cast(*obj)->SetLocale(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetNumberingSystem(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetCurrency(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetUnit(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetMinimumIntegerDigits(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetMinimumFractionDigits(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetMaximumFractionDigits(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetMinimumSignificantDigits(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetMaximumSignificantDigits(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetUseGrouping(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetBoundFormat(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetIcuField(thread_, JSTaggedValue::Undefined()); JSNumberFormat::Cast(*obj)->SetStyle(StyleOption::EXCEPTION); JSNumberFormat::Cast(*obj)->SetCurrencySign(CurrencySignOption::EXCEPTION); JSNumberFormat::Cast(*obj)->SetCurrencyDisplay(CurrencyDisplayOption::EXCEPTION); JSNumberFormat::Cast(*obj)->SetUnitDisplay(UnitDisplayOption::EXCEPTION); JSNumberFormat::Cast(*obj)->SetSignDisplay(SignDisplayOption::EXCEPTION); JSNumberFormat::Cast(*obj)->SetCompactDisplay(CompactDisplayOption::EXCEPTION); JSNumberFormat::Cast(*obj)->SetNotation(NotationOption::EXCEPTION); JSNumberFormat::Cast(*obj)->SetRoundingType(RoundingType::EXCEPTION); break; } case JSType::JS_RELATIVE_TIME_FORMAT: { JSRelativeTimeFormat::Cast(*obj)->SetLocale(thread_, JSTaggedValue::Undefined()); JSRelativeTimeFormat::Cast(*obj)->SetNumberingSystem(thread_, JSTaggedValue::Undefined()); JSRelativeTimeFormat::Cast(*obj)->SetIcuField(thread_, JSTaggedValue::Undefined()); JSRelativeTimeFormat::Cast(*obj)->SetStyle(RelativeStyleOption::EXCEPTION); JSRelativeTimeFormat::Cast(*obj)->SetNumeric(NumericOption::EXCEPTION); break; } case JSType::JS_COLLATOR: { JSCollator::Cast(*obj)->SetIcuField(thread_, JSTaggedValue::Undefined()); JSCollator::Cast(*obj)->SetLocale(thread_, JSTaggedValue::Undefined()); JSCollator::Cast(*obj)->SetCollation(thread_, JSTaggedValue::Undefined()); JSCollator::Cast(*obj)->SetBoundCompare(thread_, JSTaggedValue::Undefined()); JSCollator::Cast(*obj)->SetUsage(UsageOption::EXCEPTION); JSCollator::Cast(*obj)->SetCaseFirst(CaseFirstOption::EXCEPTION); JSCollator::Cast(*obj)->SetSensitivity(SensitivityOption::EXCEPTION); JSCollator::Cast(*obj)->SetIgnorePunctuation(false); JSCollator::Cast(*obj)->SetNumeric(false); break; } case JSType::JS_PLURAL_RULES: { JSPluralRules::Cast(*obj)->SetLocale(thread_, JSTaggedValue::Undefined()); JSPluralRules::Cast(*obj)->SetMinimumIntegerDigits(thread_, JSTaggedValue::Undefined()); JSPluralRules::Cast(*obj)->SetMinimumFractionDigits(thread_, JSTaggedValue::Undefined()); JSPluralRules::Cast(*obj)->SetMaximumFractionDigits(thread_, JSTaggedValue::Undefined()); JSPluralRules::Cast(*obj)->SetMinimumSignificantDigits(thread_, JSTaggedValue::Undefined()); JSPluralRules::Cast(*obj)->SetMaximumSignificantDigits(thread_, JSTaggedValue::Undefined()); JSPluralRules::Cast(*obj)->SetIcuPR(thread_, JSTaggedValue::Undefined()); JSPluralRules::Cast(*obj)->SetIcuNF(thread_, JSTaggedValue::Undefined()); JSPluralRules::Cast(*obj)->SetRoundingType(RoundingType::EXCEPTION); JSPluralRules::Cast(*obj)->SetType(TypeOption::EXCEPTION); break; } case JSType::JS_DISPLAYNAMES: { JSDisplayNames::Cast(*obj)->SetLocale(thread_, JSTaggedValue::Undefined()); JSDisplayNames::Cast(*obj)->SetType(TypednsOption::EXCEPTION); JSDisplayNames::Cast(*obj)->SetStyle(StyOption::EXCEPTION); JSDisplayNames::Cast(*obj)->SetFallback(FallbackOption::EXCEPTION); JSDisplayNames::Cast(*obj)->SetIcuLDN(thread_, JSTaggedValue::Undefined()); break; } case JSType::JS_SEGMENTER: { JSSegmenter::Cast(*obj)->SetLocale(thread_, JSTaggedValue::Undefined()); JSSegmenter::Cast(*obj)->SetGranularity(GranularityOption::EXCEPTION); JSSegmenter::Cast(*obj)->SetIcuField(thread_, JSTaggedValue::Undefined()); break; } case JSType::JS_SEGMENTS: { JSSegments::Cast(*obj)->SetIcuField(thread_, JSTaggedValue::Undefined()); JSSegments::Cast(*obj)->SetSegmentsString(thread_, JSTaggedValue::Undefined()); JSSegments::Cast(*obj)->SetUnicodeString(thread_, JSTaggedValue::Undefined()); JSSegments::Cast(*obj)->SetGranularity(GranularityOption::EXCEPTION); break; } case JSType::JS_SEGMENT_ITERATOR: { JSSegmentIterator::Cast(*obj)->SetIcuField(thread_, JSTaggedValue::Undefined()); JSSegmentIterator::Cast(*obj)->SetIteratedString(thread_, JSTaggedValue::Undefined()); JSSegmentIterator::Cast(*obj)->SetUnicodeString(thread_, JSTaggedValue::Undefined()); JSSegmentIterator::Cast(*obj)->SetGranularity(GranularityOption::EXCEPTION); break; } case JSType::JS_LIST_FORMAT: { JSListFormat::Cast(*obj)->SetLocale(thread_, JSTaggedValue::Undefined()); JSListFormat::Cast(*obj)->SetType(ListTypeOption::EXCEPTION); JSListFormat::Cast(*obj)->SetStyle(ListStyleOption::EXCEPTION); JSListFormat::Cast(*obj)->SetIcuLF(thread_, JSTaggedValue::Undefined()); break; } #else case JSType::JS_INTL: case JSType::JS_LOCALE: case JSType::JS_DATE_TIME_FORMAT: case JSType::JS_NUMBER_FORMAT: case JSType::JS_RELATIVE_TIME_FORMAT: case JSType::JS_COLLATOR: case JSType::JS_PLURAL_RULES: case JSType::JS_DISPLAYNAMES: case JSType::JS_SEGMENTER: case JSType::JS_SEGMENTS: case JSType::JS_SEGMENT_ITERATOR: case JSType::JS_LIST_FORMAT: { break; } #endif case JSType::JS_ARRAY: { JSArray::Cast(*obj)->SetLength(0); JSArray::Cast(*obj)->SetTrackInfo(thread_, JSTaggedValue::Undefined()); ASSERT(!obj->GetJSHClass()->IsDictionaryMode()); auto accessor = thread_->GlobalConstants()->GetArrayLengthAccessor(); JSArray::Cast(*obj)->SetPropertyInlinedProps(thread_, JSArray::LENGTH_INLINE_PROPERTY_INDEX, accessor); break; } case JSType::JS_SHARED_ARRAY: { JSSharedArray::Cast(*obj)->SetLength(0); JSSharedArray::Cast(*obj)->SetTrackInfo(thread_, JSTaggedValue::Undefined()); ASSERT(!obj->GetJSHClass()->IsDictionaryMode()); JSSharedArray::Cast(*obj)->SetModRecord(0); auto accessor = thread_->GlobalConstants()->GetSharedArrayLengthAccessor(); JSSharedArray::Cast(*obj)->SetPropertyInlinedProps(thread_, JSArray::LENGTH_INLINE_PROPERTY_INDEX, accessor); break; } case JSType::JS_DATE: JSDate::Cast(*obj)->SetTimeValue(thread_, JSTaggedValue(0.0)); JSDate::Cast(*obj)->SetLocalOffset(thread_, JSTaggedValue(JSDate::MAX_DOUBLE)); break; case JSType::JS_TYPED_ARRAY: case JSType::JS_INT8_ARRAY: case JSType::JS_UINT8_ARRAY: case JSType::JS_UINT8_CLAMPED_ARRAY: case JSType::JS_INT16_ARRAY: case JSType::JS_UINT16_ARRAY: case JSType::JS_INT32_ARRAY: case JSType::JS_UINT32_ARRAY: case JSType::JS_FLOAT32_ARRAY: case JSType::JS_FLOAT64_ARRAY: case JSType::JS_BIGINT64_ARRAY: case JSType::JS_BIGUINT64_ARRAY: JSTypedArray::Cast(*obj)->SetViewedArrayBufferOrByteArray(thread_, JSTaggedValue::Undefined()); JSTypedArray::Cast(*obj)->SetTypedArrayName(thread_, JSTaggedValue::Undefined()); JSTypedArray::Cast(*obj)->SetByteLength(0); JSTypedArray::Cast(*obj)->SetByteOffset(0); JSTypedArray::Cast(*obj)->SetArrayLength(0); JSTypedArray::Cast(*obj)->SetContentType(ContentType::None); break; case JSType::JS_SHARED_TYPED_ARRAY: case JSType::JS_SHARED_INT8_ARRAY: case JSType::JS_SHARED_UINT8_ARRAY: case JSType::JS_SHARED_UINT8_CLAMPED_ARRAY: case JSType::JS_SHARED_INT16_ARRAY: case JSType::JS_SHARED_UINT16_ARRAY: case JSType::JS_SHARED_INT32_ARRAY: case JSType::JS_SHARED_UINT32_ARRAY: case JSType::JS_SHARED_FLOAT32_ARRAY: case JSType::JS_SHARED_FLOAT64_ARRAY: case JSType::JS_SHARED_BIGINT64_ARRAY: case JSType::JS_SHARED_BIGUINT64_ARRAY: JSSharedTypedArray::Cast(*obj)->SetViewedArrayBufferOrByteArray(thread_, JSTaggedValue::Undefined()); JSSharedTypedArray::Cast(*obj)->SetTypedArrayName(thread_, JSTaggedValue::Undefined()); JSSharedTypedArray::Cast(*obj)->SetByteLength(0); JSSharedTypedArray::Cast(*obj)->SetByteOffset(0); JSSharedTypedArray::Cast(*obj)->SetArrayLength(0); JSSharedTypedArray::Cast(*obj)->SetContentType(ContentType::None); JSSharedTypedArray::Cast(*obj)->SetModRecord(0); break; case JSType::JS_REG_EXP: JSRegExp::Cast(*obj)->SetByteCodeBuffer(thread_, JSTaggedValue::Undefined()); JSRegExp::Cast(*obj)->SetOriginalSource(thread_, JSTaggedValue::Undefined()); JSRegExp::Cast(*obj)->SetOriginalFlags(thread_, JSTaggedValue(0)); JSRegExp::Cast(*obj)->SetGroupName(thread_, JSTaggedValue::Undefined()); JSRegExp::Cast(*obj)->SetLength(0); break; case JSType::JS_PRIMITIVE_REF: JSPrimitiveRef::Cast(*obj)->SetValue(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_SET: JSSet::Cast(*obj)->SetLinkedSet(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_SHARED_SET: JSSharedSet::Cast(*obj)->SetLinkedSet(thread_, JSTaggedValue::Undefined()); JSSharedSet::Cast(*obj)->SetModRecord(0); break; case JSType::JS_MAP: JSMap::Cast(*obj)->SetLinkedMap(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_SHARED_MAP: JSSharedMap::Cast(*obj)->SetLinkedMap(thread_, JSTaggedValue::Undefined()); JSSharedMap::Cast(*obj)->SetModRecord(0); break; case JSType::JS_WEAK_MAP: JSWeakMap::Cast(*obj)->SetLinkedMap(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_WEAK_SET: JSWeakSet::Cast(*obj)->SetLinkedSet(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_WEAK_REF: JSWeakRef::Cast(*obj)->SetWeakObject(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_FINALIZATION_REGISTRY: JSFinalizationRegistry::Cast(*obj)->SetCleanupCallback(thread_, JSTaggedValue::Undefined()); JSFinalizationRegistry::Cast(*obj)->SetNoUnregister(thread_, JSTaggedValue::Undefined()); JSFinalizationRegistry::Cast(*obj)->SetMaybeUnregister(thread_, JSTaggedValue::Undefined()); JSFinalizationRegistry::Cast(*obj)->SetNext(thread_, JSTaggedValue::Null()); JSFinalizationRegistry::Cast(*obj)->SetPrev(thread_, JSTaggedValue::Null()); break; case JSType::JS_GENERATOR_OBJECT: JSGeneratorObject::Cast(*obj)->SetGeneratorContext(thread_, JSTaggedValue::Undefined()); JSGeneratorObject::Cast(*obj)->SetResumeResult(thread_, JSTaggedValue::Undefined()); JSGeneratorObject::Cast(*obj)->SetGeneratorState(JSGeneratorState::UNDEFINED); JSGeneratorObject::Cast(*obj)->SetResumeMode(GeneratorResumeMode::UNDEFINED); break; case JSType::JS_ASYNC_GENERATOR_OBJECT: JSAsyncGeneratorObject::Cast(*obj)->SetGeneratorContext(thread_, JSTaggedValue::Undefined()); JSAsyncGeneratorObject::Cast(*obj)->SetAsyncGeneratorQueue(thread_, GetEmptyTaggedQueue().GetTaggedValue()); JSAsyncGeneratorObject::Cast(*obj)->SetGeneratorBrand(thread_, JSTaggedValue::Undefined()); JSAsyncGeneratorObject::Cast(*obj)->SetResumeResult(thread_, JSTaggedValue::Undefined()); JSAsyncGeneratorObject::Cast(*obj)->SetAsyncGeneratorState(JSAsyncGeneratorState::UNDEFINED); JSAsyncGeneratorObject::Cast(*obj)->SetResumeMode(AsyncGeneratorResumeMode::UNDEFINED); break; case JSType::JS_STRING_ITERATOR: JSStringIterator::Cast(*obj)->SetStringIteratorNextIndex(0); JSStringIterator::Cast(*obj)->SetIteratedString(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_ASYNC_FROM_SYNC_ITERATOR: JSAsyncFromSyncIterator::Cast(*obj)->SetSyncIteratorRecord(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_ASYNC_FROM_SYNC_ITER_UNWARP_FUNCTION: JSAsyncFromSyncIterUnwarpFunction::Cast(*obj)->SetDone(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_ARRAY_BUFFER: JSArrayBuffer::Cast(*obj)->SetArrayBufferData(thread_, JSTaggedValue::Undefined()); JSArrayBuffer::Cast(*obj)->SetArrayBufferByteLength(0); JSArrayBuffer::Cast(*obj)->ClearBitField(); break; case JSType::JS_SHARED_ARRAY_BUFFER: JSArrayBuffer::Cast(*obj)->SetArrayBufferData(thread_, JSTaggedValue::Undefined()); JSArrayBuffer::Cast(*obj)->SetArrayBufferByteLength(0); JSArrayBuffer::Cast(*obj)->SetShared(true); break; case JSType::JS_SENDABLE_ARRAY_BUFFER: JSSendableArrayBuffer::Cast(*obj)->SetArrayBufferData(thread_, JSTaggedValue::Undefined()); JSSendableArrayBuffer::Cast(*obj)->SetArrayBufferByteLength(0); break; case JSType::JS_PROMISE: JSPromise::Cast(*obj)->SetPromiseState(PromiseState::PENDING); JSPromise::Cast(*obj)->SetPromiseResult(thread_, JSTaggedValue::Undefined()); JSPromise::Cast(*obj)->SetPromiseRejectReactions(thread_, GetEmptyTaggedQueue().GetTaggedValue()); JSPromise::Cast(*obj)->SetPromiseFulfillReactions(thread_, GetEmptyTaggedQueue().GetTaggedValue()); JSPromise::Cast(*obj)->SetPromiseIsHandled(false); break; case JSType::JS_DATA_VIEW: JSDataView::Cast(*obj)->SetDataView(thread_, JSTaggedValue(false)); JSDataView::Cast(*obj)->SetViewedArrayBuffer(thread_, JSTaggedValue::Undefined()); JSDataView::Cast(*obj)->SetByteLength(0); JSDataView::Cast(*obj)->SetByteOffset(0); break; // non ECMA standard jsapi container case JSType::JS_API_ARRAY_LIST: { JSAPIArrayList::Cast(*obj)->SetLength(thread_, JSTaggedValue(0)); break; } case JSType::JS_API_HASH_MAP: { JSAPIHashMap::Cast(*obj)->SetSize(0); JSAPIHashMap::Cast(*obj)->SetTable(thread_, JSTaggedValue::Undefined()); break; } case JSType::JS_API_HASH_SET: { JSAPIHashSet::Cast(*obj)->SetSize(0); JSAPIHashSet::Cast(*obj)->SetTable(thread_, JSTaggedValue::Undefined()); break; } case JSType::JS_API_TREE_MAP: { JSAPITreeMap::Cast(*obj)->SetTreeMap(thread_, JSTaggedValue::Undefined()); break; } case JSType::JS_API_TREE_SET: { JSAPITreeSet::Cast(*obj)->SetTreeSet(thread_, JSTaggedValue::Undefined()); break; } case JSType::JS_API_QUEUE: { JSAPIQueue::Cast(*obj)->SetLength(thread_, JSTaggedValue(0)); JSAPIQueue::Cast(*obj)->SetFront(0); JSAPIQueue::Cast(*obj)->SetTail(0); break; } case JSType::JS_API_PLAIN_ARRAY: { JSAPIPlainArray::Cast(*obj)->SetLength(0); JSAPIPlainArray::Cast(*obj)->SetValues(thread_, JSTaggedValue(0)); JSAPIPlainArray::Cast(*obj)->SetKeys(thread_, JSTaggedValue(0)); break; } case JSType::JS_API_STACK: { JSAPIStack::Cast(*obj)->SetTop(0); break; } case JSType::JS_API_DEQUE: { JSAPIDeque::Cast(*obj)->SetFirst(0); JSAPIDeque::Cast(*obj)->SetLast(0); break; } case JSType::JS_API_LIGHT_WEIGHT_MAP: { JSAPILightWeightMap::Cast(*obj)->SetLength(0); JSAPILightWeightMap::Cast(*obj)->SetHashes(thread_, JSTaggedValue::Undefined()); JSAPILightWeightMap::Cast(*obj)->SetKeys(thread_, JSTaggedValue::Undefined()); JSAPILightWeightMap::Cast(*obj)->SetValues(thread_, JSTaggedValue::Undefined()); break; } case JSType::JS_API_LIGHT_WEIGHT_SET: { JSAPILightWeightSet::Cast(*obj)->SetLength(0); JSAPILightWeightSet::Cast(*obj)->SetHashes(thread_, JSTaggedValue::Undefined()); JSAPILightWeightSet::Cast(*obj)->SetValues(thread_, JSTaggedValue::Undefined()); break; } case JSType::JS_API_VECTOR: { JSAPIVector::Cast(*obj)->SetLength(0); break; } case JSType::JS_API_LIST: { JSAPIList::Cast(*obj)->SetSingleList(thread_, JSTaggedValue::Undefined()); JSAPIList::Cast(*obj)->SetBitField(0UL); break; } case JSType::JS_API_LINKED_LIST: { JSAPILinkedList::Cast(*obj)->SetDoubleList(thread_, JSTaggedValue::Undefined()); break; } case JSType::JS_ASYNC_FUNC_OBJECT: JSAsyncFuncObject::Cast(*obj)->SetGeneratorContext(thread_, JSTaggedValue::Undefined()); JSAsyncFuncObject::Cast(*obj)->SetResumeResult(thread_, JSTaggedValue::Undefined()); JSAsyncFuncObject::Cast(*obj)->SetPromise(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_FUNCTION: case JSType::JS_GENERATOR_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj)); break; case JSType::JS_ASYNC_GENERATOR_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj)); break; case JSType::JS_PROXY_REVOC_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj)); JSProxyRevocFunction::Cast(*obj)->SetRevocableProxy(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_PROMISE_REACTIONS_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj)); JSPromiseReactionsFunction::Cast(*obj)->SetPromise(thread_, JSTaggedValue::Undefined()); JSPromiseReactionsFunction::Cast(*obj)->SetAlreadyResolved(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_PROMISE_EXECUTOR_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj)); JSPromiseExecutorFunction::Cast(*obj)->SetCapability(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_ASYNC_MODULE_FULFILLED_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj)); JSAsyncModuleFulfilledFunction::Cast(*obj)->SetModule(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_ASYNC_MODULE_REJECTED_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj)); JSAsyncModuleRejectedFunction::Cast(*obj)->SetModule(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_ASYNC_GENERATOR_RESUME_NEXT_RETURN_PROCESSOR_RST_FTN: JSFunction::InitializeJSFunction(thread_, JSHandle(obj)); JSAsyncGeneratorResNextRetProRstFtn::Cast(*obj)->SetAsyncGeneratorObject(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_PROMISE_ALL_RESOLVE_ELEMENT_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj)); JSPromiseAllResolveElementFunction::Cast(*obj)->SetIndex(thread_, JSTaggedValue::Undefined()); JSPromiseAllResolveElementFunction::Cast(*obj)->SetValues(thread_, JSTaggedValue::Undefined()); JSPromiseAllResolveElementFunction::Cast(*obj)->SetCapabilities(thread_, JSTaggedValue::Undefined()); JSPromiseAllResolveElementFunction::Cast(*obj)->SetRemainingElements(thread_, JSTaggedValue::Undefined()); JSPromiseAllResolveElementFunction::Cast(*obj)->SetAlreadyCalled(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_PROMISE_ANY_REJECT_ELEMENT_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj)); JSPromiseAnyRejectElementFunction::Cast(*obj)->SetIndex(0); JSPromiseAnyRejectElementFunction::Cast(*obj)->SetErrors(thread_, JSTaggedValue::Undefined()); JSPromiseAnyRejectElementFunction::Cast(*obj)->SetCapability(thread_, JSTaggedValue::Undefined()); JSPromiseAnyRejectElementFunction::Cast(*obj)->SetRemainingElements(thread_, JSTaggedValue::Undefined()); JSPromiseAnyRejectElementFunction::Cast(*obj)->SetAlreadyCalled(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_PROMISE_ALL_SETTLED_ELEMENT_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj)); JSPromiseAllSettledElementFunction::Cast(*obj)->SetIndex(0); JSPromiseAllSettledElementFunction::Cast(*obj)->SetValues(thread_, JSTaggedValue::Undefined()); JSPromiseAllSettledElementFunction::Cast(*obj)->SetCapability(thread_, JSTaggedValue::Undefined()); JSPromiseAllSettledElementFunction::Cast(*obj)->SetRemainingElements(thread_, JSTaggedValue::Undefined()); JSPromiseAllSettledElementFunction::Cast(*obj)->SetAlreadyCalled(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_PROMISE_FINALLY_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj)); JSPromiseFinallyFunction::Cast(*obj)->SetOnFinally(thread_, JSTaggedValue::Undefined()); JSPromiseFinallyFunction::Cast(*obj)->SetConstructor(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_PROMISE_VALUE_THUNK_OR_THROWER_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj)); JSPromiseValueThunkOrThrowerFunction::Cast(*obj)->SetResult(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_INTL_BOUND_FUNCTION: JSFunction::InitializeJSFunction(thread_, JSHandle(obj)); JSIntlBoundFunction::Cast(*obj)->SetNumberFormat(thread_, JSTaggedValue::Undefined()); JSIntlBoundFunction::Cast(*obj)->SetDateTimeFormat(thread_, JSTaggedValue::Undefined()); JSIntlBoundFunction::Cast(*obj)->SetCollator(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_BOUND_FUNCTION: JSBoundFunction::Cast(*obj)->SetMethod(thread_, JSTaggedValue::Undefined()); JSBoundFunction::Cast(*obj)->SetBoundTarget(thread_, JSTaggedValue::Undefined()); JSBoundFunction::Cast(*obj)->SetBoundThis(thread_, JSTaggedValue::Undefined()); JSBoundFunction::Cast(*obj)->SetBoundArguments(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_ARGUMENTS: break; case JSType::JS_FORIN_ITERATOR: case JSType::JS_MAP_ITERATOR: case JSType::JS_SET_ITERATOR: case JSType::JS_REG_EXP_ITERATOR: case JSType::JS_API_ARRAYLIST_ITERATOR: case JSType::JS_API_TREEMAP_ITERATOR: case JSType::JS_API_TREESET_ITERATOR: case JSType::JS_API_QUEUE_ITERATOR: case JSType::JS_API_DEQUE_ITERATOR: case JSType::JS_API_LIGHT_WEIGHT_MAP_ITERATOR: case JSType::JS_API_LIGHT_WEIGHT_SET_ITERATOR: case JSType::JS_API_STACK_ITERATOR: case JSType::JS_API_VECTOR_ITERATOR: case JSType::JS_API_HASHMAP_ITERATOR: case JSType::JS_API_HASHSET_ITERATOR: case JSType::JS_ARRAY_ITERATOR: case JSType::JS_API_PLAIN_ARRAY_ITERATOR: break; case JSType::JS_CJS_MODULE: CjsModule::Cast(*obj)->SetId(thread_, JSTaggedValue::Undefined()); CjsModule::Cast(*obj)->SetExports(thread_, JSTaggedValue::Undefined()); CjsModule::Cast(*obj)->SetPath(thread_, JSTaggedValue::Undefined()); CjsModule::Cast(*obj)->SetFilename(thread_, JSTaggedValue::Undefined()); CjsModule::Cast(*obj)->SetStatus(CjsModuleStatus::UNLOAD); break; case JSType::JS_CJS_EXPORTS: CjsExports::Cast(*obj)->SetExports(thread_, JSTaggedValue::Undefined()); break; case JSType::JS_CJS_REQUIRE: CjsRequire::Cast(*obj)->SetCache(thread_, JSTaggedValue::Undefined()); CjsRequire::Cast(*obj)->SetParent(thread_, JSTaggedValue::Undefined()); break; default: LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); } } FreeObject *ObjectFactory::FillFreeObject(uintptr_t address, size_t size, RemoveSlots removeSlots, uintptr_t hugeObjectHead) { FreeObject *object = nullptr; const GlobalEnvConstants *globalConst = thread_->GetFirstGlobalConst(); if (size >= FreeObject::SIZE_OFFSET && size < FreeObject::SIZE) { object = reinterpret_cast(address); object->SetClassWithoutBarrier(JSHClass::Cast(globalConst->GetFreeObjectWithOneFieldClass().GetTaggedObject())); object->SetNext(INVALID_OBJECT); } else if (size >= FreeObject::SIZE) { object = reinterpret_cast(address); object->SetClassWithoutBarrier( JSHClass::Cast(globalConst->GetFreeObjectWithTwoFieldClass().GetTaggedObject())); object->SetAvailable(size); object->SetNext(INVALID_OBJECT); if (UNLIKELY(heap_->ShouldVerifyHeap())) { FillFreeMemoryRange(address + FreeObject::SIZE, address + size); } } else if (size == FreeObject::NEXT_OFFSET) { object = reinterpret_cast(address); object->SetClassWithoutBarrier( JSHClass::Cast(globalConst->GetFreeObjectWithNoneFieldClass().GetTaggedObject())); } else { LOG_ECMA(DEBUG) << "Fill free object size is smaller"; } if (removeSlots == RemoveSlots::YES) { // For huge object, the region of `object` might not be its 1st region. Use `hugeObjectHead` instead. Region *region = Region::ObjectAddressToRange(hugeObjectHead == 0 ? object : reinterpret_cast(hugeObjectHead)); heap_->ClearSlotsRange(region, address, address + size); } return object; } TaggedObject *ObjectFactory::NewObject(const JSHandle &hclass) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject(*hclass); uint32_t inobjPropCount = hclass->GetInlinedProperties(); if (inobjPropCount > 0) { InitializeExtraProperties(hclass, header, inobjPropCount); } return header; } TaggedObject *ObjectFactory::NewNonMovableObject(const JSHandle &hclass, uint32_t inobjPropCount) { NewObjectHook(); TaggedObject *header = heap_->AllocateNonMovableOrHugeObject(*hclass); if (inobjPropCount > 0) { InitializeExtraProperties(hclass, header, inobjPropCount); } return header; } void ObjectFactory::InitializeExtraProperties(const JSHandle &hclass, TaggedObject *obj, uint32_t inobjPropCount) { ASSERT(inobjPropCount * JSTaggedValue::TaggedTypeSize() < hclass->GetObjectSize()); auto paddr = reinterpret_cast(obj) + hclass->GetObjectSize(); // The object which created by AOT speculative hclass, should be initialized as hole, means does not exist, // to follow ECMA spec. JSTaggedType initVal = hclass->IsTS() ? JSTaggedValue::VALUE_HOLE : JSTaggedValue::VALUE_UNDEFINED; for (uint32_t i = 0; i < inobjPropCount; ++i) { paddr -= JSTaggedValue::TaggedTypeSize(); *reinterpret_cast(paddr) = initVal; } } JSHandle ObjectFactory::OrdinaryNewJSObjectCreate(const JSHandle &proto) { JSHandle protoValue(proto); JSHandle hclass(thread_, thread_->GlobalConstants()->GetObjectClass().GetTaggedObject()); JSHandle newClass = JSHClass::TransProtoWithoutLayout(thread_, hclass, protoValue); JSHandle newObj = NewJSObject(newClass); newObj->GetJSHClass()->SetExtensible(true); return newObj; } JSHandle ObjectFactory::NewJSFunction(const JSHandle &env, const void *nativeFunc, FunctionKind kind, kungfu::BuiltinsStubCSigns::ID builtinId, MemSpaceType methodSpaceType) { JSHandle target = NewMethodForNativeFunction(nativeFunc, kind, builtinId, methodSpaceType); return NewJSFunction(env, target); } JSHandle ObjectFactory::NewJSFunction(const JSHandle &env, const JSHandle &method) { FunctionKind kind = method->GetFunctionKind(); JSHandle hclass; if (kind == FunctionKind::BASE_CONSTRUCTOR) { hclass = JSHandle::Cast(env->GetFunctionClassWithProto()); } else if (JSFunction::IsConstructorKind(kind)) { hclass = JSHandle::Cast(env->GetConstructorFunctionClass()); } else if (kind == FunctionKind::CONCURRENT_FUNCTION) { hclass = JSHandle::Cast(env->GetAsyncFunctionClass()); } else { hclass = JSHandle::Cast(env->GetNormalFunctionClass()); } return NewJSFunctionByHClass(method, hclass); } JSHandle ObjectFactory::NewSFunction(const JSHandle &env, const void *nativeFunc, FunctionKind kind, kungfu::BuiltinsStubCSigns::ID builtinId, MemSpaceType spaceType) { JSHandle method = NewSMethodForNativeFunction(nativeFunc, kind, builtinId, spaceType); JSHandle hclass = JSHandle::Cast(env->GetSFunctionClassWithoutProto()); JSHandle sfunc = NewSFunctionByHClass(method, hclass); return sfunc; } JSHandle ObjectFactory::CreateFunctionClass(FunctionKind kind, uint32_t size, JSType type, const JSHandle &prototype) { const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle functionClass = NewEcmaHClass(size, type, prototype); { functionClass->SetCallable(true); // FunctionKind = BASE_CONSTRUCTOR if (JSFunction::IsConstructorKind(kind)) { functionClass->SetConstructor(true); } functionClass->SetExtensible(true); } uint32_t fieldOrder = 0; ASSERT(JSFunction::LENGTH_INLINE_PROPERTY_INDEX == fieldOrder); JSHandle layoutInfoHandle = CreateLayoutInfo(JSFunction::LENGTH_OF_INLINE_PROPERTIES); { PropertyAttributes attributes = PropertyAttributes::DefaultAccessor(false, false, true); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(fieldOrder); layoutInfoHandle->AddKey(thread_, fieldOrder, globalConst->GetLengthString(), attributes); fieldOrder++; } ASSERT(JSFunction::NAME_INLINE_PROPERTY_INDEX == fieldOrder); // not set name in-object property on class which may have a name() method if (!JSFunction::IsClassConstructor(kind)) { PropertyAttributes attributes = PropertyAttributes::DefaultAccessor(false, false, true); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(fieldOrder); layoutInfoHandle->AddKey(thread_, fieldOrder, thread_->GlobalConstants()->GetHandledNameString().GetTaggedValue(), attributes); fieldOrder++; } if (JSFunction::HasPrototype(kind) && !JSFunction::IsClassConstructor(kind)) { ASSERT(JSFunction::PROTOTYPE_INLINE_PROPERTY_INDEX == fieldOrder); PropertyAttributes attributes = PropertyAttributes::DefaultAccessor(true, false, false); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(fieldOrder); layoutInfoHandle->AddKey(thread_, fieldOrder, globalConst->GetPrototypeString(), attributes); fieldOrder++; } else if (JSFunction::IsClassConstructor(kind)) { ASSERT(JSFunction::CLASS_PROTOTYPE_INLINE_PROPERTY_INDEX == fieldOrder); PropertyAttributes attributes = PropertyAttributes::DefaultAccessor(false, false, false); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(fieldOrder); layoutInfoHandle->AddKey(thread_, fieldOrder, globalConst->GetPrototypeString(), attributes); fieldOrder++; } { functionClass->SetLayout(thread_, layoutInfoHandle); functionClass->SetNumberOfProps(fieldOrder); } return functionClass; } JSHandle ObjectFactory::CreateBoundFunctionClass() { JSHandle env = vm_->GetGlobalEnv(); JSHandle proto = env->GetFunctionPrototype(); JSHandle hclass = NewEcmaHClass(JSBoundFunction::SIZE, JSType::JS_BOUND_FUNCTION, proto); hclass->SetCallable(true); // set hclass layout uint32_t fieldOrder = 0; const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); ASSERT(JSFunction::LENGTH_INLINE_PROPERTY_INDEX == fieldOrder); JSHandle layoutInfoHandle = CreateLayoutInfo(JSFunction::LENGTH_OF_INLINE_PROPERTIES); { PropertyAttributes attributes = PropertyAttributes::DefaultAccessor(false, false, true); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(fieldOrder); layoutInfoHandle->AddKey(thread_, fieldOrder, globalConst->GetLengthString(), attributes); fieldOrder++; } ASSERT(JSFunction::NAME_INLINE_PROPERTY_INDEX == fieldOrder); // not set name in-object property on class which may have a name() method { PropertyAttributes attributes = PropertyAttributes::DefaultAccessor(false, false, true); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(fieldOrder); layoutInfoHandle->AddKey(thread_, fieldOrder, globalConst->GetHandledNameString().GetTaggedValue(), attributes); fieldOrder++; } { hclass->SetLayout(thread_, layoutInfoHandle); hclass->SetNumberOfProps(fieldOrder); } return hclass; } JSHandle ObjectFactory::CreateDefaultClassPrototypeHClass(JSHClass *hclass) { uint32_t size = ClassInfoExtractor::NON_STATIC_RESERVED_LENGTH; JSHandle layout = CreateLayoutInfo(size, MemSpaceType::OLD_SPACE, GrowMode::KEEP); PropertyAttributes attributes = PropertyAttributes::Default(true, false, true); // non-enumerable attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(ClassInfoExtractor::CONSTRUCTOR_INDEX); layout->AddKey(thread_, ClassInfoExtractor::CONSTRUCTOR_INDEX, thread_->GlobalConstants()->GetConstructorString(), attributes); JSHandle defaultHclass = NewEcmaHClass(hclass, JSObject::SIZE, JSType::JS_OBJECT, size); defaultHclass->SetLayout(thread_, layout); defaultHclass->SetNumberOfProps(size); defaultHclass->SetClassPrototype(true); defaultHclass->SetIsPrototype(true); return defaultHclass; } JSHandle ObjectFactory::CreateDefaultClassConstructorHClass(JSHClass *hclass) { uint32_t size = ClassInfoExtractor::STATIC_RESERVED_LENGTH; JSHandle layout = CreateLayoutInfo(size, MemSpaceType::OLD_SPACE, GrowMode::KEEP); JSHandle array = NewTaggedArray(size); array->Set(thread_, ClassInfoExtractor::LENGTH_INDEX, thread_->GlobalConstants()->GetLengthString()); array->Set(thread_, ClassInfoExtractor::NAME_INDEX, thread_->GlobalConstants()->GetNameString()); array->Set(thread_, ClassInfoExtractor::PROTOTYPE_INDEX, thread_->GlobalConstants()->GetPrototypeString()); for (uint32_t index = ClassInfoExtractor::LENGTH_INDEX; index < size; index++) { PropertyAttributes attributes; if (index == ClassInfoExtractor::PROTOTYPE_INDEX) { attributes = PropertyAttributes::DefaultAccessor(false, false, false); } else { attributes = PropertyAttributes::Default(false, false, true); } attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(index); layout->AddKey(thread_, index, array->Get(index), attributes); } JSHandle defaultHclass = NewEcmaHClass(hclass, JSFunction::SIZE, JSType::JS_FUNCTION, size); defaultHclass->SetLayout(thread_, layout); defaultHclass->SetNumberOfProps(size); defaultHclass->SetClassConstructor(true); defaultHclass->SetConstructor(true); return defaultHclass; } JSHandle ObjectFactory::NewJSFunctionByHClass(const JSHandle &method, const JSHandle &clazz, MemSpaceType type) { JSHandle function; switch (type) { case MemSpaceType::SEMI_SPACE: function = JSHandle::Cast(NewJSObject(clazz)); break; case MemSpaceType::OLD_SPACE: function = JSHandle::Cast(NewOldSpaceJSObject(clazz)); break; case MemSpaceType::NON_MOVABLE: function = JSHandle::Cast(NewNonMovableJSObject(clazz)); break; default: LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); } clazz->SetCallable(true); clazz->SetExtensible(true); JSFunction::InitializeJSFunction(thread_, function, method->GetFunctionKind()); function->SetMethod(thread_, method); if (method->IsJitCompiledCode()) { // jit install code also set aot callfield, should clear flag when new function method->ClearJitCompiledCodeFlags(); } else if (method->IsAotWithCallField()) { thread_->GetEcmaVM()->GetAOTFileManager()-> SetAOTFuncEntry(method->GetJSPandaFile(), *function, *method); } return function; } JSHandle ObjectFactory::NewJSFunctionByHClass(const void *func, const JSHandle &clazz, FunctionKind kind) { JSHandle method = NewMethodForNativeFunction(func, kind); JSHandle function = JSHandle::Cast(NewJSObject(clazz)); clazz->SetCallable(true); clazz->SetExtensible(true); JSFunction::InitializeJSFunction(thread_, function, kind); function->SetMethod(thread_, method); return function; } void ObjectFactory::InitializeMethod(const MethodLiteral *methodLiteral, JSHandle &method) { if (methodLiteral != nullptr) { method->SetCallField(methodLiteral->GetCallField()); method->SetLiteralInfo(methodLiteral->GetLiteralInfo()); method->SetNativePointerOrBytecodeArray(const_cast(methodLiteral->GetNativePointer())); method->SetExtraLiteralInfo(methodLiteral->GetExtraLiteralInfo()); } else { method->SetCallField(0ULL); method->SetLiteralInfo(0ULL); method->SetNativePointerOrBytecodeArray(nullptr); method->SetExtraLiteralInfo(0ULL); } method->SetCodeEntryOrLiteral(reinterpret_cast(methodLiteral)); method->SetConstantPool(thread_, JSTaggedValue::Undefined()); } JSHandle ObjectFactory::NewMethod(const MethodLiteral *methodLiteral, MemSpaceType spaceType) { NewObjectHook(); TaggedObject *header = nullptr; if (spaceType == NON_MOVABLE) { header = heap_->AllocateNonMovableOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetMethodClass().GetTaggedObject())); } else { header = heap_->AllocateOldOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetMethodClass().GetTaggedObject())); } JSHandle method(thread_, header); InitializeMethod(methodLiteral, method); return method; } JSHandle ObjectFactory::NewMethod(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 = NewMethod(methodLiteral); method->SetConstantPool(thread_, constpool); } if (needSetAotFlag) { thread_->GetEcmaVM()->GetAOTFileManager()-> SetAOTFuncEntry(jsPandaFile, nullptr, *method, entryIndex, canFastCall); } else { method->ClearAOTFlagsWhenInit(); } return method; } JSHandle ObjectFactory::NewJSNativeErrorFunction(const JSHandle &env, const void *nativeFunc) { JSHandle target = NewMethodForNativeFunction(nativeFunc, FunctionKind::BUILTIN_CONSTRUCTOR); JSHandle hclass = JSHandle::Cast(env->GetNativeErrorFunctionClass()); return NewJSFunctionByHClass(target, hclass); } JSHandle ObjectFactory::NewSpecificTypedArrayFunction(const JSHandle &env, const void *nativeFunc) { JSHandle target = NewMethodForNativeFunction(nativeFunc, FunctionKind::BUILTIN_CONSTRUCTOR); JSHandle hclass = JSHandle::Cast(env->GetSpecificTypedArrayFunctionClass()); return NewJSFunctionByHClass(target, hclass); } JSHandle ObjectFactory::NewAotFunction(uint32_t numArgs, uintptr_t codeEntry) { JSHandle env = vm_->GetGlobalEnv(); JSHandle method = NewMethodForNativeFunction(reinterpret_cast(codeEntry)); method->SetAotCodeBit(true); method->SetNativeBit(false); method->SetNumArgsWithCallField(numArgs); method->SetCodeEntryOrLiteral(codeEntry); JSHandle jsfunc = NewJSFunction(env, method); return jsfunc; } JSHandle ObjectFactory::NewJSBoundFunction(const JSHandle &target, const JSHandle &boundThis, const JSHandle &args) { JSHandle env = vm_->GetGlobalEnv(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle hclass = JSHandle::Cast(env->GetBoundFunctionClass()); JSHandle bundleFunction = JSHandle::Cast(NewJSObject(hclass)); // set properties JSHandle accessor = globalConst->GetHandledFunctionNameAccessor(); bundleFunction->SetPropertyInlinedProps(thread_, JSFunction::NAME_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue()); accessor = globalConst->GetHandledFunctionLengthAccessor(); bundleFunction->SetPropertyInlinedProps(thread_, JSFunction::LENGTH_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue()); bundleFunction->SetBoundTarget(thread_, target); bundleFunction->SetBoundThis(thread_, boundThis); bundleFunction->SetBoundArguments(thread_, args); if (target.GetTaggedValue().IsConstructor()) { bundleFunction->SetConstructor(true); } bundleFunction->SetMethod(thread_, vm_->GetMethodByIndex(MethodIndex::BUILTINS_GLOBAL_CALL_JS_BOUND_FUNCTION)); return bundleFunction; } JSHandle ObjectFactory::NewJSIntlBoundFunction(MethodIndex idx, int functionLength) { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetJSIntlBoundFunctionClass()); JSHandle intlBoundFunc = JSHandle::Cast(NewJSObject(hclass)); intlBoundFunc->SetNumberFormat(thread_, JSTaggedValue::Undefined()); intlBoundFunc->SetDateTimeFormat(thread_, JSTaggedValue::Undefined()); intlBoundFunc->SetCollator(thread_, JSTaggedValue::Undefined()); JSHandle function = JSHandle::Cast(intlBoundFunc); JSFunction::InitializeJSFunction(thread_, function); function->SetMethod(thread_, vm_->GetMethodByIndex(idx)); JSFunction::SetFunctionLength(thread_, function, JSTaggedValue(functionLength)); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle emptyString = globalConst->GetHandledEmptyString(); JSHandle nameKey = globalConst->GetHandledNameString(); PropertyDescriptor nameDesc(thread_, emptyString, false, false, true); JSTaggedValue::DefinePropertyOrThrow(thread_, JSHandle::Cast(function), nameKey, nameDesc); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSIntlBoundFunction, thread_); return intlBoundFunc; } JSHandle ObjectFactory::NewJSProxyRevocFunction(const JSHandle &proxy) { JSHandle env = vm_->GetGlobalEnv(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle hclass = JSHandle::Cast(env->GetProxyRevocFunctionClass()); JSHandle revocFunction = JSHandle::Cast(NewJSObject(hclass)); revocFunction->SetRevocableProxy(thread_, JSTaggedValue::Undefined()); revocFunction->SetRevocableProxy(thread_, proxy); JSHandle function = JSHandle::Cast(revocFunction); JSFunction::InitializeJSFunction(thread_, function); function->SetMethod(thread_, vm_->GetMethodByIndex(MethodIndex::BUILTINS_PROXY_INVALIDATE_PROXY_FUNCTION)); JSFunction::SetFunctionLength(thread_, function, JSTaggedValue(0)); JSHandle emptyString = globalConst->GetHandledEmptyString(); JSHandle nameKey = globalConst->GetHandledNameString(); PropertyDescriptor nameDesc(thread_, emptyString, false, false, true); JSTaggedValue::DefinePropertyOrThrow(thread_, JSHandle::Cast(function), nameKey, nameDesc); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSProxyRevocFunction, thread_); return revocFunction; } JSHandle ObjectFactory::NewJSAsyncAwaitStatusFunction(MethodIndex idx) { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetAsyncAwaitStatusFunctionClass()); JSHandle awaitFunction = JSHandle::Cast(NewJSObject(hclass)); awaitFunction->SetAsyncContext(thread_, JSTaggedValue::Undefined()); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(awaitFunction)); awaitFunction->SetMethod(thread_, vm_->GetMethodByIndex(idx)); return awaitFunction; } JSHandle ObjectFactory::NewJSGeneratorObject(JSHandle generatorFunction) { JSHandle proto(thread_, JSHandle::Cast(generatorFunction)->GetProtoOrHClass()); if (!proto->IsECMAObject()) { JSHandle realmHandle = JSObject::GetFunctionRealm(thread_, generatorFunction); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSGeneratorObject, thread_); proto = realmHandle->GetGeneratorPrototype(); } JSHandle hclass = NewEcmaHClass(JSGeneratorObject::SIZE, JSType::JS_GENERATOR_OBJECT, proto); JSHandle generatorObject = JSHandle::Cast(NewJSObjectWithInit(hclass)); generatorObject->SetGeneratorContext(thread_, JSTaggedValue::Undefined()); generatorObject->SetResumeResult(thread_, JSTaggedValue::Undefined()); return generatorObject; } JSHandle ObjectFactory::NewJSAsyncGeneratorObject(JSHandle generatorFunction) { JSHandle proto(thread_, JSHandle::Cast(generatorFunction)->GetProtoOrHClass()); if (!proto->IsECMAObject()) { JSHandle realmHandle = JSObject::GetFunctionRealm(thread_, generatorFunction); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSAsyncGeneratorObject, thread_); proto = realmHandle->GetAsyncGeneratorPrototype(); } JSHandle hclass = NewEcmaHClass(JSAsyncGeneratorObject::SIZE, JSType::JS_ASYNC_GENERATOR_OBJECT, proto); JSHandle generatorObject = JSHandle::Cast(NewJSObjectWithInit(hclass)); return generatorObject; } JSHandle ObjectFactory::NewJSAsyncFuncObject() { JSHandle env = vm_->GetGlobalEnv(); JSHandle proto = env->GetInitialGenerator(); JSHandle hclass = NewEcmaHClass(JSAsyncFuncObject::SIZE, JSType::JS_ASYNC_FUNC_OBJECT, proto); JSHandle asyncFuncObject = JSHandle::Cast(NewJSObjectWithInit(hclass)); return asyncFuncObject; } JSHandle ObjectFactory::NewCompletionRecord(CompletionRecordType type, JSHandle value) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetCompletionRecordClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetType(type); obj->SetValue(thread_, value); return obj; } JSHandle ObjectFactory::NewGeneratorContext() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetGeneratorContextClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetRegsArray(thread_, JSTaggedValue::Undefined()); obj->SetMethod(thread_, JSTaggedValue::Undefined()); obj->SetThis(thread_, JSTaggedValue::Undefined()); obj->SetAcc(thread_, JSTaggedValue::Undefined()); obj->SetGeneratorObject(thread_, JSTaggedValue::Undefined()); obj->SetLexicalEnv(thread_, JSTaggedValue::Undefined()); obj->SetNRegs(0); obj->SetBCOffset(0); return obj; } JSHandle ObjectFactory::NewJSPrimitiveRef(const JSHandle &function, const JSHandle &object) { JSHandle obj(NewJSObjectByConstructor(function)); obj->SetValue(thread_, object); JSHandle env = vm_->GetGlobalEnv(); if (function.GetTaggedValue() == env->GetStringFunction().GetTaggedValue()) { JSHandle lengthStr = thread_->GlobalConstants()->GetHandledLengthString(); uint32_t length = EcmaStringAccessor(object.GetTaggedValue()).GetLength(); PropertyDescriptor desc(thread_, JSHandle(thread_, JSTaggedValue(length)), false, false, false); JSTaggedValue::DefinePropertyOrThrow(thread_, JSHandle(obj), lengthStr, desc); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSPrimitiveRef, thread_); } return obj; } JSHandle ObjectFactory::NewJSPrimitiveRef(PrimitiveType type, const JSHandle &object) { ObjectFactory *factory = vm_->GetFactory(); JSHandle env = vm_->GetGlobalEnv(); JSHandle function; switch (type) { case PrimitiveType::PRIMITIVE_NUMBER: function = env->GetNumberFunction(); break; case PrimitiveType::PRIMITIVE_STRING: function = env->GetStringFunction(); break; case PrimitiveType::PRIMITIVE_SYMBOL: function = env->GetSymbolFunction(); break; case PrimitiveType::PRIMITIVE_BOOLEAN: function = env->GetBooleanFunction(); break; case PrimitiveType::PRIMITIVE_BIGINT: function = env->GetBigIntFunction(); break; default: break; } JSHandle funcHandle(function); return factory->NewJSPrimitiveRef(funcHandle, object); } JSHandle ObjectFactory::NewJSString(const JSHandle &str, const JSHandle &newTarget) { JSHandle env = vm_->GetGlobalEnv(); JSHandle stringFunc(env->GetStringFunction()); JSHandle obj; if (newTarget->IsUndefined()) { obj = JSHandle::Cast(NewJSObjectByConstructor(stringFunc)); } else { JSHandle newObject = NewJSObjectByConstructor(stringFunc, newTarget); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSPrimitiveRef, thread_); obj = JSHandle::Cast(newObject); } obj->SetValue(thread_, str); return obj; } JSHandle ObjectFactory::NewGlobalEnv(JSHClass *globalEnvClass) { NewObjectHook(); // Note: Global env must be allocated in non-movable heap, since its getters will directly return // the offsets of the properties as the address of Handles. TaggedObject *header = heap_->AllocateNonMovableOrHugeObject(globalEnvClass); InitObjectFields(header); return JSHandle(thread_, GlobalEnv::Cast(header)); } JSHandle ObjectFactory::NewLexicalEnv(int numSlots) { NewObjectHook(); size_t size = LexicalEnv::ComputeSize(numSlots); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetEnvClass().GetTaggedObject()), size); JSHandle array(thread_, header); array->InitializeWithSpecialValue(JSTaggedValue::Hole(), numSlots + LexicalEnv::RESERVED_ENV_LENGTH); return array; } JSHandle ObjectFactory::NewEmptySymbol() { NewObjectHook(); TaggedObject *header = heap_->AllocateNonMovableOrHugeObject( 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::NewJSSymbol() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetSymbolClass().GetTaggedObject())); JSHandle obj(thread_, JSSymbol::Cast(header)); obj->SetDescription(thread_, JSTaggedValue::Undefined()); obj->SetFlags(0); obj->SetHashField(SymbolTable::Hash(obj.GetTaggedValue())); return obj; } JSHandle ObjectFactory::NewPrivateSymbol() { JSHandle obj = NewJSSymbol(); obj->SetPrivate(); return obj; } JSHandle ObjectFactory::NewPrivateNameSymbol(const JSHandle &name) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetSymbolClass().GetTaggedObject())); JSHandle obj(thread_, JSSymbol::Cast(header)); obj->SetFlags(0); obj->SetPrivateNameSymbol(); obj->SetDescription(thread_, name); obj->SetHashField(SymbolTable::Hash(name.GetTaggedValue())); return obj; } JSHandle ObjectFactory::NewWellKnownSymbol(const JSHandle &name) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( 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::NewPublicSymbol(const JSHandle &name) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( 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::NewSymbolWithTable(const JSHandle &name) { JSHandle env = vm_->GetGlobalEnv(); JSHandle tableHandle(env->GetRegisterSymbols()); if (tableHandle->ContainsKey(name.GetTaggedValue())) { JSTaggedValue objValue = tableHandle->GetSymbol(name.GetTaggedValue()); return JSHandle(thread_, objValue); } JSHandle obj = NewPublicSymbol(name); JSHandle valueHandle(obj); JSHandle keyHandle(name); JSHandle table = SymbolTable::Insert(thread_, tableHandle, keyHandle, valueHandle); env->SetRegisterSymbols(thread_, table); return obj; } JSHandle ObjectFactory::NewPrivateNameSymbolWithChar(std::string_view description) { JSHandle string = NewFromUtf8(description); return NewPrivateNameSymbol(JSHandle(string)); } JSHandle ObjectFactory::NewWellKnownSymbolWithChar(std::string_view description) { JSHandle string = NewFromUtf8(description); return NewWellKnownSymbol(JSHandle(string)); } JSHandle ObjectFactory::NewPublicSymbolWithChar(std::string_view description) { JSHandle string = NewFromUtf8(description); return NewPublicSymbol(JSHandle(string)); } JSHandle ObjectFactory::NewSymbolWithTableWithChar(std::string_view description) { JSHandle string = NewFromUtf8(description); return NewSymbolWithTable(JSHandle(string)); } JSHandle ObjectFactory::NewAccessorData() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( 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::NewInternalAccessor(void *setter, void *getter) { NewObjectHook(); TaggedObject *header = heap_->AllocateNonMovableOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetInternalAccessorClass().GetTaggedObject())); JSHandle obj(thread_, AccessorData::Cast(header)); obj->SetGetter(thread_, JSTaggedValue::Undefined()); obj->SetSetter(thread_, JSTaggedValue::Undefined()); if (setter != nullptr) { JSHandle setFunc = NewJSNativePointer(setter, nullptr, nullptr, true); obj->SetSetter(thread_, setFunc.GetTaggedValue()); } else { JSTaggedValue setFunc = JSTaggedValue::Undefined(); obj->SetSetter(thread_, setFunc); ASSERT(!obj->HasSetter()); } JSHandle getFunc = NewJSNativePointer(getter, nullptr, nullptr, true); obj->SetGetter(thread_, getFunc); return obj; } JSHandle ObjectFactory::NewPromiseCapability() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetCapabilityRecordClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetPromise(thread_, JSTaggedValue::Undefined()); obj->SetResolve(thread_, JSTaggedValue::Undefined()); obj->SetReject(thread_, JSTaggedValue::Undefined()); return obj; } JSHandle ObjectFactory::NewPromiseReaction() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetReactionsRecordClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetPromiseCapability(thread_, JSTaggedValue::Undefined()); obj->SetHandler(thread_, JSTaggedValue::Undefined()); obj->SetType(PromiseType::RESOLVE); return obj; } JSHandle ObjectFactory::NewPromiseIteratorRecord(const JSHandle &itor, bool done) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetPromiseIteratorRecordClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetIterator(thread_, itor.GetTaggedValue()); obj->SetDone(done); return obj; } JSHandle ObjectFactory::NewMicroJobQueue() { NewObjectHook(); TaggedObject *header = heap_->AllocateNonMovableOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetMicroJobQueueClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetPromiseJobQueue(thread_, GetEmptyTaggedQueue().GetTaggedValue()); obj->SetScriptJobQueue(thread_, GetEmptyTaggedQueue().GetTaggedValue()); return obj; } JSHandle ObjectFactory::NewPendingJob(const JSHandle &func, const JSHandle &argv) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetPendingJobClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetJob(thread_, func.GetTaggedValue()); obj->SetArguments(thread_, argv.GetTaggedValue()); #if defined(ENABLE_HITRACE) obj->SetChainId(0); obj->SetSpanId(0); obj->SetParentSpanId(0); obj->SetFlags(0); obj->SetJobId(0); #endif return obj; } JSHandle ObjectFactory::NewJSProxy(const JSHandle &target, const JSHandle &handler) { NewObjectHook(); TaggedObject *header = nullptr; const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle emptyObject = OrdinaryNewJSObjectCreate(vm_->GetGlobalEnv()->GetObjectFunctionPrototype()); if (target->IsCallable()) { auto jsProxyCallableClass = JSHClass::Cast(globalConst->GetJSProxyCallableClass().GetTaggedObject()); auto jsProxyConstructClass = JSHClass::Cast(globalConst->GetJSProxyConstructClass().GetTaggedObject()); header = target->IsConstructor() ? heap_->AllocateYoungOrHugeObject(jsProxyConstructClass) : heap_->AllocateYoungOrHugeObject(jsProxyCallableClass); } else { header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetJSProxyOrdinaryClass().GetTaggedObject())); } JSHandle proxy(thread_, header); proxy->InitializeHash(); proxy->SetMethod(thread_, vm_->GetMethodByIndex(MethodIndex::BUILTINS_GLOBAL_CALL_JS_PROXY)); proxy->SetTarget(thread_, target.GetTaggedValue()); proxy->SetHandler(thread_, handler.GetTaggedValue()); proxy->SetPrivateField(thread_, emptyObject.GetTaggedValue()); proxy->SetIsRevoked(false); return proxy; } JSHandle ObjectFactory::NewJSRealm() { JSHandle hClassHandle = NewEcmaHClassClass(nullptr, JSHClass::SIZE, JSType::HCLASS); JSHClass *hclass = reinterpret_cast(hClassHandle.GetTaggedValue().GetTaggedObject()); hclass->SetClass(thread_, hclass); JSHandle realmEnvClass = NewEcmaHClass(*hClassHandle, GlobalEnv::SIZE, JSType::GLOBAL_ENV); JSHandle realmEnvHandle = NewGlobalEnv(*realmEnvClass); auto result = TemplateMap::Create(thread_); realmEnvHandle->SetTemplateMap(thread_, result); realmEnvHandle->SetJSThread(thread_); Builtins builtins; builtins.Initialize(realmEnvHandle, thread_, false, true); JSHandle protoValue = thread_->GlobalConstants()->GetHandledJSRealmClass(); JSHandle hclassHandle = NewEcmaHClass(JSRealm::SIZE, JSType::JS_REALM, protoValue); JSHandle realm(NewJSObject(hclassHandle)); realm->SetGlobalEnv(thread_, realmEnvHandle.GetTaggedValue()); realm->SetValue(thread_, JSTaggedValue::Undefined()); JSHandle realmObj = realmEnvHandle->GetJSGlobalObject(); JSHandle realmkey(thread_->GlobalConstants()->GetHandledGlobalString()); PropertyDescriptor realmDesc(thread_, JSHandle::Cast(realmObj), true, false, true); [[maybe_unused]] bool status = JSObject::DefineOwnProperty(thread_, JSHandle::Cast(realm), realmkey, realmDesc); ASSERT_PRINT(status == true, "Realm defineOwnProperty failed"); return realm; } JSHandle ObjectFactory::NewTaggedArray(uint32_t length, JSTaggedValue initVal, bool nonMovable) { if (nonMovable) { return NewTaggedArray(length, initVal, MemSpaceType::NON_MOVABLE); } return NewTaggedArray(length, initVal, MemSpaceType::SEMI_SPACE); } JSHandle ObjectFactory::NewTaggedArray(uint32_t length, JSTaggedValue initVal, MemSpaceType spaceType) { NewObjectHook(); 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::SEMI_SPACE: header = heap_->AllocateYoungOrHugeObject(arrayClass, size); break; case MemSpaceType::OLD_SPACE: header = heap_->AllocateOldOrHugeObject(arrayClass, size); break; case MemSpaceType::NON_MOVABLE: header = heap_->AllocateNonMovableOrHugeObject(arrayClass, size); break; 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::NewAndCopyTaggedArray(JSHandle &srcElements, uint32_t newLength, uint32_t oldLength, uint32_t k) { ASSERT(oldLength <= newLength); MemSpaceType spaceType = newLength < LENGTH_THRESHOLD ? MemSpaceType::SEMI_SPACE : MemSpaceType::OLD_SPACE; JSHandle dstElements = NewTaggedArrayWithoutInit(newLength, spaceType); dstElements->SetExtraLength(srcElements->GetExtraLength()); if (newLength == 0) { return dstElements; } for (uint32_t i = 0; i < oldLength; i++) { dstElements->Set(thread_, i, srcElements->Get(i + k)); } for (uint32_t i = oldLength; i < newLength; i++) { dstElements->Set(thread_, i, JSTaggedValue::Hole()); } return dstElements; } JSHandle ObjectFactory::NewAndCopyTaggedArraySkipBarrier(JSHandle &srcElements, uint32_t newLength, uint32_t oldLength, uint32_t k) { ASSERT(oldLength <= newLength); MemSpaceType spaceType = newLength < LENGTH_THRESHOLD ? MemSpaceType::SEMI_SPACE : MemSpaceType::OLD_SPACE; JSHandle dstElements = NewTaggedArrayWithoutInit(newLength, spaceType); if (newLength == 0) { return dstElements; } for (uint32_t i = 0; i < oldLength; i++) { dstElements->Set(thread_, i, srcElements->Get(i + k)); } for (uint32_t i = oldLength; i < newLength; i++) { dstElements->Set(thread_, i, JSTaggedValue::Hole()); } return dstElements; } JSHandle ObjectFactory::NewAndCopySNameDictionary(JSHandle &srcElements, uint32_t length) { JSHandle dstElements = NewSDictionaryArray(length); if (length == 0) { return dstElements; } for (uint32_t i = 0; i < length; i++) { dstElements->Set(thread_, i, srcElements->Get(i)); } return dstElements; } JSHandle ObjectFactory::NewAndCopyJSArrayObject(JSHandle thisObjHandle, uint32_t newLength, uint32_t oldLength, uint32_t k) { ASSERT(oldLength <= newLength); JSHandle dstElements(NewTaggedArray(newLength)); JSHandle holeHandle(thread_, JSTaggedValue::Hole()); JSHandle arrayObj = JSHandle(NewJSStableArrayWithElements(dstElements)); if (newLength == 0) { return JSHandle(arrayObj); } for (uint32_t i = 0; i < oldLength; i++) { JSHandle value(thread_, ElementAccessor::Get(thisObjHandle, i + k)); ElementAccessor::Set(thread_, arrayObj, i, value, true); } for (uint32_t i = oldLength; i < newLength; i++) { ElementAccessor::Set(thread_, arrayObj, i, holeHandle, true); } return arrayObj; } JSHandle ObjectFactory::NewAndCopyTaggedArrayByObject(JSHandle thisObjHandle, uint32_t newLength, uint32_t oldLength, uint32_t k) { ASSERT(oldLength <= newLength); MemSpaceType spaceType = newLength < LENGTH_THRESHOLD ? MemSpaceType::SEMI_SPACE : MemSpaceType::OLD_SPACE; JSHandle dstElements(NewTaggedArrayWithoutInit(newLength, spaceType)); TaggedArray *srcElements = TaggedArray::Cast(thisObjHandle->GetElements().GetTaggedObject()); dstElements->SetExtraLength(srcElements->GetExtraLength()); if (newLength == 0) { return dstElements; } for (uint32_t i = 0; i < oldLength; i++) { dstElements->Set(thread_, i, ElementAccessor::Get(thisObjHandle, i + k)); } for (uint32_t i = oldLength; i < newLength; i++) { dstElements->Set(thread_, i, JSTaggedValue::Hole()); } return dstElements; } JSHandle ObjectFactory::NewAndCopyMutantTaggedArrayByObject(JSHandle thisObjHandle, uint32_t newLength, uint32_t oldLength, uint32_t k) { ASSERT(oldLength <= newLength); MemSpaceType spaceType = newLength < LENGTH_THRESHOLD ? MemSpaceType::SEMI_SPACE : MemSpaceType::OLD_SPACE; JSHandle dstElements(NewMutantTaggedArrayWithoutInit(newLength, spaceType)); MutantTaggedArray *srcElements = MutantTaggedArray::Cast(thisObjHandle->GetElements().GetTaggedObject()); dstElements->SetExtraLength(srcElements->GetExtraLength()); if (newLength == 0) { return dstElements; } for (uint32_t i = 0; i < oldLength; i++) { ElementsKind kind = thisObjHandle->GetClass()->GetElementsKind(); JSTaggedValue value = JSTaggedValue(ElementAccessor::ConvertTaggedValueWithElementsKind( ElementAccessor::Get(thisObjHandle, i + k), kind)); dstElements->Set(thread_, i, value); } for (uint32_t i = oldLength; i < newLength; i++) { ElementsKind kind = thisObjHandle->GetClass()->GetElementsKind(); JSTaggedValue value = JSTaggedValue(ElementAccessor::ConvertTaggedValueWithElementsKind(JSTaggedValue::Hole(), kind)); dstElements->Set(thread_, i, value); } return dstElements; } // private JSHandle ObjectFactory::NewTaggedArrayWithoutInit(uint32_t length, MemSpaceType spaceType) { NewObjectHook(); if (length == 0) { return EmptyArray(); } size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); TaggedObject *header = nullptr; auto arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()); switch (spaceType) { case MemSpaceType::SEMI_SPACE: header = heap_->AllocateYoungOrHugeObject(arrayClass, size); break; case MemSpaceType::OLD_SPACE: header = heap_->AllocateOldOrHugeObject(arrayClass, size); break; case MemSpaceType::SHARED_OLD_SPACE: header = sHeap_->AllocateOldOrHugeObject(thread_, arrayClass, size); break; default: LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); } JSHandle array(thread_, header); array->SetLength(length); return array; } // private JSHandle ObjectFactory::NewMutantTaggedArrayWithoutInit(uint32_t length, MemSpaceType spaceType) { NewObjectHook(); if (length == 0) { return EmptyMutantArray(); } size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); TaggedObject *header = nullptr; auto arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetMutantTaggedArrayClass().GetTaggedObject()); switch (spaceType) { case MemSpaceType::SEMI_SPACE: header = heap_->AllocateYoungOrHugeObject(arrayClass, size); break; case MemSpaceType::OLD_SPACE: header = heap_->AllocateOldOrHugeObject(arrayClass, size); break; default: LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); } JSHandle array(thread_, header); array->SetLength(length); return array; } JSHandle ObjectFactory::NewTaggedArray(uint32_t length, JSTaggedValue initVal) { NewObjectHook(); if (length == 0) { return EmptyArray(); } MemSpaceType spaceType = length < LENGTH_THRESHOLD ? MemSpaceType::SEMI_SPACE : MemSpaceType::OLD_SPACE; JSHandle array = NewTaggedArrayWithoutInit(length, spaceType); array->InitializeWithSpecialValue(initVal, length); return array; } JSHandle ObjectFactory::NewCOWTaggedArray(uint32_t length, JSTaggedValue initVal) { NewObjectHook(); ASSERT(length > 0); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); auto header = heap_->AllocateNonMovableOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetCOWArrayClass().GetTaggedObject()), size); JSHandle cowArray(thread_, header); cowArray->InitializeWithSpecialValue(initVal, length); return cowArray; } JSHandle ObjectFactory::NewCOWMutantTaggedArray(uint32_t length, JSTaggedType initVal) { NewObjectHook(); ASSERT(length > 0); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); auto header = heap_->AllocateNonMovableOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetCOWMutantTaggedArrayClass().GetTaggedObject()), size); JSHandle cowMutantTaggedArray(thread_, header); cowMutantTaggedArray->InitializeWithSpecialValue(initVal, length); return cowMutantTaggedArray; } JSHandle ObjectFactory::NewMutantTaggedArray(uint32_t length, JSTaggedType initVal) { NewObjectHook(); ASSERT(length > 0); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetMutantTaggedArrayClass().GetTaggedObject()), size); JSHandle mutantTaggedArray(thread_, header); mutantTaggedArray->InitializeWithSpecialValue(initVal, length); return mutantTaggedArray; } JSHandle ObjectFactory::NewTaggedHashArray(uint32_t length) { if (length == 0) { return JSHandle::Cast(EmptyArray()); } size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), size); JSHandle array(thread_, header); array->InitializeWithSpecialValue(JSTaggedValue::Hole(), length); return array; } JSHandle ObjectFactory::NewByteArray(uint32_t length, uint32_t size, void *srcData, MemSpaceType spaceType) { size_t byteSize = ByteArray::ComputeSize(size, length); JSHClass *arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetByteArrayClass().GetTaggedObject()); TaggedObject *header = AllocObjectWithSpaceType(byteSize, arrayClass, spaceType); JSHandle array(thread_, header); void *data = array->GetData(); if (srcData != nullptr) { if (memcpy_s(data, length * size, srcData, length * size) != EOK) { LOG_FULL(FATAL) << "memcpy_s failed"; UNREACHABLE(); } } else { if (memset_s(data, length * size, 0, length * size) != EOK) { LOG_FULL(FATAL) << "memset_s failed"; UNREACHABLE(); } } array->SetArrayLength(length); array->SetByteLength(size); return array; } JSHandle ObjectFactory::NewLinkedNode(int hash, const JSHandle &key, const JSHandle &value, const JSHandle &next) { NewObjectHook(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(globalConst->GetLinkedNode().GetTaggedObject()), LinkedNode::SIZE); JSHandle node(thread_, header); node->InitLinkedNode(thread_, hash, key, value, next); return node; } JSHandle ObjectFactory::NewTreeNode(int hash, const JSHandle &key, const JSHandle &value) { NewObjectHook(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(globalConst->GetRBTreeNode().GetTaggedObject()), RBTreeNode::SIZE); JSHandle treenode(thread_, header); treenode->InitRBTreeNode(thread_, hash, key, value, 1); return treenode; } JSHandle ObjectFactory::NewDictionaryArray(uint32_t length) { NewObjectHook(); ASSERT(length > 0); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetDictionaryClass().GetTaggedObject()), size); JSHandle array(thread_, header); array->InitializeWithSpecialValue(JSTaggedValue::Undefined(), length); return array; } JSHandle ObjectFactory::ExtendArray(const JSHandle &old, uint32_t length, JSTaggedValue initVal, MemSpaceType type, [[maybe_unused]] ElementsKind kind) { ASSERT(length >= old->GetLength()); NewObjectHook(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); JSHClass *arrayClass = nullptr; // If old element is Mutantarray, need conversion according to kind. if (old->GetClass()->IsMutantTaggedArray()) { arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetMutantTaggedArrayClass().GetTaggedObject()); } else { arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()); } TaggedObject *header = AllocObjectWithSpaceType(size, arrayClass, type); JSHandle newArray(thread_, header); newArray->SetLength(length); newArray->SetExtraLength(old->GetExtraLength()); uint32_t oldLength = old->GetLength(); for (uint32_t i = 0; i < oldLength; i++) { JSTaggedValue value = old->Get(i); if (old->GetClass()->IsMutantTaggedArray()) { newArray->Set(thread_, i, value); } else { newArray->Set(thread_, i, value); } } for (uint32_t i = oldLength; i < length; i++) { if (initVal.IsHole() && old->GetClass()->IsMutantTaggedArray()) { JSTaggedValue specialHole = JSTaggedValue(base::SPECIAL_HOLE); newArray->Set(thread_, i, specialHole); } else { newArray->Set(thread_, i, initVal); } } return newArray; } JSHandle ObjectFactory::CopyPartArray(const JSHandle &old, uint32_t start, uint32_t end) { ASSERT(start <= end); ASSERT(end <= old->GetLength()); uint32_t newLength = end - start; if (newLength == 0) { return EmptyArray(); } NewObjectHook(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), size); JSHandle newArray(thread_, header); newArray->InitializeWithSpecialValue(JSTaggedValue::Hole(), newLength, old->GetExtraLength()); for (uint32_t i = 0; i < newLength; i++) { JSTaggedValue value = old->Get(i + start); if (value.IsHole()) { break; } newArray->Set(thread_, i, value); } return newArray; } JSHandle ObjectFactory::CopyArray(const JSHandle &old, uint32_t oldLength, uint32_t newLength, JSTaggedValue initVal, MemSpaceType type, ElementsKind kind) { if (newLength == 0) { return EmptyArray(); } if (newLength > oldLength) { return ExtendArray(old, newLength, initVal, type, kind); } NewObjectHook(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength); TaggedObject *header = nullptr; if (type == MemSpaceType::NON_MOVABLE) { // COW array is shared in nonmovable space. JSHClass *cowArrayClass = nullptr; if (old->GetClass()->IsMutantTaggedArray()) { cowArrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetCOWMutantTaggedArrayClass() .GetTaggedObject()); } else { cowArrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetCOWArrayClass().GetTaggedObject()); } header = AllocObjectWithSpaceType(size, cowArrayClass, type); } else { JSHClass *arrayClass = nullptr; if (old->GetClass()->IsMutantTaggedArray()) { arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetMutantTaggedArrayClass().GetTaggedObject()); } else { arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()); } header = AllocObjectWithSpaceType(size, arrayClass, type); } JSHandle newArray(thread_, header); newArray->SetLength(newLength); newArray->SetExtraLength(old->GetExtraLength()); for (uint32_t i = 0; i < newLength; i++) { JSTaggedValue value = old->Get(i); if (old->GetClass()->IsMutantTaggedArray()) { newArray->Set(thread_, i, value); } else { newArray->Set(thread_, i, value); } } return newArray; } JSHandle ObjectFactory::CopyFromEnumCache(const JSHandle &old) { NewObjectHook(); uint32_t oldLength = old->GetLength(); uint32_t newLength = oldLength - EnumCache::ENUM_CACHE_HEADER_SIZE; size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), size); JSHandle newArray(thread_, header); newArray->SetLength(newLength); newArray->SetExtraLength(old->GetExtraLength()); for (uint32_t i = 0; i < newLength; i++) { JSTaggedValue value = old->Get(i + EnumCache::ENUM_CACHE_HEADER_SIZE); newArray->Set(thread_, i, value); } return newArray; } JSHandle ObjectFactory::CreateLayoutInfo(int properties, MemSpaceType type, GrowMode mode) { int growLength = mode == GrowMode::GROW ? static_cast(LayoutInfo::ComputeGrowCapacity(properties)) : properties; uint32_t arrayLength = LayoutInfo::ComputeArrayLength(growLength); JSHandle layoutInfoHandle = JSHandle::Cast(NewTaggedArrayWithoutInit(arrayLength, type)); layoutInfoHandle->Initialize(thread_); return layoutInfoHandle; } JSHandle ObjectFactory::ExtendLayoutInfo(const JSHandle &old, int properties) { ASSERT(properties >= old->NumberOfElements()); uint32_t arrayLength = LayoutInfo::ComputeArrayLength(LayoutInfo::ComputeGrowCapacity(properties)); ASSERT(arrayLength > old->GetLength()); auto oldArray = JSHandle(old); auto newArray = NewTaggedArrayWithoutInit(arrayLength, MemSpaceType::SEMI_SPACE); JSHandle::Cast(newArray)->Initialize(thread_, oldArray->GetExtraLength()); uint32_t oldLength = old->GetLength(); for (uint32_t i = 0; i < oldLength; i++) { JSTaggedValue value = oldArray->Get(i); newArray->Set(thread_, i, value); } return JSHandle::Cast(newArray); } JSHandle ObjectFactory::CopyLayoutInfo(const JSHandle &old) { uint32_t newLength = old->GetLength(); return JSHandle(CopyArray(JSHandle::Cast(old), newLength, newLength)); } JSHandle ObjectFactory::CopyAndReSort(const JSHandle &old, int end, int capacity) { ASSERT(capacity >= end); JSHandle newArr = CreateLayoutInfo(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::NewConstantPool(uint32_t capacity) { NewObjectHook(); size_t size = ConstantPool::ComputeSize(capacity); auto header = heap_->AllocateOldOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetConstantPoolClass().GetTaggedObject()), size); JSHandle array(thread_, header); array->InitializeWithSpecialValue(thread_, JSTaggedValue::Hole(), capacity); return array; } JSHandle ObjectFactory::NewProgram() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetProgramClass().GetTaggedObject())); JSHandle p(thread_, header); p->InitializeHash(); p->SetMainFunction(thread_, JSTaggedValue::Undefined()); return p; } JSHandle ObjectFactory::NewModuleNamespace() { NewObjectHook(); JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetModuleNamespaceClass()); JSHandle obj = NewJSObject(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::NewCjsModule() { NewObjectHook(); JSHandle env = vm_->GetGlobalEnv(); JSHandle moduleObj(env->GetCjsModuleFunction()); JSHandle cjsModule = JSHandle(NewJSObjectByConstructor(moduleObj)); return cjsModule; } JSHandle ObjectFactory::NewCjsExports() { NewObjectHook(); JSHandle env = vm_->GetGlobalEnv(); JSHandle exportsObj(env->GetCjsExportsFunction()); JSHandle cjsExports = JSHandle(NewJSObjectByConstructor(exportsObj)); return cjsExports; } JSHandle ObjectFactory::NewCjsRequire() { NewObjectHook(); JSHandle env = vm_->GetGlobalEnv(); JSHandle requireObj(env->GetCjsRequireFunction()); JSHandle cjsRequire = JSHandle(NewJSObjectByConstructor(requireObj)); return cjsRequire; } JSHandle ObjectFactory::GetEmptyString() const { return JSHandle(thread_->GlobalConstants()->GetHandledEmptyString()); } JSHandle ObjectFactory::EmptyArray() const { return JSHandle(thread_->GlobalConstants()->GetHandledEmptyArray()); } JSHandle ObjectFactory::EmptyMutantArray() const { return JSHandle(thread_->GlobalConstants()->GetHandledEmptyArray()); } JSHandle ObjectFactory::GetStringFromStringTable(const uint8_t *utf8Data, uint32_t utf8Len, bool canBeCompress) const { NewObjectHook(); if (utf8Len == 0) { return GetEmptyString(); } auto stringTable = vm_->GetEcmaStringTable(); return JSHandle(thread_, stringTable->GetOrInternString(vm_, utf8Data, utf8Len, canBeCompress)); } JSHandle ObjectFactory::GetCompressedSubStringFromStringTable(const JSHandle &string, uint32_t offset, uint32_t utf8Len) const { NewObjectHook(); if (UNLIKELY(utf8Len == 0)) { return GetEmptyString(); } auto *stringTable = vm_->GetEcmaStringTable(); return JSHandle(thread_, stringTable->GetOrInternCompressedSubString(vm_, string, offset, utf8Len)); } JSHandle ObjectFactory::GetStringFromStringTableNonMovable(const uint8_t *utf8Data, uint32_t utf8Len) const { NewObjectHook(); if (utf8Len == 0) { return GetEmptyString(); } auto stringTable = vm_->GetEcmaStringTable(); return JSHandle(thread_, stringTable->CreateAndInternStringNonMovable(vm_, utf8Data, utf8Len)); } JSHandle ObjectFactory::GetStringFromStringTableReadOnly(const uint8_t *utf8Data, uint32_t utf8Len) const { NewObjectHook(); if (utf8Len == 0) { return GetEmptyString(); } auto stringTable = vm_->GetEcmaStringTable(); return JSHandle(thread_, stringTable->CreateAndInternStringReadOnly(vm_, utf8Data, utf8Len)); } JSHandle ObjectFactory::GetStringFromStringTable(const uint16_t *utf16Data, uint32_t utf16Len, bool canBeCompress) const { NewObjectHook(); if (utf16Len == 0) { return GetEmptyString(); } auto stringTable = vm_->GetEcmaStringTable(); return JSHandle(thread_, stringTable->GetOrInternString(vm_, utf16Data, utf16Len, canBeCompress)); } JSHandle ObjectFactory::GetStringFromStringTable(EcmaString *string) const { ASSERT(string != nullptr); if (EcmaStringAccessor(string).GetLength() == 0) { return GetEmptyString(); } auto stringTable = vm_->GetEcmaStringTable(); return JSHandle(thread_, stringTable->GetOrInternString(vm_, string)); } // NB! don't do special case for C0 80, it means '\u0000', so don't convert to UTF-8 EcmaString *ObjectFactory::GetRawStringFromStringTable(StringData sd, MemSpaceType type, bool isConstantString, uint32_t idOffset) const { NewObjectHook(); uint32_t utf16Len = sd.utf16_length; if (UNLIKELY(utf16Len == 0)) { return *GetEmptyString(); } bool canBeCompressed = sd.is_ascii; const uint8_t *mutf8Data = sd.data; if (canBeCompressed) { // This branch will use constant string, which has a pointer at the string in the pandafile. return vm_->GetEcmaStringTable()->GetOrInternStringWithSpaceType(vm_, mutf8Data, utf16Len, true, type, isConstantString, idOffset); } return vm_->GetEcmaStringTable()->GetOrInternStringWithSpaceType(vm_, mutf8Data, utf16Len, type); } JSHandle ObjectFactory::NewPropertyBox(const JSHandle &value) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetPropertyBoxClass().GetTaggedObject())); JSHandle box(thread_, header); box->SetValue(thread_, value); return box; } JSHandle ObjectFactory::NewProtoChangeMarker() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetProtoChangeMarkerClass().GetTaggedObject())); JSHandle marker(thread_, header); marker->ClearBitField(); return marker; } JSHandle ObjectFactory::NewMarkerCell() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetMarkerCellClass().GetTaggedObject())); JSHandle marker(thread_, header); marker->ClearBitField(); return marker; } JSHandle ObjectFactory::NewProtoChangeDetails() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetProtoChangeDetailsClass().GetTaggedObject())); JSHandle protoInfo(thread_, header); protoInfo->SetChangeListener(thread_, JSTaggedValue::Undefined()); protoInfo->SetRegisterIndex(ProtoChangeDetails::UNREGISTERED); return protoInfo; } JSHandle ObjectFactory::NewProfileTypeInfo(uint32_t length) { NewObjectHook(); ASSERT(length > 0); size_t size = ProfileTypeInfo::ComputeSize(length); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetProfileTypeInfoClass().GetTaggedObject()), size); JSHandle array(thread_, header); array->InitializeWithSpecialValue(JSTaggedValue::Undefined(), length); if (vm_->IsEnableJit()) { uint16_t threshold = vm_->GetJSOptions().GetJitHotnessThreshold(); ASSERT(threshold != ProfileTypeInfo::JIT_DISABLE_FLAG); array->SetJitHotnessThreshold(threshold); threshold = vm_->GetJSOptions().GetOsrHotnessThreshold(); array->SetOsrHotnessThreshold(threshold); } return array; } JSHandle ObjectFactory::NewBigInt(uint32_t length) { NewObjectHook(); ASSERT(length > 0); size_t size = BigInt::ComputeSize(length); auto header = sHeap_->AllocateNonMovableOrHugeObject(thread_, JSHClass::Cast(thread_->GlobalConstants()->GetBigIntClass().GetTaggedObject()), size); JSHandle bigint(thread_, header); bigint->SetLength(length); bigint->SetSign(false); bigint->InitializationZero(); return bigint; } // static void ObjectFactory::NewObjectHook() const { CHECK_NO_HEAP_ALLOC; #ifndef NDEBUG if (vm_->GetJSOptions().EnableForceGC() && vm_->IsInitialized() && thread_->IsAllContextsInitialized()) { if (vm_->GetJSOptions().ForceFullGC()) { vm_->CollectGarbage(TriggerGCType::YOUNG_GC); vm_->CollectGarbage(TriggerGCType::OLD_GC); vm_->CollectGarbage(TriggerGCType::FULL_GC); } else { vm_->CollectGarbage(TriggerGCType::YOUNG_GC); vm_->CollectGarbage(TriggerGCType::OLD_GC); } } #endif } JSHandle ObjectFactory::NewTaggedQueue(uint32_t length) { uint32_t queueLength = TaggedQueue::QueueToArrayIndex(length); auto queue = JSHandle::Cast(NewTaggedArray(queueLength, JSTaggedValue::Hole())); queue->SetStart(thread_, JSTaggedValue(0)); // equal to 0 when add 1. queue->SetEnd(thread_, JSTaggedValue(0)); queue->SetCapacity(thread_, JSTaggedValue(length)); return queue; } JSHandle ObjectFactory::GetEmptyTaggedQueue() const { return JSHandle(thread_->GlobalConstants()->GetHandledEmptyTaggedQueue()); } JSHandle ObjectFactory::NewJSSetIterator(const JSHandle &set, IterationKind kind) { JSHandle env = vm_->GetGlobalEnv(); JSHandle protoValue = env->GetSharedSetIteratorPrototype(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle hclassHandle(globalConst->GetHandledJSSharedSetIteratorClass()); hclassHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedSet(thread_, set.GetTaggedValue()); iter->SetNextIndex(0); iter->SetIterationKind(kind); ASSERT(iter.GetTaggedValue().IsJSSharedSetIterator()); return iter; } JSHandle ObjectFactory::NewJSSetIterator(const JSHandle &set, IterationKind kind) { JSHandle env = vm_->GetGlobalEnv(); JSHandle protoValue = env->GetSetIteratorPrototype(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle hclassHandle(globalConst->GetHandledJSSetIteratorClass()); hclassHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedSet(thread_, set->GetLinkedSet()); iter->SetNextIndex(0); iter->SetIterationKind(kind); return iter; } JSHandle ObjectFactory::NewJSRegExpIterator(const JSHandle &matcher, const JSHandle &inputStr, bool global, bool fullUnicode) { JSHandle env = vm_->GetGlobalEnv(); JSHandle protoValue = env->GetRegExpIteratorPrototype(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle hclassHandle(globalConst->GetHandledJSRegExpIteratorClass()); hclassHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratingRegExp(thread_, matcher.GetTaggedValue()); iter->SetIteratedString(thread_, inputStr.GetTaggedValue()); iter->SetGlobal(global); iter->SetUnicode(fullUnicode); iter->SetDone(false); return iter; } JSHandle ObjectFactory::NewJSMapIterator(const JSHandle &map, IterationKind kind) { JSHandle env = vm_->GetGlobalEnv(); JSHandle protoValue = env->GetMapIteratorPrototype(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle hclassHandle(globalConst->GetHandledJSMapIteratorClass()); hclassHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedMap(thread_, map->GetLinkedMap()); iter->SetNextIndex(0); iter->SetIterationKind(kind); return iter; } JSHandle ObjectFactory::NewJSMapIterator(const JSHandle &map, IterationKind kind) { JSHandle env = vm_->GetGlobalEnv(); JSHandle protoValue = env->GetSharedMapIteratorPrototype(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle hclassHandle(globalConst->GetHandledJSSharedMapIteratorClass()); hclassHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedMap(thread_, map.GetTaggedValue()); iter->SetNextIndex(0); iter->SetIterationKind(kind); ASSERT(iter.GetTaggedValue().IsJSSharedMapIterator()); return iter; } JSHandle ObjectFactory::NewJSAPIHashMapIterator(const JSHandle &hashMap, IterationKind kind) { NewObjectHook(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle undefinedHandle = globalConst->GetHandledUndefined(); JSHandle proto(thread_, globalConst->GetHashMapIteratorPrototype()); JSHandle hclassHandle(globalConst->GetHandledJSAPIHashMapIteratorClass()); hclassHandle->SetPrototype(thread_, proto); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetCurrentNodeResult(thread_, undefinedHandle); iter->SetIteratedHashMap(thread_, hashMap); iter->SetNextIndex(0); iter->SetTaggedQueue(thread_, JSTaggedValue::Undefined()); JSHandle queue = NewTaggedQueue(0); iter->SetTaggedQueue(thread_, queue); iter->SetIterationKind(kind); return iter; } JSHandle ObjectFactory::NewJSAPIHashSetIterator(const JSHandle &hashSet, IterationKind kind) { NewObjectHook(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle undefinedHandle = globalConst->GetHandledUndefined(); JSHandle proto(thread_, globalConst->GetHashSetIteratorPrototype()); JSHandle hclassHandle(globalConst->GetHandledJSAPIHashSetIteratorClass()); hclassHandle->SetPrototype(thread_, proto); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetCurrentNodeResult(thread_, undefinedHandle); iter->SetIteratedHashSet(thread_, hashSet); iter->SetNextIndex(0); iter->SetTableIndex(0); iter->SetTaggedQueue(thread_, JSTaggedValue::Undefined()); JSHandle queue = NewTaggedQueue(0); iter->SetTaggedQueue(thread_, queue); iter->SetIterationKind(kind); return iter; } JSHandle ObjectFactory::NewJSArrayIterator(const JSHandle &array, IterationKind kind) { JSHandle env = vm_->GetGlobalEnv(); JSHandle protoValue = env->GetArrayIteratorPrototype(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle hclassHandle(globalConst->GetHandledJSArrayIteratorClass()); hclassHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedArray(thread_, array); iter->SetNextIndex(0); iter->SetIterationKind(kind); return iter; } JSHandle ObjectFactory::NewJSSharedArrayIterator(const JSHandle &array, IterationKind kind) { JSHandle env = vm_->GetGlobalEnv(); JSHandle protoValue = env->GetSharedArrayIteratorPrototype(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle hclassHandle(globalConst->GetHandledJSSharedArrayIteratorClass()); hclassHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedArray(thread_, array); iter->SetNextIndex(0); iter->SetIterationKind(kind); return iter; } JSHandle ObjectFactory::CreateJSPromiseReactionsFunction(MethodIndex idx) { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetPromiseReactionFunctionClass()); JSHandle reactionsFunction = JSHandle::Cast(NewJSObject(hclass)); reactionsFunction->SetPromise(thread_, JSTaggedValue::Hole()); reactionsFunction->SetAlreadyResolved(thread_, JSTaggedValue::Hole()); JSHandle function = JSHandle::Cast(reactionsFunction); JSFunction::InitializeJSFunction(thread_, function); reactionsFunction->SetMethod(thread_, vm_->GetMethodByIndex(idx)); JSFunction::SetFunctionLength(thread_, function, JSTaggedValue(1)); return reactionsFunction; } JSHandle ObjectFactory::CreateJSPromiseExecutorFunction() { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetPromiseExecutorFunctionClass()); JSHandle executorFunction = JSHandle::Cast(NewJSObject(hclass)); executorFunction->SetCapability(thread_, JSTaggedValue::Undefined()); JSHandle function = JSHandle::Cast(executorFunction); JSFunction::InitializeJSFunction(thread_, function); executorFunction->SetMethod( thread_, vm_->GetMethodByIndex(MethodIndex::BUILTINS_PROMISE_HANDLER_EXECUTOR)); JSFunction::SetFunctionLength(thread_, function, JSTaggedValue(FunctionLength::TWO)); return executorFunction; } JSHandle ObjectFactory::CreateJSAsyncModuleFulfilledFunction() { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetAsyncModuleFulfilledFunctionClass()); JSHandle fulfilledFunction = JSHandle::Cast(NewJSObject(hclass)); fulfilledFunction->SetModule(thread_, JSTaggedValue::Undefined()); JSHandle function = JSHandle::Cast(fulfilledFunction); JSFunction::InitializeJSFunction(thread_, function); fulfilledFunction->SetMethod( thread_, vm_->GetMethodByIndex(MethodIndex::BUILTINS_ASYNC_MODULE_FULFILLED_FUNCTION)); JSFunction::SetFunctionLength(thread_, function, JSTaggedValue(FunctionLength::ONE)); return fulfilledFunction; } JSHandle ObjectFactory::CreateJSAsyncModuleRejectedFunction() { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetAsyncModuleRejectedFunctionClass()); JSHandle rejectedFunction = JSHandle::Cast(NewJSObject(hclass)); rejectedFunction->SetModule(thread_, JSTaggedValue::Undefined()); JSHandle function = JSHandle::Cast(rejectedFunction); JSFunction::InitializeJSFunction(thread_, function); rejectedFunction->SetMethod( thread_, vm_->GetMethodByIndex(MethodIndex::BUILTINS_ASYNC_MODULE_REJECTED_FUNCTION)); JSFunction::SetFunctionLength(thread_, function, JSTaggedValue(FunctionLength::ONE)); return rejectedFunction; } JSHandle ObjectFactory::NewJSPromiseAllResolveElementFunction() { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetPromiseAllResolveElementFunctionClass()); JSHandle function = JSHandle::Cast(NewJSObject(hclass)); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(function)); function->SetMethod( thread_, vm_->GetMethodByIndex(MethodIndex::BUILTINS_PROMISE_HANDLER_RESOLVE_ELEMENT_FUNCTION)); function->SetIndex(thread_, JSTaggedValue::Undefined()); function->SetValues(thread_, JSTaggedValue::Undefined()); function->SetCapabilities(thread_, JSTaggedValue::Undefined()); function->SetRemainingElements(thread_, JSTaggedValue::Undefined()); function->SetAlreadyCalled(thread_, JSTaggedValue::Undefined()); JSFunction::SetFunctionLength(thread_, JSHandle::Cast(function), JSTaggedValue(1)); return function; } JSHandle ObjectFactory::NewJSPromiseAnyRejectElementFunction() { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetPromiseAnyRejectElementFunctionClass()); JSHandle function = JSHandle::Cast(NewJSObject(hclass)); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(function)); function->SetMethod( thread_, vm_->GetMethodByIndex(MethodIndex::BUILTINS_PROMISE_HANDLER_ANY_REJECT_ELEMENT_FUNCTION)); function->SetIndex(0); function->SetErrors(thread_, JSTaggedValue::Undefined()); function->SetCapability(thread_, JSTaggedValue::Undefined()); function->SetRemainingElements(thread_, JSTaggedValue::Undefined()); function->SetAlreadyCalled(thread_, JSTaggedValue::Undefined()); JSFunction::SetFunctionLength(thread_, JSHandle::Cast(function), JSTaggedValue(1)); return function; } JSHandle ObjectFactory::NewJSPromiseAllSettledResolveElementFunction() { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetPromiseAllSettledElementFunctionClass()); JSHandle function = JSHandle::Cast(NewJSObject(hclass)); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(function)); function->SetMethod(thread_, vm_->GetMethodByIndex(MethodIndex::BUILTINS_PROMISE_HANDLER_ALL_SETTLED_RESOLVE_ELEMENT_FUNCTION)); function->SetIndex(0); function->SetValues(thread_, JSTaggedValue::Undefined()); function->SetCapability(thread_, JSTaggedValue::Undefined()); function->SetRemainingElements(thread_, JSTaggedValue::Undefined()); function->SetAlreadyCalled(thread_, JSTaggedValue::Undefined()); JSFunction::SetFunctionLength(thread_, JSHandle::Cast(function), JSTaggedValue(1)); return function; } JSHandle ObjectFactory::NewJSPromiseAllSettledRejectElementFunction() { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetPromiseAllSettledElementFunctionClass()); JSHandle function = JSHandle::Cast(NewJSObject(hclass)); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(function)); function->SetMethod(thread_, vm_->GetMethodByIndex(MethodIndex::BUILTINS_PROMISE_HANDLER_ALL_SETTLED_REJECT_ELEMENT_FUNCTION)); function->SetIndex(0); function->SetValues(thread_, JSTaggedValue::Undefined()); function->SetCapability(thread_, JSTaggedValue::Undefined()); function->SetRemainingElements(thread_, JSTaggedValue::Undefined()); function->SetAlreadyCalled(thread_, JSTaggedValue::Undefined()); JSFunction::SetFunctionLength(thread_, JSHandle::Cast(function), JSTaggedValue(1)); return function; } JSHandle ObjectFactory::NewJSPromiseThenFinallyFunction() { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetPromiseFinallyFunctionClass()); JSHandle function = JSHandle::Cast(NewJSObject(hclass)); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(function)); function->SetMethod(thread_, vm_->GetMethodByIndex(MethodIndex::BUILTINS_PROMISE_HANDLER_THEN_FINALLY_FUNCTION)); function->SetConstructor(thread_, JSTaggedValue::Undefined()); function->SetOnFinally(thread_, JSTaggedValue::Undefined()); JSFunction::SetFunctionLength(thread_, JSHandle::Cast(function), JSTaggedValue(1)); return function; } JSHandle ObjectFactory::NewJSPromiseCatchFinallyFunction() { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetPromiseFinallyFunctionClass()); JSHandle function = JSHandle::Cast(NewJSObject(hclass)); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(function)); function->SetMethod(thread_, vm_->GetMethodByIndex(MethodIndex::BUILTINS_PROMISE_HANDLER_CATCH_FINALLY_FUNCTION)); function->SetConstructor(thread_, JSTaggedValue::Undefined()); function->SetOnFinally(thread_, JSTaggedValue::Undefined()); JSFunction::SetFunctionLength(thread_, JSHandle::Cast(function), JSTaggedValue(1)); return function; } JSHandle ObjectFactory::NewJSAsyGenResNextRetProRstFulfilledFtn() { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast( env->GetAsyncGeneratorResNextRetProRstFtnClass()); JSHandle function = JSHandle::Cast(NewJSObject(hclass)); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(function)); function->SetMethod(thread_, vm_->GetMethodByIndex(MethodIndex::BUILTINS_ASYNC_GENERATOR_NEXT_FULFILLED_FUNCTION)); function->SetAsyncGeneratorObject(thread_, JSTaggedValue::Undefined()); JSFunction::SetFunctionLength(thread_, JSHandle::Cast(function), JSTaggedValue(1)); return function; } JSHandle ObjectFactory::NewJSAsyncFromSyncIterUnwarpFunction() { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetAsyncFromSyncIterUnwarpClass()); JSHandle function = JSHandle::Cast(NewJSObject(hclass)); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(function)); JSTaggedValue debugVaule = vm_->GetMethodByIndex(MethodIndex::BUILTINS_ASYNC_FROM_SYNC_ITERATOR_FUNCTION); function->SetMethod(thread_, debugVaule); function->SetDone(thread_, JSTaggedValue::Undefined()); JSFunction::SetFunctionLength(thread_, JSHandle::Cast(function), JSTaggedValue(1)); return function; } JSHandle ObjectFactory::NewJSAsyGenResNextRetProRstRejectedFtn() { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast( env->GetAsyncGeneratorResNextRetProRstFtnClass()); JSHandle function = JSHandle::Cast(NewJSObject(hclass)); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(function)); function->SetMethod(thread_, vm_->GetMethodByIndex(MethodIndex::BUILTINS_ASYNC_GENERATOR_NEXT_REJECTED_FUNCTION)); function->SetAsyncGeneratorObject(thread_, JSTaggedValue::Undefined()); JSFunction::SetFunctionLength(thread_, JSHandle::Cast(function), JSTaggedValue(1)); return function; } JSHandle ObjectFactory::NewJSPromiseValueThunkFunction() { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetPromiseValueThunkOrThrowerFunctionClass()); JSHandle function = JSHandle::Cast(NewJSObject(hclass)); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(function)); function->SetMethod(thread_, vm_->GetMethodByIndex(MethodIndex::BUILTINS_PROMISE_HANDLER_VALUE_THUNK_FUNCTION)); function->SetResult(thread_, JSTaggedValue::Undefined()); JSFunction::SetFunctionLength(thread_, JSHandle::Cast(function), JSTaggedValue(0)); return function; } JSHandle ObjectFactory::NewJSPromiseThrowerFunction() { JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetPromiseValueThunkOrThrowerFunctionClass()); JSHandle function = JSHandle::Cast(NewJSObject(hclass)); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(function)); function->SetMethod(thread_, vm_->GetMethodByIndex(MethodIndex::BUILTINS_PROMISE_HANDLER_THROWER_FUNCTION)); function->SetResult(thread_, JSTaggedValue::Undefined()); JSFunction::SetFunctionLength(thread_, JSHandle::Cast(function), JSTaggedValue(0)); return function; } EcmaString *ObjectFactory::InternString(const JSHandle &key) { EcmaString *str = EcmaString::Cast(key->GetTaggedObject()); if (EcmaStringAccessor(str).IsInternString()) { return str; } EcmaStringTable *stringTable = vm_->GetEcmaStringTable(); return stringTable->GetOrInternString(vm_, str); } JSHandle ObjectFactory::NewTransitionHandler() { NewObjectHook(); TransitionHandler *handler = TransitionHandler::Cast(heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTransitionHandlerClass().GetTaggedObject()))); handler->SetHandlerInfo(thread_, JSTaggedValue::Undefined()); handler->SetTransitionHClass(thread_, JSTaggedValue::Undefined()); return JSHandle(thread_, handler); } JSHandle ObjectFactory::NewPrototypeHandler() { NewObjectHook(); PrototypeHandler *header = PrototypeHandler::Cast(heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetPrototypeHandlerClass().GetTaggedObject()))); JSHandle handler(thread_, header); handler->SetHandlerInfo(thread_, JSTaggedValue::Undefined()); handler->SetProtoCell(thread_, JSTaggedValue::Undefined()); handler->SetHolder(thread_, JSTaggedValue::Undefined()); handler->SetAccessorMethodId(0); return handler; } JSHandle ObjectFactory::NewTransWithProtoHandler() { NewObjectHook(); TransWithProtoHandler *header = TransWithProtoHandler::Cast(heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTransWithProtoHandlerClass().GetTaggedObject()))); JSHandle handler(thread_, header); handler->SetHandlerInfo(thread_, JSTaggedValue::Undefined()); handler->SetProtoCell(thread_, JSTaggedValue::Undefined()); handler->SetTransitionHClass(thread_, JSTaggedValue::Undefined()); return handler; } JSHandle ObjectFactory::NewStoreTSHandler() { NewObjectHook(); StoreTSHandler *header = StoreTSHandler::Cast(heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetStoreTSHandlerClass().GetTaggedObject()))); JSHandle handler(thread_, header); handler->SetHandlerInfo(thread_, JSTaggedValue::Undefined()); handler->SetProtoCell(thread_, JSTaggedValue::Undefined()); handler->SetHolder(thread_, JSTaggedValue::Undefined()); return handler; } JSHandle ObjectFactory::NewPromiseRecord() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetPromiseRecordClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetValue(thread_, JSTaggedValue::Undefined()); return obj; } JSHandle ObjectFactory::NewResolvingFunctionsRecord() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetPromiseResolvingFunctionsRecordClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetResolveFunction(thread_, JSTaggedValue::Undefined()); obj->SetRejectFunction(thread_, JSTaggedValue::Undefined()); return obj; } JSHandle ObjectFactory::CreateObjectClass(const JSHandle &properties, size_t length) { JSHandle env = vm_->GetGlobalEnv(); JSHandle proto = env->GetObjectFunctionPrototype(); uint32_t fieldOrder = 0; JSMutableHandle key(thread_, JSTaggedValue::Undefined()); JSHandle layoutInfoHandle = CreateLayoutInfo(length); while (fieldOrder < length) { key.Update(properties->Get(fieldOrder * 2)); // 2: Meaning to double ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key"); PropertyAttributes attributes = PropertyAttributes::Default(); if (properties->Get(fieldOrder * 2 + 1).IsAccessor()) { // 2: Meaning to double attributes.SetIsAccessor(true); } attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(fieldOrder); layoutInfoHandle->AddKey(thread_, fieldOrder, key.GetTaggedValue(), attributes); fieldOrder++; } ASSERT(fieldOrder <= PropertyAttributes::MAX_FAST_PROPS_CAPACITY); JSHandle objClass = NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, fieldOrder); objClass->SetPrototype(thread_, proto.GetTaggedValue()); { objClass->SetExtensible(true); objClass->SetLayout(thread_, layoutInfoHandle); objClass->SetNumberOfProps(fieldOrder); } return objClass; } JSHandle ObjectFactory::SetLayoutInObjHClass(const JSHandle &properties, size_t length, const JSHandle &objClass) { JSMutableHandle key(thread_, JSTaggedValue::Undefined()); JSHandle newObjHclass(objClass); for (size_t fieldOffset = 0; fieldOffset < length; fieldOffset++) { key.Update(properties->Get(fieldOffset * 2)); // 2 : pair of key and value ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key"); PropertyAttributes attributes = PropertyAttributes::Default(); if (properties->Get(fieldOffset * 2 + 1).IsAccessor()) { // 2: Meaning to double attributes.SetIsAccessor(true); } attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(fieldOffset); newObjHclass = JSHClass::SetPropertyOfObjHClass(thread_, newObjHclass, key, attributes); } return newObjHclass; } JSHandle ObjectFactory::CreateObjectLiteralRootHClass(size_t length) { JSHandle env = vm_->GetGlobalEnv(); JSHandle proto = env->GetObjectFunctionPrototype(); JSHandle hclass = NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, length); hclass->SetPrototype(thread_, proto.GetTaggedValue()); { hclass->SetNumberOfProps(0); hclass->SetExtensible(true); } return hclass; } JSHandle ObjectFactory::GetObjectLiteralRootHClass(size_t length) { JSHandle env = vm_->GetGlobalEnv(); JSHandle maybeCache = env->GetObjectLiteralHClassCache(); if (UNLIKELY(maybeCache->IsHole())) { JSHandle cacheArr = NewTaggedArray(MAX_LITERAL_HCLASS_CACHE_SIZE + 1); env->SetObjectLiteralHClassCache(thread_, cacheArr.GetTaggedValue()); JSHandle objHClass = CreateObjectLiteralRootHClass(length); cacheArr->Set(thread_, length, objHClass); return objHClass; } JSHandle hclassCacheArr = JSHandle::Cast(maybeCache); JSTaggedValue maybeHClass = hclassCacheArr->Get(length); if (UNLIKELY(maybeHClass.IsHole())) { JSHandle objHClass = CreateObjectLiteralRootHClass(length); hclassCacheArr->Set(thread_, length, objHClass); return objHClass; } return JSHandle(thread_, maybeHClass); } JSHandle ObjectFactory::GetObjectLiteralHClass(const JSHandle &properties, size_t length) { ASSERT(length <= PropertyAttributes::MAX_FAST_PROPS_CAPACITY); // 64 : If object literal gets too many properties, create hclass directly. if (length > MAX_LITERAL_HCLASS_CACHE_SIZE) { return CreateObjectClass(properties, length); } JSHandle rootHClass = GetObjectLiteralRootHClass(length); return SetLayoutInObjHClass(properties, length, rootHClass); } JSHandle ObjectFactory::NewOldSpaceObjLiteralByHClass(const JSHandle &hclass) { JSHandle obj = NewOldSpaceJSObject(hclass); InitializeJSObject(obj, hclass); return obj; } JSHandle ObjectFactory::NewEmptyJSObject(uint32_t inlinedProps) { JSHandle env = vm_->GetGlobalEnv(); JSHandle builtinObj(env->GetObjectFunction()); return NewJSObjectByConstructor(builtinObj, inlinedProps); } JSHandle ObjectFactory::CreateNullJSObject() { const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle nullValue = globalConst->GetHandledNull(); return OrdinaryNewJSObjectCreate(nullValue); } uintptr_t ObjectFactory::NewSpaceBySnapshotAllocator(size_t size) { NewObjectHook(); return heap_->AllocateSnapshotSpace(size); } JSHandle ObjectFactory::NewMachineCodeObject(size_t length, const MachineCodeDesc *desc, JSHandle &method) { NewObjectHook(); TaggedObject *obj = heap_->AllocateMachineCodeObject(JSHClass::Cast( thread_->GlobalConstants()->GetMachineCodeClass().GetTaggedObject()), length + MachineCode::SIZE); MachineCode *code = MachineCode::Cast(obj); if (code == nullptr) { LOG_FULL(FATAL) << "machine code cast failed"; UNREACHABLE(); } if (desc != nullptr) { code->SetData(desc, method, length); } JSHandle codeObj(thread_, code); return codeObj; } JSHandle ObjectFactory::NewClassInfoExtractor(JSHandle method) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->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; } // ----------------------------------- new TSType ---------------------------------------- JSHandle ObjectFactory::CreateTSObjLayoutInfo(int propNum, JSTaggedValue initVal) { uint32_t arrayLength = TSObjLayoutInfo::ComputeArrayLength(propNum); JSHandle tsPropInfoHandle = JSHandle::Cast(NewTaggedArray(arrayLength, initVal)); tsPropInfoHandle->SetNumOfProperties(thread_, 0); return tsPropInfoHandle; } JSHandle ObjectFactory::NewTSObjectType(uint32_t numOfKeys) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTSObjectTypeClass().GetTaggedObject())); JSHandle objectType(thread_, header); objectType->SetObjLayoutInfo(thread_, JSTaggedValue::Undefined()); objectType->SetIndexSigns(thread_, JSTaggedValue::Undefined()); objectType->SetGT(GlobalTSTypeRef::Default()); JSHandle tsPropInfo = CreateTSObjLayoutInfo(numOfKeys); objectType->SetObjLayoutInfo(thread_, tsPropInfo); return objectType; } JSHandle ObjectFactory::NewTSClassType() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTSClassTypeClass().GetTaggedObject())); JSHandle classType(thread_, header); classType->SetGT(GlobalTSTypeRef::Default()); classType->SetInstanceType(thread_, JSTaggedValue::Undefined()); classType->SetConstructorType(thread_, JSTaggedValue::Undefined()); classType->SetPrototypeType(thread_, JSTaggedValue::Undefined()); classType->SetName(thread_, JSTaggedValue::Undefined()); classType->SetIndexSigns(thread_, JSTaggedValue::Undefined()); classType->SetExtensionGT(GlobalTSTypeRef::Default()); classType->ClearBitField(); return classType; } JSHandle ObjectFactory::NewTSInterfaceType() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTSInterfaceTypeClass().GetTaggedObject())); JSHandle interfaceType(thread_, header); JSHandle extends = EmptyArray(); interfaceType->SetGT(GlobalTSTypeRef::Default()); interfaceType->SetExtends(thread_, extends); interfaceType->SetFields(thread_, JSTaggedValue::Undefined()); interfaceType->SetIndexSigns(thread_, JSTaggedValue::Undefined()); return interfaceType; } JSHandle ObjectFactory::NewTSUnionType(uint32_t length) { NewObjectHook(); ASSERT(length > 0); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTSUnionTypeClass().GetTaggedObject())); JSHandle unionType(thread_, header); unionType->SetGT(GlobalTSTypeRef::Default()); unionType->SetComponents(thread_, JSTaggedValue::Undefined()); JSHandle componentTypes = NewTaggedArray(length, JSTaggedValue::Undefined()); unionType->SetComponents(thread_, componentTypes); return unionType; } JSHandle ObjectFactory::NewTSClassInstanceType() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTSClassInstanceTypeClass().GetTaggedObject())); JSHandle classInstanceType(thread_, header); classInstanceType->SetGT(GlobalTSTypeRef::Default()); classInstanceType->SetClassGT(GlobalTSTypeRef::Default()); return classInstanceType; } JSHandle ObjectFactory::NewTSFunctionType(uint32_t length) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTSFunctionTypeClass().GetTaggedObject())); JSHandle functionType(thread_, header); functionType->SetGT(GlobalTSTypeRef::Default()); functionType->SetName(thread_, JSTaggedValue::Undefined()); functionType->SetParameterTypes(thread_, JSTaggedValue::Undefined()); functionType->SetReturnGT(GlobalTSTypeRef::Default()); functionType->SetThisGT(GlobalTSTypeRef::Default()); functionType->ClearBitField(); functionType->SetMethodOffset(0); JSHandle parameterTypes = NewTaggedArray(length, JSTaggedValue::Undefined()); functionType->SetParameterTypes(thread_, parameterTypes); return functionType; } JSHandle ObjectFactory::NewTSArrayType() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTSArrayTypeClass().GetTaggedObject())); JSHandle arrayType(thread_, header); arrayType->SetElementGT(GlobalTSTypeRef::Default()); return arrayType; } JSHandle ObjectFactory::NewTSTypeTable(uint32_t length) { NewObjectHook(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length + TSTypeTable::RESERVE_TABLE_LENGTH); JSHClass *arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()); auto header = heap_->AllocateOldOrHugeObject(arrayClass, size); JSHandle table(thread_, header); table->InitializeWithSpecialValue(JSTaggedValue::Undefined(), length + TSTypeTable::RESERVE_TABLE_LENGTH); table->SetNumberOfTypes(thread_); return table; } JSHandle ObjectFactory::NewTSModuleTable(uint32_t length) { NewObjectHook(); ASSERT(length > 0); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); JSHClass *arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()); auto header = heap_->AllocateYoungOrHugeObject(arrayClass, size); JSHandle array(thread_, header); array->InitializeWithSpecialValue(JSTaggedValue::Undefined(), length); array->SetNumberOfTSTypeTables(thread_, 0); return array; } JSHandle ObjectFactory::NewTSIteratorInstanceType() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTSIteratorInstanceTypeClass().GetTaggedObject())); JSHandle iteratorInstanceType(thread_, header); iteratorInstanceType->SetGT(GlobalTSTypeRef::Default()); iteratorInstanceType->SetKindGT(GlobalTSTypeRef::Default()); iteratorInstanceType->SetElementGT(GlobalTSTypeRef::Default()); return iteratorInstanceType; } JSHandle ObjectFactory::NewTSNamespaceType() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetTSNamespaceTypeClass().GetTaggedObject())); JSHandle namespaceType(thread_, header); namespaceType->SetPropertyType(thread_, JSTaggedValue::Undefined()); JSHandle tsPropInfo = CreateTSObjLayoutInfo(TSObjLayoutInfo::DEFAULT_CAPACITY); namespaceType->SetPropertyType(thread_, tsPropInfo); return namespaceType; } // ----------------------------------- new string ---------------------------------------- JSHandle ObjectFactory::NewFromASCII(std::string_view data) { auto utf8Data = reinterpret_cast(data.data()); ASSERT(EcmaStringAccessor::CanBeCompressed(utf8Data, data.length())); return GetStringFromStringTable(utf8Data, data.length(), true); } // At this situation, Create string directly without using a StringTable. JSHandle ObjectFactory::NewFromASCIISkippingStringTable(std::string_view data) { auto utf8Data = reinterpret_cast(data.data()); ASSERT(EcmaStringAccessor::CanBeCompressed(utf8Data, data.length())); EcmaString *str = EcmaStringAccessor::CreateFromUtf8(vm_, utf8Data, data.length(), true); return JSHandle(thread_, str); } JSHandle ObjectFactory::NewFromASCIINonMovable(std::string_view data) { auto utf8Data = reinterpret_cast(data.data()); ASSERT(EcmaStringAccessor::CanBeCompressed(utf8Data, data.length())); return GetStringFromStringTableNonMovable(utf8Data, data.length()); } JSHandle ObjectFactory::NewFromASCIIReadOnly(std::string_view data) { auto utf8Data = reinterpret_cast(data.data()); ASSERT(EcmaStringAccessor::CanBeCompressed(utf8Data, data.length())); return GetStringFromStringTableReadOnly(utf8Data, data.length()); } JSHandle ObjectFactory::NewFromUtf8(std::string_view data) { auto utf8Data = reinterpret_cast(data.data()); bool canBeCompress = EcmaStringAccessor::CanBeCompressed(utf8Data, data.length()); return GetStringFromStringTable(utf8Data, data.length(), canBeCompress); } JSHandle ObjectFactory::NewFromUtf16(std::u16string_view data) { uint32_t length = data.length(); auto utf16Data = reinterpret_cast(data.data()); bool canBeCompress = EcmaStringAccessor::CanBeCompressed(utf16Data, length); return GetStringFromStringTable(utf16Data, length, canBeCompress); } JSHandle ObjectFactory::NewFromStdString(const std::string &data) { auto utf8Data = reinterpret_cast(data.c_str()); bool canBeCompress = EcmaStringAccessor::CanBeCompressed(utf8Data, data.length()); return GetStringFromStringTable(utf8Data, data.size(), canBeCompress); } JSHandle ObjectFactory::NewFromUtf8(const uint8_t *utf8Data, uint32_t utf8Len) { bool canBeCompress = EcmaStringAccessor::CanBeCompressed(utf8Data, utf8Len); return GetStringFromStringTable(utf8Data, utf8Len, canBeCompress); } JSHandle ObjectFactory::NewFromUtf16(const uint16_t *utf16Data, uint32_t utf16Len) { bool canBeCompress = EcmaStringAccessor::CanBeCompressed(utf16Data, utf16Len); return GetStringFromStringTable(utf16Data, utf16Len, canBeCompress); } JSHandle ObjectFactory::NewFromUtf16Compress(const uint16_t *utf16Data, uint32_t utf16Len) { ASSERT(EcmaStringAccessor::CanBeCompressed(utf16Data, utf16Len)); return GetStringFromStringTable(utf16Data, utf16Len, true); } JSHandle ObjectFactory::NewFromUtf16NotCompress(const uint16_t *utf16Data, uint32_t utf16Len) { ASSERT(!EcmaStringAccessor::CanBeCompressed(utf16Data, utf16Len)); return GetStringFromStringTable(utf16Data, utf16Len, false); } JSHandle ObjectFactory::NewFromUtf8Literal(const uint8_t *utf8Data, uint32_t utf8Len) { NewObjectHook(); bool canBeCompress = EcmaStringAccessor::CanBeCompressed(utf8Data, utf8Len); return JSHandle(thread_, EcmaStringAccessor::CreateFromUtf8(vm_, utf8Data, utf8Len, canBeCompress)); } JSHandle ObjectFactory::NewFromUtf8LiteralCompress(const uint8_t *utf8Data, uint32_t utf8Len) { NewObjectHook(); ASSERT(EcmaStringAccessor::CanBeCompressed(utf8Data, utf8Len)); return JSHandle(thread_, EcmaStringAccessor::CreateFromUtf8(vm_, utf8Data, utf8Len, true)); } JSHandle ObjectFactory::NewFromUtf8LiteralCompressSubString(const JSHandle &string, uint32_t offset, uint32_t utf8Len) { NewObjectHook(); ASSERT(EcmaStringAccessor::CanBeCompressed(EcmaStringAccessor(string).GetDataUtf8() + offset, utf8Len)); return JSHandle(thread_, EcmaStringAccessor::CreateFromUtf8CompressedSubString(vm_, string, offset, utf8Len)); } JSHandle ObjectFactory::NewCompressedUtf8(const uint8_t *utf8Data, uint32_t utf8Len) { NewObjectHook(); ASSERT(EcmaStringAccessor::CanBeCompressed(utf8Data, utf8Len)); return GetStringFromStringTable(utf8Data, utf8Len, true); } JSHandle ObjectFactory::NewCompressedUtf8SubString(const JSHandle &string, uint32_t offset, uint32_t utf8Len) { NewObjectHook(); ASSERT(EcmaStringAccessor::CanBeCompressed(EcmaStringAccessor(string).GetDataUtf8() + offset, utf8Len)); return GetCompressedSubStringFromStringTable(string, offset, utf8Len); } JSHandle ObjectFactory::NewFromUtf16Literal(const uint16_t *utf16Data, uint32_t utf16Len) { NewObjectHook(); bool canBeCompress = EcmaStringAccessor::CanBeCompressed(utf16Data, utf16Len); return JSHandle(thread_, EcmaStringAccessor::CreateFromUtf16(vm_, utf16Data, utf16Len, canBeCompress)); } JSHandle ObjectFactory::NewFromUtf16LiteralCompress(const uint16_t *utf16Data, uint32_t utf16Len) { NewObjectHook(); ASSERT(EcmaStringAccessor::CanBeCompressed(utf16Data, utf16Len)); return JSHandle(thread_, EcmaStringAccessor::CreateFromUtf16(vm_, utf16Data, utf16Len, true)); } JSHandle ObjectFactory::NewFromUtf16LiteralNotCompress(const uint16_t *utf16Data, uint32_t utf16Len) { NewObjectHook(); ASSERT(!EcmaStringAccessor::CanBeCompressed(utf16Data, utf16Len)); return JSHandle(thread_, EcmaStringAccessor::CreateFromUtf16(vm_, utf16Data, utf16Len, false)); } JSHandle ObjectFactory::ConcatFromString(const JSHandle &firstString, const JSHandle &secondString) { if (EcmaStringAccessor(firstString).GetLength() == 0) { return secondString; } if (EcmaStringAccessor(secondString).GetLength() == 0) { return firstString; } return GetStringFromStringTable(firstString, secondString); } JSHandle ObjectFactory::GetStringFromStringTable(const JSHandle &firstString, const JSHandle &secondString) { auto stringTable = vm_->GetEcmaStringTable(); return JSHandle(thread_, stringTable->GetOrInternString(vm_, firstString, secondString)); } JSHandle ObjectFactory::NewJSAPIArrayList(uint32_t capacity) { NewObjectHook(); JSHandle builtinObj(thread_, thread_->GlobalConstants()->GetArrayListFunction()); JSHandle obj = JSHandle(NewJSObjectByConstructor(builtinObj)); ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory(); JSHandle elements = factory->NewTaggedArray(capacity); obj->SetElements(thread_, elements); return obj; } JSHandle ObjectFactory::NewJSAPIArrayListIterator(const JSHandle &arrayList) { NewObjectHook(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle protoValue(thread_, globalConst->GetArrayListIteratorPrototype()); JSHandle hclassHandle(globalConst->GetHandledJSAPIArrayListIteratorClass()); hclassHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedArrayList(thread_, arrayList); iter->SetNextIndex(0); return iter; } JSHandle ObjectFactory::NewJSAPILightWeightMapIterator( const JSHandle &obj, IterationKind kind) { NewObjectHook(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle protoValue(thread_, globalConst->GetLightWeightMapIteratorPrototype()); JSHandle hclassHandle(globalConst->GetHandledJSAPILightWeightMapIteratorClass()); hclassHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedLightWeightMap(thread_, obj); iter->SetNextIndex(0); iter->SetIterationKind(kind); return iter; } JSHandle ObjectFactory::NewJSAPILightWeightSetIterator( const JSHandle &obj, IterationKind kind) { NewObjectHook(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle protoValue(thread_, globalConst->GetLightWeightSetIteratorPrototype()); JSHandle hclassHandle(globalConst->GetHandledJSAPILightWeightSetIteratorClass()); hclassHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedLightWeightSet(thread_, obj); iter->SetNextIndex(0); iter->SetIterationKind(kind); return iter; } JSHandle ObjectFactory::NewJSAPIPlainArray(uint32_t capacity) { NewObjectHook(); JSHandle builtinObj(thread_, thread_->GlobalConstants()->GetPlainArrayFunction()); JSHandle obj = JSHandle(NewJSObjectByConstructor(builtinObj)); ObjectFactory *factory = thread_->GetEcmaVM()->GetFactory(); JSHandle keyArray = factory->NewTaggedArray(capacity); JSHandle valueArray = factory->NewTaggedArray(capacity); obj->SetKeys(thread_, keyArray); obj->SetValues(thread_, valueArray); return obj; } JSHandle ObjectFactory::NewJSAPIPlainArrayIterator(const JSHandle &plainarray, IterationKind kind) { NewObjectHook(); JSHandle protoValue(thread_, thread_->GlobalConstants()->GetPlainArrayIteratorPrototype()); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle hclassHandle(globalConst->GetHandledJSAPIPlainArrayIteratorClass()); hclassHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedPlainArray(thread_, plainarray); iter->SetNextIndex(0); iter->SetIterationKind(kind); return iter; } JSHandle ObjectFactory::NewJSAPIStackIterator(const JSHandle &stack) { NewObjectHook(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle protoValue(thread_, globalConst->GetStackIteratorPrototype()); JSHandle hclassHandle(globalConst->GetHandledJSAPIStackIteratorClass()); hclassHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedStack(thread_, stack); iter->SetNextIndex(0); return iter; } JSHandle ObjectFactory::CopyDeque(const JSHandle &old, uint32_t newLength, [[maybe_unused]] uint32_t oldLength, uint32_t first, uint32_t last) { NewObjectHook(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), size); JSHandle newArray(thread_, header); newArray->InitializeWithSpecialValue(JSTaggedValue::Hole(), newLength, old->GetExtraLength()); uint32_t curIndex = first; // newIndex use in new TaggedArray, 0 : New TaggedArray index uint32_t newIndex = 0; uint32_t oldCapacity = old->GetLength(); while (curIndex != last) { JSTaggedValue value = old->Get(curIndex); newArray->Set(thread_, newIndex, value); ASSERT(oldCapacity != 0); curIndex = (curIndex + 1) % oldCapacity; newIndex = newIndex + 1; } return newArray; } JSHandle ObjectFactory::NewJSAPIDequeIterator(const JSHandle &deque) { NewObjectHook(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle protoValue(thread_, globalConst->GetDequeIteratorPrototype()); JSHandle hclassHandle(globalConst->GetHandledJSAPIDequeIteratorClass()); hclassHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedDeque(thread_, deque); iter->SetNextIndex(deque->GetFirst()); return iter; } JSHandle ObjectFactory::CopyQueue(const JSHandle &old, uint32_t newLength, uint32_t front, uint32_t tail) { NewObjectHook(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), size); JSHandle newArray(thread_, header); newArray->InitializeWithSpecialValue(JSTaggedValue::Hole(), newLength, old->GetExtraLength()); uint32_t curIndex = front; // newIndex use in new TaggedArray, 0 : New TaggedArray index uint32_t newIndex = 0; uint32_t oldCapacity = old->GetLength(); while (curIndex != tail) { JSTaggedValue value = old->Get(curIndex); newArray->Set(thread_, newIndex, value); ASSERT(oldCapacity != 0); curIndex = (curIndex + 1) % oldCapacity; newIndex = newIndex + 1; } return newArray; } JSHandle ObjectFactory::NewJSAPIQueueIterator(const JSHandle &queue) { NewObjectHook(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle protoValue(thread_, globalConst->GetQueueIteratorPrototype()); JSHandle hclassHandle(globalConst->GetHandledJSAPIQueueIteratorClass()); hclassHandle->SetPrototype(thread_, protoValue); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedQueue(thread_, queue); // IteratedQueue iter->SetNextIndex(0); return iter; } JSHandle ObjectFactory::NewJSAPITreeMapIterator(const JSHandle &map, IterationKind kind) { NewObjectHook(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle proto(thread_, globalConst->GetTreeMapIteratorPrototype()); JSHandle hclassHandle(globalConst->GetHandledJSAPITreeMapIteratorClass()); hclassHandle->SetPrototype(thread_, proto); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedMap(thread_, map); iter->SetNextIndex(0); iter->SetEntries(thread_, JSTaggedValue::Hole()); iter->SetIterationKind(kind); return iter; } JSHandle ObjectFactory::NewJSAPITreeSetIterator(const JSHandle &set, IterationKind kind) { NewObjectHook(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle proto(thread_, globalConst->GetTreeSetIteratorPrototype()); JSHandle hclassHandle(globalConst->GetHandledJSAPITreeSetIteratorClass()); hclassHandle->SetPrototype(thread_, proto); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedSet(thread_, set); iter->SetNextIndex(0); iter->SetEntries(thread_, JSTaggedValue::Hole()); iter->SetIterationKind(kind); return iter; } JSHandle ObjectFactory::NewJSAPIVector(uint32_t capacity) { NewObjectHook(); JSHandle builtinObj(thread_, thread_->GlobalConstants()->GetVectorFunction()); JSHandle obj = JSHandle(NewJSObjectByConstructor(builtinObj)); JSHandle newVector = NewTaggedArray(capacity); obj->SetElements(thread_, newVector); return obj; } JSHandle ObjectFactory::NewJSAPIVectorIterator(const JSHandle &vector) { NewObjectHook(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle proto(thread_, globalConst->GetVectorIteratorPrototype()); JSHandle hclassHandle(globalConst->GetHandledJSAPIVectorIteratorClass()); hclassHandle->SetPrototype(thread_, proto); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedVector(thread_, vector); iter->SetNextIndex(0); return iter; } JSHandle ObjectFactory::NewJSAPILinkedListIterator(const JSHandle &linkedList) { NewObjectHook(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle proto(thread_, globalConst->GetLinkedListIteratorPrototype()); JSHandle hclassHandle(globalConst->GetHandledJSAPILinkedListIteratorClass()); hclassHandle->SetPrototype(thread_, proto); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedLinkedList(thread_, linkedList->GetDoubleList()); iter->SetNextIndex(0); const uint32_t linkedListElementStartIndex = 4; iter->SetDataIndex(linkedListElementStartIndex); return iter; } JSHandle ObjectFactory::NewJSAPIListIterator(const JSHandle &List) { NewObjectHook(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); JSHandle proto(thread_, globalConst->GetListIteratorPrototype()); JSHandle hclassHandle(globalConst->GetHandledJSAPIListIteratorClass()); hclassHandle->SetPrototype(thread_, proto); JSHandle iter(NewJSObject(hclassHandle)); iter->GetJSHClass()->SetExtensible(true); iter->SetIteratedList(thread_, List->GetSingleList()); iter->SetNextIndex(0); const uint32_t linkedListElementStartIndex = 4; iter->SetDataIndex(linkedListElementStartIndex); return iter; } JSHandle ObjectFactory::NewJSAPIList() { NewObjectHook(); JSHandle function(thread_, thread_->GlobalConstants()->GetListFunction()); return JSHandle::Cast(NewJSObjectByConstructor(function)); } JSHandle ObjectFactory::NewJSAPILinkedList() { NewObjectHook(); JSHandle function(thread_, thread_->GlobalConstants()->GetLinkedListFunction()); return JSHandle::Cast(NewJSObjectByConstructor(function)); } JSHandle ObjectFactory::NewImportEntry() { JSHandle defautValue = thread_->GlobalConstants()->GetHandledUndefined(); return NewImportEntry(defautValue, defautValue, defautValue, SharedTypes::UNSENDABLE_MODULE); } JSHandle ObjectFactory::NewImportEntry(const JSHandle &moduleRequest, const JSHandle &importName, const JSHandle &localName, SharedTypes sharedTypes) { if (sharedTypes == SharedTypes::SHARED_MODULE) { return NewSImportEntry(moduleRequest, importName, localName); } NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( 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::NewLocalExportEntry() { JSHandle defautValue = thread_->GlobalConstants()->GetHandledUndefined(); return NewLocalExportEntry(defautValue, defautValue, LocalExportEntry::LOCAL_DEFAULT_INDEX, SharedTypes::UNSENDABLE_MODULE); } JSHandle ObjectFactory::NewLocalExportEntry(const JSHandle &exportName, const JSHandle &localName, const uint32_t index, SharedTypes sharedTypes) { if (sharedTypes == SharedTypes::SHARED_MODULE) { return NewSLocalExportEntry(exportName, localName, index); } NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( 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::NewIndirectExportEntry() { JSHandle defautValue = thread_->GlobalConstants()->GetHandledUndefined(); return NewIndirectExportEntry(defautValue, defautValue, defautValue, SharedTypes::UNSENDABLE_MODULE); } JSHandle ObjectFactory::NewIndirectExportEntry(const JSHandle &exportName, const JSHandle &moduleRequest, const JSHandle &importName, SharedTypes sharedTypes) { if (sharedTypes == SharedTypes::SHARED_MODULE) { return NewSIndirectExportEntry(exportName, moduleRequest, importName); } NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( 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::NewStarExportEntry() { JSHandle defautValue = thread_->GlobalConstants()->GetHandledUndefined(); return NewStarExportEntry(defautValue, SharedTypes::UNSENDABLE_MODULE); } JSHandle ObjectFactory::NewStarExportEntry(const JSHandle &moduleRequest, SharedTypes sharedTypes) { if (sharedTypes == SharedTypes::SHARED_MODULE) { return NewSStarExportEntry(moduleRequest); } NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetStarExportEntryClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetModuleRequest(thread_, moduleRequest); return obj; } JSHandle ObjectFactory::NewSourceTextModule() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetSourceTextModuleClass().GetTaggedObject())); JSHandle obj(thread_, header); JSTaggedValue undefinedValue = thread_->GlobalConstants()->GetUndefined(); obj->SetEnvironment(thread_, undefinedValue); obj->SetNamespace(thread_, undefinedValue); obj->SetEcmaModuleFilename(thread_, undefinedValue); obj->SetEcmaModuleRecordName(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->SetSharedType(SharedTypes::UNSENDABLE_MODULE); return obj; } JSHandle ObjectFactory::NewResolvedBindingRecord() { JSHandle undefinedValue = thread_->GlobalConstants()->GetHandledUndefined(); JSHandle ecmaModule(undefinedValue); JSHandle bindingName(undefinedValue); return NewResolvedBindingRecord(ecmaModule, bindingName); } JSHandle ObjectFactory::NewResolvedBindingRecord(const JSHandle &module, const JSHandle &bindingName) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetResolvedBindingClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetModule(thread_, module); obj->SetBindingName(thread_, bindingName); return obj; } JSHandle ObjectFactory::NewResolvedIndexBindingRecord() { JSHandle undefinedValue = thread_->GlobalConstants()->GetHandledUndefined(); JSHandle ecmaModule(undefinedValue); int32_t index = 0; return NewResolvedIndexBindingRecord(ecmaModule, index); } JSHandle ObjectFactory::NewResolvedIndexBindingRecord(const JSHandle &module, int32_t index) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetResolvedIndexBindingClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetModule(thread_, module); obj->SetIndex(index); return obj; } JSHandle ObjectFactory::NewCellRecord() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetCellRecordClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetWeakRefTarget(thread_, JSTaggedValue::Undefined()); obj->SetHeldValue(thread_, JSTaggedValue::Undefined()); return obj; } JSHandle ObjectFactory::CreateIteratorResultInstanceClass(const JSHandle &env) { auto globalConst = thread_->GlobalConstants(); JSHandle proto = env->GetObjectFunctionPrototype(); JSHandle iterResultClass = NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, proto); uint32_t fieldOrder = 0; JSHandle layoutInfoHandle = CreateLayoutInfo(2); // 2 means two field { ASSERT(JSIterator::VALUE_INLINE_PROPERTY_INDEX == fieldOrder); PropertyAttributes attributes = PropertyAttributes::Default(); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(fieldOrder); layoutInfoHandle->AddKey(thread_, fieldOrder++, globalConst->GetValueString(), attributes); } { ASSERT(JSIterator::DONE_INLINE_PROPERTY_INDEX == fieldOrder); PropertyAttributes attributes = PropertyAttributes::Default(); attributes.SetIsInlinedProps(true); attributes.SetRepresentation(Representation::TAGGED); attributes.SetOffset(fieldOrder); layoutInfoHandle->AddKey(thread_, fieldOrder++, globalConst->GetDoneString(), attributes); } { iterResultClass->SetLayout(thread_, layoutInfoHandle); iterResultClass->SetNumberOfProps(fieldOrder); } return iterResultClass; } TaggedObject *ObjectFactory::NewOldSpaceObject(const JSHandle &hclass) { NewObjectHook(); TaggedObject *header = heap_->AllocateOldOrHugeObject(*hclass); uint32_t inobjPropCount = hclass->GetInlinedProperties(); if (inobjPropCount > 0) { InitializeExtraProperties(hclass, header, inobjPropCount); } return header; } JSHandle ObjectFactory::NewOldSpaceJSObject(const JSHandle &jshclass) { JSHandle obj(thread_, JSObject::Cast(NewOldSpaceObject(jshclass))); JSHandle emptyArray = EmptyArray(); obj->InitializeHash(); obj->SetElements(thread_, emptyArray); obj->SetProperties(thread_, emptyArray); return obj; } JSHandle ObjectFactory::NewOldSpaceTaggedArray(uint32_t length, JSTaggedValue initVal) { return NewTaggedArray(length, initVal, MemSpaceType::OLD_SPACE); } JSHandle ObjectFactory::NewJSStableArrayWithElements(const JSHandle &elements) { JSHandle cls(thread_, JSHandle::Cast(vm_->GetGlobalEnv()->GetArrayFunction())->GetProtoOrHClass()); JSHandle array = JSHandle::Cast(NewJSObject(cls)); array->SetElements(thread_, elements); array->SetLength(elements->GetLength()); array->SetTrackInfo(thread_, JSTaggedValue::Undefined()); auto accessor = thread_->GlobalConstants()->GetArrayLengthAccessor(); array->SetPropertyInlinedProps(thread_, JSArray::LENGTH_INLINE_PROPERTY_INDEX, accessor); return array; } JSHandle ObjectFactory::NewJSAsyncGeneratorFunction(const JSHandle &method) { NewObjectHook(); JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetAsyncGeneratorFunctionClass()); JSHandle asyncGeneratorFunc = JSHandle::Cast(NewJSObject(hclass)); JSFunction::InitializeJSFunction(thread_, asyncGeneratorFunc, FunctionKind::ASYNC_GENERATOR_FUNCTION); asyncGeneratorFunc->SetMethod(thread_, method); return asyncGeneratorFunc; } JSHandle ObjectFactory::NewAsyncGeneratorRequest() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetAsyncGeneratorRequestRecordClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetCompletion(thread_, JSTaggedValue::Undefined()); obj->SetCapability(thread_, JSTaggedValue::Undefined()); return obj; } JSHandle ObjectFactory::NewAsyncIteratorRecord(const JSHandle &itor, const JSHandle &next, bool done) { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetAsyncIteratorRecordClass().GetTaggedObject())); JSHandle obj(thread_, header); obj->SetIterator(thread_, itor.GetTaggedValue()); obj->SetNextMethod(thread_, next.GetTaggedValue()); obj->SetDone(done); return obj; } JSHandle ObjectFactory::NewAOTLiteralInfo(uint32_t length, JSTaggedValue initVal) { NewObjectHook(); size_t size = AOTLiteralInfo::ComputeSize(length); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetAOTLiteralInfoClass().GetTaggedObject()), size); JSHandle aotLiteralInfo(thread_, header); aotLiteralInfo->InitializeWithSpecialValue(initVal, length); return aotLiteralInfo; } JSHandle ObjectFactory::NewVTable(uint32_t length, JSTaggedValue initVal) { NewObjectHook(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length * VTable::TUPLE_SIZE); auto header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetVTableClass().GetTaggedObject()), size); JSHandle vtable(thread_, header); vtable->InitializeWithSpecialValue(initVal, length * VTable::TUPLE_SIZE); return vtable; } JSHandle ObjectFactory::NewClassLiteral() { NewObjectHook(); TaggedObject *header = heap_->AllocateYoungOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetClassLiteralClass().GetTaggedObject())); JSHandle emptyArray = EmptyArray(); JSHandle classLiteral(thread_, header); classLiteral->SetArray(thread_, emptyArray); classLiteral->SetIsAOTUsed(false); return classLiteral; } JSHandle ObjectFactory::NewJSFunction(const JSHandle &methodHandle) { JSHandle env = vm_->GetGlobalEnv(); FunctionKind kind = methodHandle->GetFunctionKind(); JSHandle hclass; switch (kind) { case FunctionKind::NORMAL_FUNCTION: case FunctionKind::BASE_CONSTRUCTOR: { hclass = JSHandle::Cast(env->GetFunctionClassWithProto()); break; } case FunctionKind::ARROW_FUNCTION: { hclass = JSHandle::Cast(env->GetFunctionClassWithoutProto()); break; } case FunctionKind::GENERATOR_FUNCTION: { hclass = JSHandle::Cast(env->GetGeneratorFunctionClass()); break; } case FunctionKind::CONCURRENT_FUNCTION: case FunctionKind::ASYNC_ARROW_FUNCTION: case FunctionKind::ASYNC_FUNCTION: { hclass = JSHandle::Cast(env->GetAsyncFunctionClass()); break; } case FunctionKind::ASYNC_GENERATOR_FUNCTION: { hclass = JSHandle::Cast(env->GetAsyncGeneratorFunctionClass()); break; } default: LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); } JSHandle jsfunc = NewJSFunctionByHClass(methodHandle, hclass); ASSERT_NO_ABRUPT_COMPLETION(thread_); return jsfunc; } JSHandle ObjectFactory::NewJSFunction(const JSHandle &methodHandle, const JSHandle &homeObject) { ASSERT(homeObject->IsECMAObject()); JSHandle env = vm_->GetGlobalEnv(); JSHandle hclass = JSHandle::Cast(env->GetFunctionClassWithoutProto()); JSHandle jsFunc = NewJSFunctionByHClass(methodHandle, hclass); jsFunc->SetHomeObject(thread_, homeObject); ASSERT_NO_ABRUPT_COMPLETION(thread_); return jsFunc; } JSHandle ObjectFactory::CreateJSObjectWithProperties(size_t propertyCount, const Local *keys, const PropertyDescriptor *descs) { if (propertyCount > MAX_LITERAL_HCLASS_CACHE_SIZE) { return CreateLargeJSObjectWithProperties(propertyCount, keys, descs); } // At least 4 inlined slot int inlineProps = std::max(static_cast(propertyCount), JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS); JSMutableHandle hclassHandle(thread_, GetObjectLiteralRootHClass(inlineProps)); for (size_t i = 0; i < propertyCount; ++i) { JSHandle key(JSNApiHelper::ToJSHandle(keys[i])); ASSERT(EcmaStringAccessor(key->GetTaggedObject()).IsInternString()); if (UNLIKELY(!JSTaggedValue::IsPureString(key.GetTaggedValue()))) { THROW_TYPE_ERROR_AND_RETURN(thread_, "property key must be string and can not convert into element index", JSHandle()); } PropertyAttributes attr(descs[i]); attr.SetIsInlinedProps(true); attr.SetOffset(i); hclassHandle.Update(JSHClass::SetPropertyOfObjHClass(thread_, hclassHandle, key, attr)); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, JSHandle()); } JSHandle object = NewJSObject(hclassHandle); for (size_t i = 0; i < propertyCount; ++i) { object->SetPropertyInlinedProps(thread_, i, descs[i].GetValue().GetTaggedValue()); } return JSHandle(object); } JSHandle ObjectFactory::CreateLargeJSObjectWithProperties(size_t propertyCount, const Local *keys, const PropertyDescriptor *descs) { ASSERT(propertyCount > MAX_LITERAL_HCLASS_CACHE_SIZE); if (UNLIKELY(propertyCount > PropertyAttributes::MAX_FAST_PROPS_CAPACITY)) { return CreateDictionaryJSObjectWithProperties(propertyCount, keys, descs); } JSHandle env = vm_->GetGlobalEnv(); JSHandle objFuncProto = env->GetObjectFunctionPrototype(); JSHandle hClassHandle = NewEcmaHClass(JSObject::SIZE, propertyCount, JSType::JS_OBJECT, objFuncProto); JSHandle layoutHandle = CreateLayoutInfo(propertyCount); JSHandle object = NewJSObject(hClassHandle); for (size_t i = 0; i < propertyCount; ++i) { JSHandle key(JSNApiHelper::ToJSHandle(keys[i])); ASSERT(EcmaStringAccessor(key->GetTaggedObject()).IsInternString()); if (UNLIKELY(!JSTaggedValue::IsPureString(key.GetTaggedValue()))) { THROW_TYPE_ERROR_AND_RETURN(thread_, "property key must be string and can not convert into element index", JSHandle()); } PropertyAttributes attr(descs[i]); attr.SetIsInlinedProps(true); attr.SetOffset(i); LayoutInfo *layout = LayoutInfo::Cast(layoutHandle.GetTaggedValue().GetTaggedObject()); layout->AddKey(thread_, i, key.GetTaggedValue(), attr); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, JSHandle()); object->SetPropertyInlinedProps(thread_, i, descs[i].GetValue().GetTaggedValue()); } hClassHandle->SetNumberOfProps(propertyCount); hClassHandle->SetLayout(thread_, layoutHandle); return JSHandle(object); } JSHandle ObjectFactory::CreateDictionaryJSObjectWithProperties(size_t propertyCount, const Local *keys, const PropertyDescriptor *descs) { ASSERT(propertyCount > PropertyAttributes::MAX_FAST_PROPS_CAPACITY); JSHandle env = vm_->GetGlobalEnv(); JSHandle objFuncProto = env->GetObjectFunctionPrototype(); JSHandle hClassHandle = NewEcmaHClass(JSObject::SIZE, 0, JSType::JS_OBJECT, objFuncProto); hClassHandle->SetNumberOfProps(0); hClassHandle->SetIsDictionaryMode(true); JSHandle object = NewJSObject(hClassHandle); JSMutableHandle dict( thread_, NameDictionary::Create(thread_, NameDictionary::ComputeHashTableSize(propertyCount))); for (size_t i = 0; i < propertyCount; ++i) { JSHandle key(JSNApiHelper::ToJSHandle(keys[i])); ASSERT(EcmaStringAccessor(key->GetTaggedObject()).IsInternString()); if (UNLIKELY(!JSTaggedValue::IsPureString(key.GetTaggedValue()))) { THROW_TYPE_ERROR_AND_RETURN(thread_, "property key must be string and can not convert into element index", JSHandle()); } PropertyAttributes attr(descs[i]); dict.Update(NameDictionary::PutIfAbsent(thread_, dict, key, descs[i].GetValue(), attr)); } if (UNLIKELY(dict->EntriesCount() != static_cast(propertyCount))) { THROW_TYPE_ERROR_AND_RETURN(thread_, "property keys can not duplicate", JSHandle()); } object->SetProperties(thread_, dict); return JSHandle(object); } JSHandle ObjectFactory::CreateJSObjectWithNamedProperties(size_t propertyCount, const char **keys, const Local *values) { if (propertyCount > MAX_LITERAL_HCLASS_CACHE_SIZE) { return CreateLargeJSObjectWithNamedProperties(propertyCount, keys, values); } // At least 4 inlined slot int inlineProps = std::max(static_cast(propertyCount), JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS); JSMutableHandle hclassHandle(thread_, GetObjectLiteralRootHClass(inlineProps)); for (size_t i = 0; i < propertyCount; ++i) { JSHandle key(NewFromUtf8(keys[i])); ASSERT(EcmaStringAccessor(key->GetTaggedObject()).IsInternString()); if (UNLIKELY(!JSTaggedValue::IsPureString(key.GetTaggedValue()))) { THROW_TYPE_ERROR_AND_RETURN(thread_, "property key must be string and can not convert into element index", JSHandle()); } PropertyAttributes attr(PropertyAttributes::GetDefaultAttributes()); attr.SetIsInlinedProps(true); attr.SetOffset(i); hclassHandle.Update(JSHClass::SetPropertyOfObjHClass(thread_, hclassHandle, key, attr)); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, JSHandle()); } JSHandle object = NewJSObject(hclassHandle); for (size_t i = 0; i < propertyCount; ++i) { object->SetPropertyInlinedProps(thread_, i, JSNApiHelper::ToJSHandle(values[i]).GetTaggedValue()); } return JSHandle(object); } JSHandle ObjectFactory::CreateLargeJSObjectWithNamedProperties(size_t propertyCount, const char **keys, const Local *values) { ASSERT(propertyCount > MAX_LITERAL_HCLASS_CACHE_SIZE); if (UNLIKELY(propertyCount > PropertyAttributes::MAX_FAST_PROPS_CAPACITY)) { return CreateDictionaryJSObjectWithNamedProperties(propertyCount, keys, values); } JSHandle env = vm_->GetGlobalEnv(); JSHandle objFuncProto = env->GetObjectFunctionPrototype(); JSHandle hClassHandle = NewEcmaHClass(JSObject::SIZE, propertyCount, JSType::JS_OBJECT, objFuncProto); JSHandle layoutHandle = CreateLayoutInfo(propertyCount); JSHandle object = NewJSObject(hClassHandle); for (size_t i = 0; i < propertyCount; ++i) { JSHandle key(NewFromUtf8(keys[i])); ASSERT(EcmaStringAccessor(key->GetTaggedObject()).IsInternString()); if (UNLIKELY(!JSTaggedValue::IsPureString(key.GetTaggedValue()))) { THROW_TYPE_ERROR_AND_RETURN(thread_, "property key must be string and can not convert into element index", JSHandle()); } PropertyAttributes attr(PropertyAttributes::GetDefaultAttributes()); attr.SetIsInlinedProps(true); attr.SetOffset(i); LayoutInfo *layout = LayoutInfo::Cast(layoutHandle.GetTaggedValue().GetTaggedObject()); layout->AddKey(thread_, i, key.GetTaggedValue(), attr); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread_, JSHandle()); object->SetPropertyInlinedProps(thread_, i, JSNApiHelper::ToJSHandle(values[i]).GetTaggedValue()); } hClassHandle->SetNumberOfProps(propertyCount); hClassHandle->SetLayout(thread_, layoutHandle); return JSHandle(object); } JSHandle ObjectFactory::CreateDictionaryJSObjectWithNamedProperties(size_t propertyCount, const char **keys, const Local *values) { ASSERT(propertyCount > PropertyAttributes::MAX_FAST_PROPS_CAPACITY); JSHandle env = vm_->GetGlobalEnv(); JSHandle objFuncProto = env->GetObjectFunctionPrototype(); JSHandle hClassHandle = NewEcmaHClass(JSObject::SIZE, 0, JSType::JS_OBJECT, objFuncProto); hClassHandle->SetNumberOfProps(0); hClassHandle->SetIsDictionaryMode(true); JSHandle object = NewJSObject(hClassHandle); JSMutableHandle dict( thread_, NameDictionary::Create(thread_, NameDictionary::ComputeHashTableSize(propertyCount))); for (size_t i = 0; i < propertyCount; ++i) { JSHandle key(NewFromUtf8(keys[i])); ASSERT(EcmaStringAccessor(key->GetTaggedObject()).IsInternString()); if (UNLIKELY(!JSTaggedValue::IsPureString(key.GetTaggedValue()))) { THROW_TYPE_ERROR_AND_RETURN(thread_, "property key must be string and can not convert into element index", JSHandle()); } PropertyAttributes attr(PropertyAttributes::GetDefaultAttributes()); dict.Update(NameDictionary::PutIfAbsent(thread_, dict, key, JSNApiHelper::ToJSHandle(values[i]), attr)); } if (UNLIKELY(dict->EntriesCount() != static_cast(propertyCount))) { THROW_TYPE_ERROR_AND_RETURN(thread_, "property keys can not duplicate", JSHandle()); } object->SetProperties(thread_, dict); return JSHandle(object); } void ObjectFactory::FillFreeMemoryRange(uintptr_t start, uintptr_t end) { ASSERT(start <= end); ASSERT(start % static_cast(MemAlignment::MEM_ALIGN_OBJECT) == 0); ASSERT(end % static_cast(MemAlignment::MEM_ALIGN_OBJECT) == 0); while (start < end) { Barriers::SetPrimitive(reinterpret_cast(start), 0, FREE_MEMMORY_ADDRESS_ZAM_VALUE); start += sizeof(JSTaggedType); } } // jit compile should not modify method which is shared // remove it when compiled code flag move to jsfunction JSHandle ObjectFactory::CloneMethodTemporaryForJIT(JSHandle method) { TaggedObject *header = nullptr; header = heap_->AllocateOldOrHugeObject( JSHClass::Cast(thread_->GlobalConstants()->GetMethodClass().GetTaggedObject())); JSHandle newmethod(thread_, header); newmethod->SetCallField(method->GetCallField()); newmethod->SetLiteralInfo(method->GetLiteralInfo()); newmethod->SetNativePointerOrBytecodeArray(method->GetNativePointerOrBytecodeArray()); newmethod->SetExtraLiteralInfo(method->GetExtraLiteralInfo()); newmethod->SetCodeEntryOrLiteral(method->GetCodeEntryOrLiteral()); newmethod->SetConstantPool(thread_, method->GetConstantPool()); return newmethod; } } // namespace panda::ecmascript