1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef ECMASCRIPT_OBJECT_FACTORY_INL_H
17 #define ECMASCRIPT_OBJECT_FACTORY_INL_H
18
19 #include "ecmascript/global_env_constants-inl.h"
20 #include "ecmascript/global_env_constants.h"
21 #include "ecmascript/js_hclass-inl.h"
22 #include "ecmascript/js_thread.h"
23 #include "ecmascript/lexical_env.h"
24 #include "ecmascript/mem/heap-inl.h"
25 #include "ecmascript/mem/barriers-inl.h"
26 #include "ecmascript/mem/space.h"
27 #include "ecmascript/object_factory.h"
28 #include "ecmascript/tagged_array-inl.h"
29
30 namespace panda::ecmascript {
AllocLineStringObjectNoGC(size_t size)31 EcmaString *ObjectFactory::AllocLineStringObjectNoGC(size_t size)
32 {
33 TaggedObject *object = nullptr;
34 if (thread_->IsEnableCMCGC()) {
35 object = sHeap_->AllocateOldOrHugeObjectNoGC(thread_, size);
36 } else {
37 if (size > g_maxRegularHeapObjectSize) {
38 object = reinterpret_cast<TaggedObject *>(sHeap_->GetHugeObjectSpace()->Allocate(thread_, size));
39 } else {
40 object = reinterpret_cast<TaggedObject *>(sHeap_->GetOldSpace()->TryAllocateAndExpand(thread_, size, true));
41 }
42 }
43 if (object == nullptr) {
44 LOG_ECMA(FATAL) << "Alloc size " << size << " bytes string fail";
45 UNREACHABLE();
46 }
47 return EcmaString::Cast(object);
48 }
49
AllocNonMovableLineStringObject(size_t size)50 EcmaString *ObjectFactory::AllocNonMovableLineStringObject(size_t size)
51 {
52 NewSObjectHook();
53 EcmaString* str = reinterpret_cast<EcmaString *>(sHeap_->AllocateNonMovableOrHugeObject(
54 thread_, JSHClass::Cast(thread_->GlobalConstants()->GetLineStringClass().GetTaggedObject()), size));
55 return str;
56 }
57
AllocLineStringObject(size_t size)58 EcmaString *ObjectFactory::AllocLineStringObject(size_t size)
59 {
60 NewSObjectHook();
61 EcmaString* str = reinterpret_cast<EcmaString *>(sHeap_->AllocateOldOrHugeObject(
62 thread_, JSHClass::Cast(thread_->GlobalConstants()->GetLineStringClass().GetTaggedObject()), size));
63 return str;
64 }
65
AllocOldSpaceLineStringObject(size_t size)66 EcmaString *ObjectFactory::AllocOldSpaceLineStringObject(size_t size)
67 {
68 NewSObjectHook();
69 EcmaString* str = reinterpret_cast<EcmaString *>(sHeap_->AllocateOldOrHugeObject(
70 thread_, JSHClass::Cast(thread_->GlobalConstants()->GetLineStringClass().GetTaggedObject()), size));
71 return str;
72 }
73
AllocReadOnlyLineStringObject(size_t size)74 EcmaString *ObjectFactory::AllocReadOnlyLineStringObject(size_t size)
75 {
76 NewSObjectHook();
77 EcmaString* str = reinterpret_cast<EcmaString *>(sHeap_->AllocateReadOnlyOrHugeObject(
78 thread_, JSHClass::Cast(thread_->GlobalConstants()->GetLineStringClass().GetTaggedObject()), size));
79 return str;
80 }
81
AllocSlicedStringObject(MemSpaceType type)82 EcmaString *ObjectFactory::AllocSlicedStringObject(MemSpaceType type)
83 {
84 ASSERT(IsSMemSpace(type));
85 NewSObjectHook();
86 EcmaString* str = reinterpret_cast<EcmaString *>(AllocObjectWithSpaceType(SlicedString::SIZE,
87 JSHClass::Cast(thread_->GlobalConstants()->GetSlicedStringClass().GetTaggedObject()), type));
88 return str;
89 }
90
AllocTreeStringObject()91 EcmaString *ObjectFactory::AllocTreeStringObject()
92 {
93 NewSObjectHook();
94 EcmaString* str = reinterpret_cast<EcmaString *>(sHeap_->AllocateOldOrHugeObject(
95 thread_, JSHClass::Cast(thread_->GlobalConstants()->GetTreeStringClass().GetTaggedObject()),
96 TreeString::SIZE));
97 return str;
98 }
99
NewJSNativePointer(void * externalPointer,const NativePointerCallback & callBack,void * data,bool nonMovable,size_t nativeBindingsize,Concurrent isConcurrent,NativeFlag flag)100 JSHandle<JSNativePointer> ObjectFactory::NewJSNativePointer(void *externalPointer,
101 const NativePointerCallback &callBack,
102 void *data,
103 bool nonMovable,
104 size_t nativeBindingsize,
105 Concurrent isConcurrent,
106 NativeFlag flag)
107 {
108 NewObjectHook();
109 TaggedObject *header;
110 auto jsNativePointerClass = JSHClass::Cast(thread_->GlobalConstants()->GetJSNativePointerClass().GetTaggedObject());
111 if (nonMovable) {
112 header = heap_->AllocateNonMovableOrHugeObject(jsNativePointerClass);
113 } else {
114 header = heap_->AllocateOldOrHugeObject(jsNativePointerClass);
115 }
116 JSHandle<JSNativePointer> obj(thread_, header);
117 obj->SetExternalPointer(externalPointer);
118 obj->SetDeleter(callBack);
119 obj->SetData(data);
120 uint32_t fixedNativeBindingsize = nativeBindingsize < UINT32_MAX ? nativeBindingsize
121 : UINT32_MAX;
122 obj->SetBindingSize(fixedNativeBindingsize);
123 obj->SetNativeFlag(flag);
124
125 heap_->IncreaseNativeBindingSize(fixedNativeBindingsize);
126 if (callBack != nullptr) {
127 vm_->PushToNativePointerList(static_cast<JSNativePointer *>(header), isConcurrent);
128 // In some cases, the size of JS/TS object is too small and the native binding size is too large.
129 // Check and try trigger concurrent mark here.
130 if (!g_isEnableCMCGC) {
131 heap_->TryTriggerFullMarkOrGCByNativeSize();
132 }
133 }
134 return obj;
135 }
136
InlineNewLexicalEnv(int numSlots)137 LexicalEnv *ObjectFactory::InlineNewLexicalEnv(int numSlots)
138 {
139 NewObjectHook();
140 size_t size = LexicalEnv::ComputeSize(numSlots);
141 auto header = heap_->TryAllocateYoungGeneration(
142 JSHClass::Cast(thread_->GlobalConstants()->GetLexicalEnvClass().GetTaggedObject()), size);
143 if (UNLIKELY(header == nullptr)) {
144 return nullptr;
145 }
146 LexicalEnv *array = LexicalEnv::Cast(header);
147 array->InitializeWithSpecialValue(JSTaggedValue::Hole(), numSlots + LexicalEnv::RESERVED_ENV_LENGTH);
148 return array;
149 }
150
151 template<typename T, typename S>
NewJSIntlIcuData(const JSHandle<T> & obj,const S & icu,const NativePointerCallback & callback)152 void ObjectFactory::NewJSIntlIcuData(const JSHandle<T> &obj, const S &icu, const NativePointerCallback &callback)
153 {
154 S *icuPoint = vm_->GetNativeAreaAllocator()->New<S>(icu);
155 ASSERT(icuPoint != nullptr);
156 JSTaggedValue data = obj->GetIcuField(vm_->GetJSThread());
157 if (data.IsHeapObject() && data.IsJSNativePointer()) {
158 JSNativePointer *native = JSNativePointer::Cast(data.GetTaggedObject());
159 native->ResetExternalPointer(thread_, icuPoint);
160 return;
161 }
162 JSHandle<JSNativePointer> pointer = NewJSNativePointer(icuPoint, callback, vm_);
163 obj->SetIcuField(thread_, pointer.GetTaggedValue());
164 }
165
AllocObjectWithSpaceType(size_t size,JSHClass * cls,MemSpaceType type)166 TaggedObject *ObjectFactory::AllocObjectWithSpaceType(size_t size, JSHClass *cls, MemSpaceType type)
167 {
168 switch (type) {
169 case MemSpaceType::SEMI_SPACE:
170 return heap_->AllocateYoungOrHugeObject(cls, size);
171 case MemSpaceType::OLD_SPACE:
172 return heap_->AllocateOldOrHugeObject(cls, size);
173 case MemSpaceType::NON_MOVABLE:
174 return heap_->AllocateNonMovableOrHugeObject(cls, size);
175 case MemSpaceType::SHARED_OLD_SPACE:
176 return sHeap_->AllocateOldOrHugeObject(thread_, cls, size);
177 case MemSpaceType::SHARED_NON_MOVABLE:
178 return sHeap_->AllocateNonMovableOrHugeObject(thread_, cls, size);
179 default:
180 LOG_ECMA(FATAL) << "this branch is unreachable";
181 UNREACHABLE();
182 }
183 }
184
185 template <MemSpaceType type>
NewBigIntWithoutInitData(uint32_t length)186 JSHandle<BigInt> ObjectFactory::NewBigIntWithoutInitData(uint32_t length)
187 {
188 NewObjectHook();
189 ASSERT(length > 0);
190 size_t size = BigInt::ComputeSize(length);
191 TaggedObject *header;
192 if (type == MemSpaceType::SHARED_READ_ONLY_SPACE) {
193 header = sHeap_->AllocateReadOnlyOrHugeObject(thread_,
194 JSHClass::Cast(thread_->GlobalConstants()->GetBigIntClass().GetTaggedObject()), size);
195 } else {
196 header = sHeap_->AllocateOldOrHugeObject(thread_,
197 JSHClass::Cast(thread_->GlobalConstants()->GetBigIntClass().GetTaggedObject()), size);
198 }
199 JSHandle<BigInt> bigint(thread_, header);
200 bigint->SetLength(length);
201 return bigint;
202 }
203
204 template <MemSpaceType type>
NewBigInt(uint32_t length)205 JSHandle<BigInt> ObjectFactory::NewBigInt(uint32_t length)
206 {
207 JSHandle<BigInt> bigint = NewBigIntWithoutInitData<type>(length);
208 bigint->InitializationZero();
209 bigint->SetSign(false);
210 return bigint;
211 }
212
213 template <MemSpaceType type>
NewSubBigInt(const JSHandle<BigInt> & x,uint32_t length)214 JSHandle<BigInt> ObjectFactory::NewSubBigInt(const JSHandle<BigInt>& x, uint32_t length)
215 {
216 JSHandle<BigInt> bigint = NewBigIntWithoutInitData<type>(length);
217 bigint->SetSign(x->GetSign());
218 ASSERT(x->GetLength() >= length);
219 std::copy(x->GetData(), x->GetData() + length, bigint->GetData());
220 return bigint;
221 }
222 } // namespace panda::ecmascript
223 #endif // ECMASCRIPT_OBJECT_FACTORY_INL_H
224