2024-01-24 14:28:54 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ecmascript/object_factory.h"
|
|
|
|
|
|
|
|
#include "ecmascript/accessor_data.h"
|
2024-01-24 01:29:37 +00:00
|
|
|
#include "ecmascript/compiler/aot_file/aot_file_manager.h"
|
2024-01-24 14:28:54 +00:00
|
|
|
#include "ecmascript/ecma_context.h"
|
|
|
|
#include "ecmascript/global_env_constants-inl.h"
|
|
|
|
#include "ecmascript/js_function.h"
|
|
|
|
#include "ecmascript/layout_info-inl.h"
|
|
|
|
#include "ecmascript/mem/heap-inl.h"
|
|
|
|
|
|
|
|
namespace panda::ecmascript {
|
|
|
|
JSHandle<JSHClass> ObjectFactory::CreateSFunctionClass(uint32_t size, JSType type,
|
|
|
|
const JSHandle<JSTaggedValue> &prototype, bool isAccessor)
|
|
|
|
{
|
2024-01-29 15:44:36 +00:00
|
|
|
const GlobalEnvConstants *globalConst = thread_->GlobalConstants();
|
2024-01-24 14:28:54 +00:00
|
|
|
uint32_t fieldOrder = 0;
|
|
|
|
ASSERT(JSFunction::LENGTH_INLINE_PROPERTY_INDEX == fieldOrder);
|
|
|
|
PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
|
|
|
|
attributes.SetIsAccessor(isAccessor);
|
|
|
|
attributes.SetIsInlinedProps(true);
|
|
|
|
attributes.SetRepresentation(Representation::TAGGED);
|
|
|
|
JSHandle<LayoutInfo> layoutInfoHandle = CreateSLayoutInfo(JSFunction::LENGTH_OF_INLINE_PROPERTIES);
|
|
|
|
{
|
|
|
|
attributes.SetOffset(fieldOrder);
|
|
|
|
layoutInfoHandle->AddKey(thread_, fieldOrder, globalConst->GetLengthString(), attributes);
|
|
|
|
fieldOrder++;
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT(JSFunction::NAME_INLINE_PROPERTY_INDEX == fieldOrder);
|
|
|
|
{
|
|
|
|
attributes.SetOffset(fieldOrder);
|
|
|
|
layoutInfoHandle->AddKey(thread_, fieldOrder,
|
|
|
|
globalConst->GetHandledNameString().GetTaggedValue(), attributes);
|
|
|
|
fieldOrder++;
|
|
|
|
}
|
|
|
|
JSHandle<JSHClass> functionClass = NewSEcmaHClass(size, fieldOrder, type, prototype,
|
|
|
|
JSHandle<JSTaggedValue>(layoutInfoHandle));
|
|
|
|
functionClass->SetCallable(true);
|
|
|
|
return functionClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<JSHClass> ObjectFactory::NewSEcmaHClass(uint32_t size, JSType type, uint32_t inlinedProps)
|
|
|
|
{
|
2024-01-29 15:44:36 +00:00
|
|
|
return NewSEcmaHClass(JSHClass::Cast(thread_->GlobalConstants()->GetHClassClass().GetTaggedObject()),
|
2024-01-24 14:28:54 +00:00
|
|
|
size, type, inlinedProps);
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<JSHClass> ObjectFactory::NewSEcmaHClass(JSHClass *hclass, uint32_t size, JSType type, uint32_t inlinedProps)
|
|
|
|
{
|
|
|
|
NewObjectHook();
|
|
|
|
uint32_t classSize = JSHClass::SIZE;
|
|
|
|
auto *newClass = static_cast<JSHClass *>(sHeap_->AllocateNonMovableOrHugeObject(thread_, hclass, classSize));
|
2024-01-29 15:44:36 +00:00
|
|
|
newClass->Initialize(thread_, size, type, inlinedProps, thread_->GlobalConstants()->GetHandledEmptySLayoutInfo());
|
2024-01-24 14:28:54 +00:00
|
|
|
return JSHandle<JSHClass>(thread_, newClass);
|
|
|
|
}
|
|
|
|
|
|
|
|
// This function don't UpdateProtoClass
|
|
|
|
JSHandle<JSHClass> ObjectFactory::NewSEcmaHClass(uint32_t size, uint32_t inlinedProps, JSType type,
|
|
|
|
const JSHandle<JSTaggedValue> &prototype, const JSHandle<JSTaggedValue> &layout)
|
|
|
|
{
|
|
|
|
NewObjectHook();
|
|
|
|
uint32_t classSize = JSHClass::SIZE;
|
|
|
|
auto *newClass = static_cast<JSHClass *>(sHeap_->AllocateNonMovableOrHugeObject(
|
2024-01-29 15:44:36 +00:00
|
|
|
thread_, JSHClass::Cast(thread_->GlobalConstants()->GetHClassClass().GetTaggedObject()), classSize));
|
2024-01-24 14:28:54 +00:00
|
|
|
newClass->Initialize(thread_, size, type, inlinedProps, layout);
|
|
|
|
JSHandle<JSHClass> hclass(thread_, newClass);
|
|
|
|
if (prototype->IsJSObject()) {
|
|
|
|
prototype->GetTaggedObject()->GetClass()->SetIsPrototype(true);
|
|
|
|
}
|
|
|
|
hclass->SetProto(thread_, prototype.GetTaggedValue());
|
|
|
|
hclass->SetExtensible(false);
|
|
|
|
hclass->SetNumberOfProps(inlinedProps);
|
|
|
|
return hclass;
|
|
|
|
}
|
|
|
|
|
2024-01-29 15:44:36 +00:00
|
|
|
JSHandle<JSHClass> ObjectFactory::NewSEcmaHClassClass(JSHClass *hclass, uint32_t size, JSType type)
|
|
|
|
{
|
|
|
|
NewObjectHook();
|
|
|
|
uint32_t classSize = JSHClass::SIZE;
|
|
|
|
auto *newClass = static_cast<JSHClass *>(sHeap_->AllocateClassClass(hclass, classSize));
|
|
|
|
newClass->Initialize(thread_, size, type, 0, thread_->GlobalConstants()->GetHandledEmptySLayoutInfo());
|
|
|
|
return JSHandle<JSHClass>(thread_, newClass);
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<JSHClass> ObjectFactory::NewSEcmaReadOnlyHClass(JSHClass *hclass, uint32_t size, JSType type,
|
|
|
|
uint32_t inlinedProps)
|
|
|
|
{
|
|
|
|
NewObjectHook();
|
|
|
|
uint32_t classSize = JSHClass::SIZE;
|
|
|
|
auto *newClass = static_cast<JSHClass *>(sHeap_->AllocateReadOnlyOrHugeObject(thread_, hclass, classSize));
|
|
|
|
newClass->Initialize(thread_, size, type, inlinedProps, thread_->GlobalConstants()->GetHandledEmptySLayoutInfo());
|
|
|
|
return JSHandle<JSHClass>(thread_, newClass);
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<JSHClass> ObjectFactory::InitSClassClass()
|
|
|
|
{
|
|
|
|
JSHandle<JSHClass> hClassHandle = NewSEcmaHClassClass(nullptr, JSHClass::SIZE, JSType::HCLASS);
|
|
|
|
JSHClass *hclass = reinterpret_cast<JSHClass *>(hClassHandle.GetTaggedValue().GetTaggedObject());
|
|
|
|
hclass->SetClass(thread_, hclass);
|
|
|
|
return hClassHandle;
|
|
|
|
}
|
|
|
|
|
2024-01-24 14:28:54 +00:00
|
|
|
JSHandle<AccessorData> ObjectFactory::NewSAccessorData()
|
|
|
|
{
|
|
|
|
NewObjectHook();
|
|
|
|
TaggedObject *header = sHeap_->AllocateOldOrHugeObject(
|
2024-01-29 15:44:36 +00:00
|
|
|
thread_, JSHClass::Cast(thread_->GlobalConstants()->GetAccessorDataClass().GetTaggedObject()));
|
2024-01-24 14:28:54 +00:00
|
|
|
JSHandle<AccessorData> acc(thread_, AccessorData::Cast(header));
|
|
|
|
acc->SetGetter(thread_, JSTaggedValue::Undefined());
|
|
|
|
acc->SetSetter(thread_, JSTaggedValue::Undefined());
|
|
|
|
return acc;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<Method> ObjectFactory::NewSMethod(const JSPandaFile *jsPandaFile, MethodLiteral *methodLiteral,
|
|
|
|
JSHandle<ConstantPool> constpool, JSHandle<JSTaggedValue> module)
|
|
|
|
{
|
|
|
|
JSHandle<Method> method;
|
|
|
|
if (jsPandaFile->IsNewVersion()) {
|
|
|
|
method = Method::Create(thread_, jsPandaFile, methodLiteral, true);
|
|
|
|
} else {
|
|
|
|
method = NewSMethod(methodLiteral);
|
|
|
|
method->SetConstantPool(thread_, constpool);
|
|
|
|
}
|
|
|
|
if (method->GetModule().IsUndefined()) {
|
|
|
|
method->SetModule(thread_, module);
|
|
|
|
}
|
|
|
|
return method;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<Method> ObjectFactory::NewSMethod(const MethodLiteral *methodLiteral, MemSpaceType spaceType)
|
|
|
|
{
|
|
|
|
ASSERT(spaceType == SHARED_NON_MOVABLE || spaceType == SHARED_OLD_SPACE);
|
|
|
|
NewObjectHook();
|
|
|
|
TaggedObject *header = nullptr;
|
|
|
|
if (spaceType == SHARED_NON_MOVABLE) {
|
|
|
|
header = sHeap_->AllocateNonMovableOrHugeObject(thread_,
|
2024-01-29 15:44:36 +00:00
|
|
|
JSHClass::Cast(thread_->GlobalConstants()->GetMethodClass().GetTaggedObject()));
|
2024-01-24 14:28:54 +00:00
|
|
|
} else {
|
|
|
|
header = sHeap_->AllocateOldOrHugeObject(thread_,
|
2024-01-29 15:44:36 +00:00
|
|
|
JSHClass::Cast(thread_->GlobalConstants()->GetMethodClass().GetTaggedObject()));
|
2024-01-24 14:28:54 +00:00
|
|
|
}
|
|
|
|
JSHandle<Method> method(thread_, header);
|
|
|
|
InitializeMethod(methodLiteral, method);
|
|
|
|
return method;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<Method> ObjectFactory::NewSMethodForNativeFunction(const void *func, FunctionKind kind,
|
|
|
|
kungfu::BuiltinsStubCSigns::ID builtinId,
|
|
|
|
MemSpaceType spaceType)
|
|
|
|
{
|
|
|
|
uint32_t numArgs = 2; // function object and this
|
|
|
|
auto method = NewSMethod(nullptr, spaceType);
|
|
|
|
method->SetNativePointer(const_cast<void *>(func));
|
|
|
|
method->SetNativeBit(true);
|
|
|
|
if (builtinId != kungfu::BuiltinsStubCSigns::INVALID) {
|
|
|
|
bool isFast = kungfu::BuiltinsStubCSigns::IsFastBuiltin(builtinId);
|
|
|
|
method->SetFastBuiltinBit(isFast);
|
|
|
|
method->SetBuiltinId(static_cast<uint8_t>(builtinId));
|
|
|
|
}
|
|
|
|
method->SetNumArgsWithCallField(numArgs);
|
|
|
|
method->SetFunctionKind(kind);
|
|
|
|
return method;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<JSFunction> ObjectFactory::NewSFunctionByHClass(const JSHandle<Method> &method,
|
|
|
|
const JSHandle<JSHClass> &hclass)
|
|
|
|
{
|
|
|
|
JSHandle<JSFunction> function(NewSharedOldSpaceJSObject(hclass));
|
|
|
|
hclass->SetCallable(true);
|
|
|
|
JSFunction::InitializeSFunction(thread_, function, method->GetFunctionKind());
|
|
|
|
function->SetMethod(thread_, method);
|
2024-01-24 01:29:37 +00:00
|
|
|
if (method->IsAotWithCallField()) {
|
|
|
|
thread_->GetCurrentEcmaContext()->GetAOTFileManager()->
|
|
|
|
SetAOTFuncEntry(method->GetJSPandaFile(), *function, *method);
|
|
|
|
}
|
2024-01-24 14:28:54 +00:00
|
|
|
return function;
|
|
|
|
}
|
|
|
|
|
|
|
|
// new function with name/length accessor
|
|
|
|
JSHandle<JSFunction> ObjectFactory::NewSFunctionWithAccessor(const void *func, const JSHandle<JSHClass> &hclass,
|
|
|
|
FunctionKind kind, kungfu::BuiltinsStubCSigns::ID builtinId, MemSpaceType spaceType)
|
|
|
|
{
|
|
|
|
ASSERT(spaceType == SHARED_NON_MOVABLE || spaceType == SHARED_OLD_SPACE);
|
|
|
|
JSHandle<Method> method = NewSMethodForNativeFunction(func, kind, builtinId, spaceType);
|
|
|
|
return NewSFunctionByHClass(method, hclass);
|
|
|
|
}
|
|
|
|
|
|
|
|
// new function without name/length accessor
|
|
|
|
JSHandle<JSFunction> ObjectFactory::NewSFunctionByHClass(const void *func, const JSHandle<JSHClass> &hclass,
|
|
|
|
FunctionKind kind, kungfu::BuiltinsStubCSigns::ID builtinId, MemSpaceType spaceType)
|
|
|
|
{
|
|
|
|
ASSERT(spaceType == SHARED_NON_MOVABLE || spaceType == SHARED_OLD_SPACE);
|
|
|
|
JSHandle<Method> method = NewSMethodForNativeFunction(func, kind, builtinId, spaceType);
|
|
|
|
JSHandle<JSFunction> function(NewSharedOldSpaceJSObject(hclass));
|
|
|
|
hclass->SetCallable(true);
|
|
|
|
JSFunction::InitializeWithDefaultValue(thread_, function);
|
|
|
|
function->SetMethod(thread_, method);
|
|
|
|
return function;
|
|
|
|
}
|
|
|
|
|
|
|
|
TaggedObject *ObjectFactory::NewSharedOldSpaceObject(const JSHandle<JSHClass> &hclass)
|
|
|
|
{
|
|
|
|
NewObjectHook();
|
|
|
|
TaggedObject *header = sHeap_->AllocateOldOrHugeObject(thread_, *hclass);
|
|
|
|
uint32_t inobjPropCount = hclass->GetInlinedProperties();
|
|
|
|
if (inobjPropCount > 0) {
|
|
|
|
InitializeExtraProperties(hclass, header, inobjPropCount);
|
|
|
|
}
|
|
|
|
return header;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<JSObject> ObjectFactory::NewSharedOldSpaceJSObject(const JSHandle<JSHClass> &jshclass)
|
|
|
|
{
|
|
|
|
JSHandle<JSObject> obj(thread_, JSObject::Cast(NewSharedOldSpaceObject(jshclass)));
|
|
|
|
JSHandle<TaggedArray> emptyArray = SharedEmptyArray();
|
|
|
|
obj->InitializeHash();
|
|
|
|
obj->SetElements(thread_, emptyArray);
|
|
|
|
obj->SetProperties(thread_, emptyArray);
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<TaggedArray> ObjectFactory::SharedEmptyArray() const
|
|
|
|
{
|
2024-01-29 15:44:36 +00:00
|
|
|
return JSHandle<TaggedArray>(thread_->GlobalConstants()->GetHandledEmptyArray());
|
2024-01-24 14:28:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<TaggedArray> ObjectFactory::NewSTaggedArrayWithoutInit(uint32_t length)
|
|
|
|
{
|
|
|
|
NewObjectHook();
|
|
|
|
size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length);
|
2024-01-29 15:44:36 +00:00
|
|
|
auto arrayClass = JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject());
|
2024-01-24 14:28:54 +00:00
|
|
|
TaggedObject *header = sHeap_->AllocateOldOrHugeObject(thread_, arrayClass, size);
|
|
|
|
JSHandle<TaggedArray> array(thread_, header);
|
|
|
|
array->SetLength(length);
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<LayoutInfo> ObjectFactory::CreateSLayoutInfo(uint32_t properties)
|
|
|
|
{
|
|
|
|
uint32_t arrayLength = LayoutInfo::ComputeArrayLength(properties);
|
|
|
|
JSHandle<LayoutInfo> layoutInfoHandle = JSHandle<LayoutInfo>::Cast(NewSTaggedArrayWithoutInit(arrayLength));
|
|
|
|
layoutInfoHandle->Initialize(thread_);
|
|
|
|
return layoutInfoHandle;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<LayoutInfo> ObjectFactory::CopyAndReSortSLayoutInfo(const JSHandle<LayoutInfo> &old, int end, int capacity)
|
|
|
|
{
|
|
|
|
ASSERT(capacity >= end);
|
|
|
|
JSHandle<LayoutInfo> newArr = CreateSLayoutInfo(capacity);
|
|
|
|
Span<struct Properties> 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<TaggedArray> ObjectFactory::NewSDictionaryArray(uint32_t length)
|
|
|
|
{
|
|
|
|
NewObjectHook();
|
|
|
|
ASSERT(length > 0);
|
|
|
|
size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length);
|
|
|
|
auto header = sHeap_->AllocateOldOrHugeObject(
|
2024-01-29 15:44:36 +00:00
|
|
|
thread_, JSHClass::Cast(thread_->GlobalConstants()->GetDictionaryClass().GetTaggedObject()), size);
|
2024-01-24 14:28:54 +00:00
|
|
|
JSHandle<TaggedArray> array(thread_, header);
|
|
|
|
array->InitializeWithSpecialValue(JSTaggedValue::Undefined(), length);
|
|
|
|
return array;
|
|
|
|
}
|
2024-02-07 02:16:42 +00:00
|
|
|
|
|
|
|
JSHandle<TaggedArray> ObjectFactory::NewSEmptyArray()
|
|
|
|
{
|
|
|
|
NewObjectHook();
|
|
|
|
auto header = sHeap_->AllocateReadOnlyOrHugeObject(thread_,
|
|
|
|
JSHClass::Cast(thread_->GlobalConstants()->GetArrayClass().GetTaggedObject()), TaggedArray::SIZE);
|
|
|
|
JSHandle<TaggedArray> array(thread_, header);
|
|
|
|
array->SetLength(0);
|
|
|
|
array->SetExtraLength(0);
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<MutantTaggedArray> ObjectFactory::NewSEmptyMutantArray()
|
|
|
|
{
|
|
|
|
NewObjectHook();
|
|
|
|
auto header = sHeap_->AllocateReadOnlyOrHugeObject(thread_,
|
|
|
|
JSHClass::Cast(thread_->GlobalConstants()->GetMutantTaggedArrayClass().GetTaggedObject()), TaggedArray::SIZE);
|
|
|
|
JSHandle<MutantTaggedArray> array(thread_, header);
|
|
|
|
array->SetLength(0);
|
|
|
|
array->SetExtraLength(0);
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<JSNativePointer> ObjectFactory::NewSJSNativePointer(void *externalPointer,
|
|
|
|
void *data,
|
|
|
|
bool nonMovable,
|
|
|
|
size_t nativeBindingsize,
|
|
|
|
NativeFlag flag)
|
|
|
|
{
|
|
|
|
NewObjectHook();
|
|
|
|
TaggedObject *header;
|
|
|
|
auto jsNativePointerClass = JSHClass::Cast(thread_->GlobalConstants()->GetJSNativePointerClass().GetTaggedObject());
|
|
|
|
if (nonMovable) {
|
|
|
|
header = sHeap_->AllocateNonMovableOrHugeObject(thread_, jsNativePointerClass);
|
|
|
|
} else {
|
|
|
|
header = sHeap_->AllocateOldOrHugeObject(thread_, jsNativePointerClass);
|
|
|
|
}
|
|
|
|
JSHandle<JSNativePointer> obj(thread_, header);
|
|
|
|
obj->SetExternalPointer(externalPointer);
|
|
|
|
obj->SetDeleter(nullptr);
|
|
|
|
obj->SetData(data);
|
|
|
|
obj->SetBindingSize(nativeBindingsize);
|
|
|
|
obj->SetNativeFlag(flag);
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSHandle<AccessorData> ObjectFactory::NewSInternalAccessor(void *setter, void *getter)
|
|
|
|
{
|
|
|
|
NewObjectHook();
|
|
|
|
TaggedObject *header = sHeap_->AllocateNonMovableOrHugeObject(thread_,
|
|
|
|
JSHClass::Cast(thread_->GlobalConstants()->GetInternalAccessorClass().GetTaggedObject()));
|
|
|
|
JSHandle<AccessorData> obj(thread_, AccessorData::Cast(header));
|
|
|
|
obj->SetGetter(thread_, JSTaggedValue::Undefined());
|
|
|
|
obj->SetSetter(thread_, JSTaggedValue::Undefined());
|
|
|
|
if (setter != nullptr) {
|
|
|
|
JSHandle<JSNativePointer> setFunc = NewSJSNativePointer(setter, nullptr, true);
|
|
|
|
obj->SetSetter(thread_, setFunc.GetTaggedValue());
|
|
|
|
}
|
|
|
|
if (getter != nullptr) {
|
|
|
|
JSHandle<JSNativePointer> getFunc = NewSJSNativePointer(getter, nullptr, true);
|
|
|
|
obj->SetGetter(thread_, getFunc);
|
|
|
|
}
|
|
|
|
return obj;
|
|
|
|
}
|
2024-01-24 14:28:54 +00:00
|
|
|
} // namespace panda::ecmascript
|