1 /*
2 * Copyright (c) 2023-2024 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 #include "ecmascript/builtins/builtins.h"
17
18 #include "ecmascript/builtins/builtins_function.h"
19 #include "ecmascript/builtins/builtins_object.h"
20 #include "ecmascript/builtins/builtins_symbol.h"
21 #include "ecmascript/builtins/builtins_sendable_arraybuffer.h"
22 #include "ecmascript/builtins/builtins_shared_async_function.h"
23 #include "ecmascript/builtins/builtins_shared_function.h"
24 #include "ecmascript/builtins/builtins_shared_object.h"
25 #include "ecmascript/builtins/builtins_shared_map.h"
26 #include "ecmascript/builtins/builtins_shared_set.h"
27 #include "ecmascript/builtins/builtins_shared_typedarray.h"
28 #include "ecmascript/containers/containers_bitvector.h"
29 #include "ecmascript/containers/containers_private.h"
30 #include "ecmascript/js_api/js_api_bitvector.h"
31 #include "ecmascript/shared_objects/js_shared_array.h"
32 #include "ecmascript/shared_objects/js_sendable_arraybuffer.h"
33 #include "ecmascript/shared_objects/js_shared_map.h"
34 #include "ecmascript/shared_objects/js_shared_set.h"
35 #include "ecmascript/shared_objects/js_shared_typed_array.h"
36 #include "ecmascript/js_async_function.h"
37 #include "ecmascript/js_object-inl.h"
38 #include "ecmascript/symbol_table.h"
39 #include "ecmascript/builtins/builtins_shared_array.h"
40
41 namespace panda::ecmascript {
42 using BuiltinsSharedObject = builtins::BuiltinsSharedObject;
43 using BuiltinsSharedFunction = builtins::BuiltinsSharedFunction;
44 using BuiltinsSharedAsyncFunction = builtins::BuiltinsSharedAsyncFunction;
45 using Function = builtins::BuiltinsFunction;
46 using Object = builtins::BuiltinsObject;
47 using BuiltinsSharedSet = builtins::BuiltinsSharedSet;
48 using BuiltinsSharedMap = builtins::BuiltinsSharedMap;
49 using BuiltinsSharedArray = builtins::BuiltinsSharedArray;
50 using BuiltinsSharedTypedArray = builtins::BuiltinsSharedTypedArray;
51 using BuiltinsSendableArrayBuffer = builtins::BuiltinsSendableArrayBuffer;
52 using ContainersBitVector = containers::ContainersBitVector;
53
InitializeSObjectAndSFunction(const JSHandle<GlobalEnv> & env) const54 void Builtins::InitializeSObjectAndSFunction(const JSHandle<GlobalEnv> &env) const
55 {
56 [[maybe_unused]] EcmaHandleScope scope(thread_);
57 // SharedObject.prototype[hclass]
58 JSHandle<JSHClass> sobjPrototypeHClass = CreateSObjectPrototypeHClass();
59 // SharedObject.prototype
60 JSHandle<JSObject> sObjPrototype =
61 factory_->NewSharedOldSpaceJSObject(sobjPrototypeHClass);
62 JSHandle<JSTaggedValue> sObjPrototypeVal(sObjPrototype);
63 // SharedObject.prototype_or_hclass
64 auto emptySLayout = thread_->GlobalConstants()->GetHandledEmptySLayoutInfo();
65 JSHandle<JSHClass> sObjIHClass =
66 factory_->NewSEcmaHClass(JSSharedObject::SIZE, 0, JSType::JS_SHARED_OBJECT, sObjPrototypeVal,
67 emptySLayout);
68 // SharedFunction.prototype_or_hclass
69 JSHandle<JSHClass> sFuncPrototypeHClass = CreateSFunctionPrototypeHClass(sObjPrototypeVal);
70 // SharedFunction.prototype
71 JSHandle<JSFunction> sFuncPrototype = factory_->NewSFunctionByHClass(
72 reinterpret_cast<void *>(Function::FunctionPrototypeInvokeSelf), sFuncPrototypeHClass,
73 FunctionKind::NORMAL_FUNCTION);
74 InitializeSFunction(env, sFuncPrototype);
75 InitializeSAsyncFunction(env, sObjIHClass);
76 InitializeSObject(env, sObjIHClass, sObjPrototype, sFuncPrototype);
77 InitializeSSet(env, sObjPrototype, sFuncPrototype);
78 InitializeSMap(env, sObjPrototype, sFuncPrototype);
79 InitializeSharedArray(env, sObjPrototype, sFuncPrototype);
80 InitializeSTypedArray(env, sObjPrototype, sFuncPrototype);
81 InitializeSArrayBuffer(env, sObjPrototype, sFuncPrototype);
82 InitializeSModuleNamespace(env, sObjIHClass);
83 env->SetSObjectFunctionPrototype(thread_, sObjPrototype);
84 }
85
CopySObjectAndSFunction(const JSHandle<GlobalEnv> & env,const JSTaggedValue & srcEnv) const86 void Builtins::CopySObjectAndSFunction(const JSHandle<GlobalEnv> &env, const JSTaggedValue &srcEnv) const
87 {
88 // Copy shareds.
89 ASSERT(srcEnv.IsJSGlobalEnv());
90 auto sGlobalEnv = reinterpret_cast<GlobalEnv*>(srcEnv.GetTaggedObject());
91 #define COPY_ENV_SHARED_FIELDS(Type, Name, INDEX) \
92 env->Set##Name(thread_, sGlobalEnv->Get##Name());
93 GLOBAL_ENV_SHARED_FIELDS(COPY_ENV_SHARED_FIELDS)
94 #undef COPY_ENV_SHARED_FIELDS
95 }
96
InitializeSObject(const JSHandle<GlobalEnv> & env,const JSHandle<JSHClass> & sObjIHClass,const JSHandle<JSObject> & sObjPrototype,const JSHandle<JSFunction> & sFuncPrototype) const97 void Builtins::InitializeSObject(const JSHandle<GlobalEnv> &env, const JSHandle<JSHClass> &sObjIHClass,
98 const JSHandle<JSObject> &sObjPrototype,
99 const JSHandle<JSFunction> &sFuncPrototype) const
100 {
101 [[maybe_unused]] EcmaHandleScope scope(thread_);
102 // SharedObject constructor (forbidden use NewBuiltinConstructor)
103 JSHandle<JSHClass> sObjectFunctionHClass = CreateSObjectFunctionHClass(sFuncPrototype);
104 JSHandle<JSFunction> sObjectFunction =
105 factory_->NewSFunctionByHClass(reinterpret_cast<void *>(BuiltinsSharedObject::SharedObjectConstructor),
106 sObjectFunctionHClass, FunctionKind::BUILTIN_CONSTRUCTOR);
107
108 InitializeSCtor(sObjIHClass, sObjectFunction, "SharedObject", FunctionLength::ONE);
109 env->SetSObjectFunction(thread_, sObjectFunction);
110 // sObject method.
111 uint32_t fieldIndex = JSFunction::PROTOTYPE_INLINE_PROPERTY_INDEX + 1;
112 for (const base::BuiltinFunctionEntry &entry : Object::GetObjectFunctions()) {
113 SetSFunction(env, JSHandle<JSObject>(sObjectFunction), entry.GetName(), entry.GetEntrypoint(),
114 fieldIndex++, entry.GetLength(), entry.GetBuiltinStubId());
115 }
116 // sObject.prototype method
117 fieldIndex = 0; // constructor
118 sObjPrototype->SetPropertyInlinedProps(thread_, fieldIndex++, sObjectFunction.GetTaggedValue());
119 for (const base::BuiltinFunctionEntry &entry : Object::GetObjectPrototypeFunctions()) {
120 SetSFunction(env, sObjPrototype, entry.GetName(), entry.GetEntrypoint(), fieldIndex++, entry.GetLength(),
121 entry.GetBuiltinStubId());
122 }
123 // B.2.2.1 sObject.prototype.__proto__
124 JSHandle<JSTaggedValue> protoGetter =
125 CreateSGetterSetter(env, Object::ProtoGetter, "__proto__", FunctionLength::ZERO);
126 JSHandle<JSTaggedValue> protoSetter =
127 CreateSGetterSetter(env, Object::ProtoSetter, "__proto__", FunctionLength::ONE);
128 SetSAccessor(sObjPrototype, fieldIndex, protoGetter, protoSetter);
129 }
130
InitializeSArrayBuffer(const JSHandle<GlobalEnv> & env,const JSHandle<JSObject> & sObjPrototype,const JSHandle<JSFunction> & sFuncPrototype) const131 void Builtins::InitializeSArrayBuffer(const JSHandle<GlobalEnv> &env, const JSHandle<JSObject> &sObjPrototype,
132 const JSHandle<JSFunction> &sFuncPrototype) const
133 {
134 [[maybe_unused]] EcmaHandleScope scope(thread_);
135 const GlobalEnvConstants *globalConst = thread_->GlobalConstants();
136 // SendableArrayBuffer.prototype
137 JSHandle<JSHClass> arrayBufferPrototypeHClass = CreateSArrayBufferPrototypeHClass(sObjPrototype);
138 JSHandle<JSObject> arrayBufferPrototype =
139 factory_->NewSharedOldSpaceJSObjectWithInit(arrayBufferPrototypeHClass);
140
141 JSHandle<JSTaggedValue> arrayBufferPrototypeValue(arrayBufferPrototype);
142
143 // SendableArrayBuffer.prototype_or_hclass
144 auto emptySLayout = globalConst->GetHandledEmptySLayoutInfo();
145 JSHandle<JSHClass> arrayBufferIHClass = factory_->NewSEcmaHClass(
146 JSSendableArrayBuffer::SIZE, 0, JSType::JS_SENDABLE_ARRAY_BUFFER, arrayBufferPrototypeValue, emptySLayout);
147
148 // SendableArrayBuffer = new Function()
149 JSHandle<JSHClass> arrayBufferFuncHClass = CreateSArrayBufferFunctionHClass(sFuncPrototype);
150
151 JSHandle<JSFunction> arrayBufferFunction =
152 factory_->NewSFunctionByHClass(reinterpret_cast<void *>(BuiltinsSendableArrayBuffer::ArrayBufferConstructor),
153 arrayBufferFuncHClass, FunctionKind::BUILTIN_CONSTRUCTOR);
154
155 InitializeSCtor(arrayBufferIHClass, arrayBufferFunction, "SendableArrayBuffer", FunctionLength::ONE);
156 JSHandle<JSObject> globalObject(thread_, env->GetGlobalObject());
157 JSHandle<JSTaggedValue> nameString(factory_->NewFromUtf8ReadOnly("SendableArrayBuffer"));
158 PropertyDescriptor desc(thread_, JSHandle<JSTaggedValue>::Cast(arrayBufferFunction), true, false, true);
159 JSObject::DefineOwnProperty(thread_, globalObject, nameString, desc);
160 RETURN_IF_ABRUPT_COMPLETION(thread_);
161
162 // SendableArrayBuffer prototype method
163 uint32_t fieldIndex = 0;
164 SetSFunction(env, arrayBufferPrototype, "slice",
165 BuiltinsSendableArrayBuffer::Slice, fieldIndex++, FunctionLength::TWO);
166
167 // 24.1.4.1 get SendableArrayBuffer.prototype.byteLength
168 JSHandle<JSTaggedValue> lengthGetter =
169 CreateSGetterSetter(env, BuiltinsSendableArrayBuffer::GetByteLength, "byteLength", FunctionLength::ZERO);
170 SetSAccessor(
171 JSHandle<JSObject>(arrayBufferPrototype), fieldIndex++, lengthGetter, globalConst->GetHandledUndefined());
172
173 // 24.1.4.4 SendableArrayBuffer.prototype[@@toStringTag]
174 JSHandle<JSTaggedValue> strTag(factory_->NewFromUtf8ReadOnly("SendableArrayBuffer"));
175 arrayBufferPrototype->SetPropertyInlinedProps(thread_, fieldIndex++, strTag.GetTaggedValue());
176
177 // 24.1.3.3 get SendableArrayBuffer[@@species]
178 fieldIndex = JSFunction::PROTOTYPE_INLINE_PROPERTY_INDEX + 1;
179 JSHandle<JSTaggedValue> speciesGetter =
180 CreateSGetterSetter(env, BuiltinsSendableArrayBuffer::Species, "[Symbol.species]", FunctionLength::ZERO);
181 SetSAccessor(
182 JSHandle<JSObject>(arrayBufferFunction), fieldIndex++, speciesGetter, globalConst->GetHandledUndefined());
183
184 // SendableArrayBuffer method
185 for (const base::BuiltinFunctionEntry& entry: BuiltinsSendableArrayBuffer::GetArrayBufferFunctions()) {
186 SetSFunction(env, JSHandle<JSObject>(arrayBufferFunction), entry.GetName(), entry.GetEntrypoint(), fieldIndex++,
187 entry.GetLength(), entry.GetBuiltinStubId());
188 }
189
190 env->SetSendableArrayBufferPrototype(thread_, arrayBufferPrototype);
191 env->SetSBuiltininArrayBufferFunction(thread_, arrayBufferFunction);
192 }
193
InitializeSSet(const JSHandle<GlobalEnv> & env,const JSHandle<JSObject> & sObjPrototype,const JSHandle<JSFunction> & sFuncPrototype) const194 void Builtins::InitializeSSet(const JSHandle<GlobalEnv> &env, const JSHandle<JSObject> &sObjPrototype,
195 const JSHandle<JSFunction> &sFuncPrototype) const
196 {
197 [[maybe_unused]] EcmaHandleScope scope(thread_);
198 const GlobalEnvConstants *globalConst = thread_->GlobalConstants();
199 // SharedSet.prototype
200 JSHandle<JSHClass> setPrototypeHClass = CreateSSetPrototypeHClass(sObjPrototype);
201 JSHandle<JSObject> setPrototype =
202 factory_->NewSharedOldSpaceJSObjectWithInit(setPrototypeHClass);
203
204 JSHandle<JSTaggedValue> setPrototypeValue(setPrototype);
205 // SharedSet.prototype_or_hclass
206 auto emptySLayout = globalConst->GetHandledEmptySLayoutInfo();
207 JSHandle<JSHClass> setIHClass =
208 factory_->NewSEcmaHClass(JSSharedSet::SIZE, 0, JSType::JS_SHARED_SET, setPrototypeValue, emptySLayout);
209 // SharedSet.hclass
210 JSHandle<JSHClass> setFuncHClass = CreateSSetFunctionHClass(sFuncPrototype);
211 // SharedSet() = new Function()
212 JSHandle<JSFunction> setFunction =
213 factory_->NewSFunctionByHClass(reinterpret_cast<void *>(BuiltinsSharedSet::Constructor),
214 setFuncHClass, FunctionKind::BUILTIN_CONSTRUCTOR);
215
216 InitializeSCtor(setIHClass, setFunction, "SendableSet", FunctionLength::ZERO);
217 JSHandle<JSObject> globalObject(thread_, env->GetGlobalObject());
218 JSHandle<JSTaggedValue> nameString(factory_->NewFromUtf8ReadOnly("SendableSet"));
219 PropertyDescriptor desc(thread_, JSHandle<JSTaggedValue>::Cast(setFunction), true, false, true);
220 JSObject::DefineOwnProperty(thread_, globalObject, nameString, desc);
221 RETURN_IF_ABRUPT_COMPLETION(thread_);
222
223 // "constructor" property on the prototype
224 uint32_t fieldIndex = 0; // constructor
225 setPrototype->SetPropertyInlinedProps(thread_, fieldIndex++, setFunction.GetTaggedValue());
226
227 // SharedSet.prototype functions, excluding keys()
228 for (const base::BuiltinFunctionEntry &entry: BuiltinsSharedSet::GetSetPrototypeFunctions()) {
229 SetSFunction(env, setPrototype, entry.GetName(), entry.GetEntrypoint(), fieldIndex++,
230 entry.GetLength(), entry.GetBuiltinStubId());
231 }
232 // SharedSet.prototype.keys, which is strictly equal to Set.prototype.values
233 JSHandle<JSTaggedValue> keys(factory_->NewFromASCIIReadOnly("keys"));
234 JSHandle<JSTaggedValue> values(factory_->NewFromASCIIReadOnly("values"));
235 JSHandle<JSTaggedValue> valuesFunc =
236 JSObject::GetMethod(thread_, JSHandle<JSTaggedValue>::Cast(setPrototype), values);
237 RETURN_IF_ABRUPT_COMPLETION(thread_);
238 setPrototype->SetPropertyInlinedProps(thread_, fieldIndex++, valuesFunc.GetTaggedValue());
239
240 // @@ToStringTag
241 JSHandle<JSTaggedValue> strTag(factory_->NewFromUtf8ReadOnly("SendableSet"));
242 setPrototype->SetPropertyInlinedProps(thread_, fieldIndex++, strTag.GetTaggedValue());
243
244 // 23.1.3.10get SharedSet.prototype.size
245 JSHandle<JSTaggedValue> sizeGetter = CreateSGetterSetter(env, BuiltinsSharedSet::GetSize, "size",
246 FunctionLength::ZERO);
247 SetSAccessor(setPrototype, fieldIndex++, sizeGetter, globalConst->GetHandledUndefined());
248
249 // %SetPrototype% [ @@iterator ]
250 setPrototype->SetPropertyInlinedProps(thread_, fieldIndex++, valuesFunc.GetTaggedValue());
251
252 fieldIndex = JSFunction::PROTOTYPE_INLINE_PROPERTY_INDEX + 1;
253 // 23.1.2.2get SharedSet [ @@species ]
254 JSHandle<JSTaggedValue> speciesGetter =
255 CreateSGetterSetter(env, BuiltinsSharedSet::Species, "[Symbol.species]", FunctionLength::ZERO);
256 SetSAccessor(JSHandle<JSObject>(setFunction), fieldIndex, speciesGetter, globalConst->GetHandledUndefined());
257
258 env->SetSharedSetPrototype(thread_, setPrototype);
259 env->SetSBuiltininSetFunction(thread_, setFunction);
260 }
261
InitializeSMap(const JSHandle<GlobalEnv> & env,const JSHandle<JSObject> & sObjPrototype,const JSHandle<JSFunction> & sFuncPrototype) const262 void Builtins::InitializeSMap(const JSHandle<GlobalEnv> &env, const JSHandle<JSObject> &sObjPrototype,
263 const JSHandle<JSFunction> &sFuncPrototype) const
264 {
265 [[maybe_unused]] EcmaHandleScope scope(thread_);
266 const GlobalEnvConstants *globalConst = thread_->GlobalConstants();
267 // SharedMap.prototype
268 JSHandle<JSHClass> mapPrototypeHClass = CreateSMapPrototypeHClass(sObjPrototype);
269 JSHandle<JSObject> mapPrototype =
270 factory_->NewSharedOldSpaceJSObjectWithInit(mapPrototypeHClass);
271 JSHandle<JSTaggedValue> mapPrototypeValue(mapPrototype);
272 // SharedMap.prototype_or_hclass
273 auto emptySLayout = globalConst->GetHandledEmptySLayoutInfo();
274 JSHandle<JSHClass> mapIHClass =
275 factory_->NewSEcmaHClass(JSSharedMap::SIZE, 0, JSType::JS_SHARED_MAP, mapPrototypeValue, emptySLayout);
276 // SharedMap.hclass
277 JSHandle<JSHClass> mapFuncHClass = CreateSMapFunctionHClass(sFuncPrototype);
278 // SharedMap() = new Function()
279 JSHandle<JSFunction> mapFunction =
280 factory_->NewSFunctionByHClass(reinterpret_cast<void *>(BuiltinsSharedMap::Constructor),
281 mapFuncHClass, FunctionKind::BUILTIN_CONSTRUCTOR);
282 InitializeSCtor(mapIHClass, mapFunction, "SendableMap", FunctionLength::ZERO);
283 JSHandle<JSObject> globalObject(thread_, env->GetGlobalObject());
284 JSHandle<JSTaggedValue> nameString(factory_->NewFromUtf8ReadOnly("SendableMap"));
285 PropertyDescriptor desc(thread_, JSHandle<JSTaggedValue>::Cast(mapFunction), true, false, true);
286 JSObject::DefineOwnProperty(thread_, globalObject, nameString, desc);
287 RETURN_IF_ABRUPT_COMPLETION(thread_);
288
289 // "constructor" property on the prototype
290 uint32_t fieldIndex = 0; // constructor
291 mapPrototype->SetPropertyInlinedProps(thread_, fieldIndex++, mapFunction.GetTaggedValue());
292 // SharedMap.prototype functions
293 for (const base::BuiltinFunctionEntry &entry: BuiltinsSharedMap::GetMapPrototypeFunctions()) {
294 SetSFunction(env, mapPrototype, entry.GetName(), entry.GetEntrypoint(), fieldIndex++,
295 entry.GetLength(), entry.GetBuiltinStubId());
296 }
297 // @@ToStringTag
298 JSHandle<JSTaggedValue> strTag(factory_->NewFromUtf8ReadOnly("SendableMap"));
299 mapPrototype->SetPropertyInlinedProps(thread_, fieldIndex++, strTag.GetTaggedValue());
300
301 // 23.1.3.10get SharedMap.prototype.size
302 JSHandle<JSTaggedValue> sizeGetter = CreateSGetterSetter(env, BuiltinsSharedMap::GetSize, "size",
303 FunctionLength::ZERO);
304 SetSAccessor(mapPrototype, fieldIndex++, sizeGetter, globalConst->GetHandledUndefined());
305
306 // %MapPrototype% [ @@iterator ]
307 JSHandle<JSTaggedValue> entries(factory_->NewFromASCIIReadOnly("entries"));
308 JSHandle<JSTaggedValue> entriesFunc =
309 JSObject::GetMethod(thread_, JSHandle<JSTaggedValue>::Cast(mapPrototype), entries);
310 RETURN_IF_ABRUPT_COMPLETION(thread_);
311 mapPrototype->SetPropertyInlinedProps(thread_, fieldIndex++, entriesFunc.GetTaggedValue());
312
313 fieldIndex = JSFunction::PROTOTYPE_INLINE_PROPERTY_INDEX + 1;
314 // 23.1.2.2get SharedMap [ @@species ]
315 JSHandle<JSTaggedValue> speciesGetter =
316 CreateSGetterSetter(env, BuiltinsSharedMap::Species, "[Symbol.species]", FunctionLength::ZERO);
317 SetSAccessor(JSHandle<JSObject>(mapFunction), fieldIndex, speciesGetter, globalConst->GetHandledUndefined());
318
319 env->SetSharedMapPrototype(thread_, mapPrototype);
320 env->SetSBuiltininMapFunction(thread_, mapFunction);
321 }
322
InitializeSModuleNamespace(const JSHandle<GlobalEnv> & env,const JSHandle<JSHClass> & sObjIHClass) const323 void Builtins::InitializeSModuleNamespace(const JSHandle<GlobalEnv> &env, const JSHandle<JSHClass> &sObjIHClass) const
324 {
325 [[maybe_unused]] EcmaHandleScope scope(thread_);
326 // SharedModuleNamespace.prototype
327 JSHandle<JSObject> moduleNamespacePrototype = factory_->NewSharedOldSpaceJSObjectWithInit(sObjIHClass);
328 JSHandle<JSTaggedValue> moduleNamespacePrototypeValue(moduleNamespacePrototype);
329
330 // SharedModuleNamespace.prototype_or_hclass
331 auto emptySLayout = thread_->GlobalConstants()->GetHandledEmptySLayoutInfo();
332
333 JSHandle<JSHClass> moduleNamespaceHClass = factory_->NewSEcmaHClass(ModuleNamespace::SIZE, 0,
334 JSType::JS_MODULE_NAMESPACE, moduleNamespacePrototypeValue, emptySLayout);
335 moduleNamespaceHClass->SetPrototype(thread_, JSTaggedValue::Null());
336 env->SetSharedModuleNamespaceClass(thread_, moduleNamespaceHClass.GetTaggedValue());
337
338 // SharedmoduleNamespace.prototype [ @@toStringTag ]
339 SetStringTagSymbol(env, moduleNamespacePrototype, "Module");
340 }
341
InitializeSAsyncFunction(const JSHandle<GlobalEnv> & env,const JSHandle<JSHClass> & sObjIHClass) const342 void Builtins::InitializeSAsyncFunction(const JSHandle<GlobalEnv> &env,
343 const JSHandle<JSHClass> &sObjIHClass) const
344 {
345 // SharedAsyncFunction.prototype
346 JSHandle<JSObject> sAsyncFuncPrototype = factory_->NewSharedOldSpaceJSObjectWithInit(sObjIHClass);
347 JSObject::SetPrototype(thread_, sAsyncFuncPrototype, env->GetSFunctionPrototype());
348 // SharedAsyncFunction.prototype_or_hclass
349 auto emptySLayout = thread_->GlobalConstants()->GetHandledEmptySLayoutInfo();
350 JSHandle<JSHClass> sAsyncFuncIHClass = factory_->NewSEcmaHClass(JSAsyncFunction::SIZE, 0,
351 JSType::JS_SHARED_ASYNC_FUNCTION, JSHandle<JSTaggedValue>(sAsyncFuncPrototype), emptySLayout);
352 // SharedAsyncFunction = new SharedFunction()
353 JSHandle<JSFunction> sAsyncFuncFunction = factory_->NewSFunctionByHClass(
354 reinterpret_cast<void *>(BuiltinsSharedAsyncFunction::SharedAsyncFunctionConstructor),
355 sAsyncFuncIHClass, FunctionKind::BUILTIN_CONSTRUCTOR);
356 JSObject::SetPrototype(thread_, JSHandle<JSObject>(sAsyncFuncFunction), env->GetSFunctionFunction());
357 sAsyncFuncFunction->SetProtoOrHClass(thread_, sAsyncFuncIHClass);
358 env->SetSAsyncFunctionFunction(thread_, sAsyncFuncFunction);
359 env->SetSAsyncFunctionPrototype(thread_, sAsyncFuncPrototype);
360 JSHandle<JSTaggedValue> sAsyncFuncPrototypeVal(thread_, sAsyncFuncPrototype.GetTaggedValue());
361 JSHandle<JSHClass> sAsyncFuncClass = factory_->CreateSFunctionClass(
362 JSAsyncFunction::SIZE, JSType::JS_SHARED_ASYNC_FUNCTION, sAsyncFuncPrototypeVal);
363 env->SetSAsyncFunctionClass(thread_, sAsyncFuncClass);
364 }
365
InitializeSFunction(const JSHandle<GlobalEnv> & env,const JSHandle<JSFunction> & sFuncPrototype) const366 void Builtins::InitializeSFunction(const JSHandle<GlobalEnv> &env,
367 const JSHandle<JSFunction> &sFuncPrototype) const
368 {
369 [[maybe_unused]] EcmaHandleScope scope(thread_);
370 SetSFunctionLength(sFuncPrototype, FunctionLength::ZERO);
371 SetSFunctionName(sFuncPrototype, thread_->GlobalConstants()->GetHandledEmptyString());
372 // SharedFunction.prototype_or_hclass
373 auto emptySLayout = thread_->GlobalConstants()->GetHandledEmptySLayoutInfo();
374 JSHandle<JSHClass> sFuncIHClass = factory_->NewSEcmaHClass(JSSharedFunction::SIZE, 0, JSType::JS_SHARED_FUNCTION,
375 JSHandle<JSTaggedValue>(sFuncPrototype), emptySLayout);
376 sFuncIHClass->SetCallable(true);
377 sFuncIHClass->SetConstructor(true);
378 // SharedFunction.hclass
379 JSHandle<JSHClass> sFuncHClass = CreateSFunctionHClass(sFuncPrototype);
380 // new SharedFunction() (forbidden use NewBuiltinConstructor)
381 JSHandle<JSFunction> sFuncFunction = factory_->NewSFunctionByHClass(
382 reinterpret_cast<void *>(BuiltinsSharedFunction::SharedFunctionConstructor),
383 sFuncHClass, FunctionKind::BUILTIN_CONSTRUCTOR);
384 InitializeSCtor(sFuncIHClass, sFuncFunction, "SharedFunction", FunctionLength::ONE);
385 env->SetSFunctionFunction(thread_, sFuncFunction);
386 env->SetSFunctionPrototype(thread_, sFuncPrototype);
387
388 JSHandle<JSTaggedValue> sFuncPrototypeVal(sFuncPrototype);
389 JSHandle<JSHClass> functionClass =
390 factory_->CreateSFunctionClass(JSSharedFunction::SIZE, JSType::JS_SHARED_FUNCTION,
391 sFuncPrototypeVal);
392 env->SetSFunctionClassWithoutProto(thread_, functionClass);
393 JSHandle<JSHClass> functionClassWithProto =
394 factory_->CreateSFunctionClass(JSSharedFunction::SIZE, JSType::JS_SHARED_FUNCTION,
395 sFuncPrototypeVal, true, true);
396 env->SetSFunctionClassWithProto(thread_, functionClassWithProto);
397
398 JSHandle<JSHClass> functionClassWithoutAccessor =
399 factory_->CreateSFunctionClass(JSSharedFunction::SIZE, JSType::JS_SHARED_FUNCTION,
400 sFuncPrototypeVal, false);
401 env->SetSFunctionClassWithoutAccessor(thread_, functionClassWithoutAccessor);
402 uint32_t fieldIndex = 2; // 2: length and name
403 JSHandle<JSObject> sFuncPrototypeObj(sFuncPrototype);
404 sFuncPrototypeObj->SetPropertyInlinedProps(thread_, fieldIndex++, sFuncFunction.GetTaggedValue()); // constructor
405 SharedStrictModeForbiddenAccessCallerArguments(env, fieldIndex, sFuncPrototypeObj);
406 // Function.prototype method
407 // 19.2.3.1 Function.prototype.apply ( thisArg, argArray )
408 SetSFunction(env, sFuncPrototypeObj, "apply", Function::FunctionPrototypeApply, fieldIndex++, FunctionLength::TWO,
409 BUILTINS_STUB_ID(FunctionPrototypeApply));
410 // 19.2.3.2 Function.prototype.bind ( thisArg , ...args)
411 SetSFunction(env, sFuncPrototypeObj, "bind", Function::FunctionPrototypeBind, fieldIndex++, FunctionLength::ONE);
412 // 19.2.3.3 Function.prototype.call (thisArg , ...args)
413 SetSFunction(env, sFuncPrototypeObj, "call", Function::FunctionPrototypeCall, fieldIndex++, FunctionLength::ONE);
414 // 19.2.3.5 Function.prototype.toString ( )
415 SetSFunction(env, sFuncPrototypeObj, thread_->GlobalConstants()->GetHandledToStringString(),
416 Function::FunctionPrototypeToString, fieldIndex++, FunctionLength::ZERO);
417 SetSFunction(env, sFuncPrototypeObj, "[Symbol.hasInstance]",
418 Function::FunctionPrototypeHasInstance, fieldIndex++, FunctionLength::ONE);
419 }
420
CreateSObjectFunctionHClass(const JSHandle<JSFunction> & sFuncPrototype) const421 JSHandle<JSHClass> Builtins::CreateSObjectFunctionHClass(const JSHandle<JSFunction> &sFuncPrototype) const
422 {
423 uint32_t index = 0;
424 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
425 attributes.SetIsInlinedProps(true);
426 attributes.SetRepresentation(Representation::TAGGED);
427 auto properties = Object::GetFunctionProperties();
428 uint32_t length = properties.size();
429 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
430 for (const std::pair<std::string_view, bool> &each : properties) {
431 attributes.SetOffset(index);
432 attributes.SetIsAccessor(each.second);
433 JSHandle<JSTaggedValue> keyString(factory_->NewFromUtf8ReadOnly(each.first));
434 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
435 }
436 JSHandle<JSHClass> sobjPrototypeHClass =
437 factory_->NewSEcmaHClass(JSSharedFunction::SIZE, length, JSType::JS_SHARED_FUNCTION,
438 JSHandle<JSTaggedValue>(sFuncPrototype), JSHandle<JSTaggedValue>(layout));
439 sobjPrototypeHClass->SetConstructor(true);
440 sobjPrototypeHClass->SetCallable(true);
441 return sobjPrototypeHClass;
442 }
443
CreateSObjectPrototypeHClass() const444 JSHandle<JSHClass> Builtins::CreateSObjectPrototypeHClass() const
445 {
446 const GlobalEnvConstants *globalConst = thread_->GlobalConstants();
447 JSHandle<JSTaggedValue> nullHandle = globalConst->GetHandledNull();
448
449 uint32_t index = 0;
450 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
451 attributes.SetIsInlinedProps(true);
452 attributes.SetRepresentation(Representation::TAGGED);
453 auto properties = Object::GetFunctionPrototypeProperties();
454 uint32_t length = properties.size();
455 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
456 for (const std::pair<std::string_view, bool> &each : properties) {
457 attributes.SetOffset(index);
458 attributes.SetIsAccessor(each.second);
459 JSHandle<JSTaggedValue> keyString(factory_->NewFromUtf8ReadOnly(each.first));
460 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
461 }
462
463 JSHandle<JSHClass> sobjPrototypeHClass =
464 factory_->NewSEcmaHClass(JSSharedObject::SIZE, length, JSType::JS_SHARED_OBJECT, nullHandle,
465 JSHandle<JSTaggedValue>(layout));
466 return sobjPrototypeHClass;
467 }
468
CreateSFunctionHClass(const JSHandle<JSFunction> & sFuncPrototype) const469 JSHandle<JSHClass> Builtins::CreateSFunctionHClass(const JSHandle<JSFunction> &sFuncPrototype) const
470 {
471 uint32_t index = 0;
472 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
473 attributes.SetIsInlinedProps(true);
474 attributes.SetRepresentation(Representation::TAGGED);
475 auto properties = Function::GetFunctionProperties();
476 uint32_t length = properties.size();
477 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
478 for (const base::BuiltinsPropertyConfig &each : properties) {
479 attributes.SetOffset(index);
480 attributes.SetIsAccessor(each.GetIsAccessor());
481 JSHandle<JSTaggedValue> keyString(factory_->NewFromUtf8ReadOnly(each.GetName()));
482 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
483 }
484 JSHandle<JSHClass> sobjPrototypeHClass =
485 factory_->NewSEcmaHClass(JSSharedFunction::SIZE, length, JSType::JS_SHARED_FUNCTION,
486 JSHandle<JSTaggedValue>(sFuncPrototype), JSHandle<JSTaggedValue>(layout));
487 sobjPrototypeHClass->SetConstructor(true);
488 sobjPrototypeHClass->SetCallable(true);
489 return sobjPrototypeHClass;
490 }
491
CreateSArrayBufferFunctionHClass(const JSHandle<JSFunction> & sFuncPrototype) const492 JSHandle<JSHClass> Builtins::CreateSArrayBufferFunctionHClass(const JSHandle<JSFunction> &sFuncPrototype) const
493 {
494 uint32_t index = 0;
495 auto env = vm_->GetGlobalEnv();
496 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
497 attributes.SetIsInlinedProps(true);
498 attributes.SetRepresentation(Representation::TAGGED);
499 auto properties = BuiltinsSendableArrayBuffer::GetFunctionProperties();
500 uint32_t length = properties.size();
501 JSHandle<JSTaggedValue> keyString;
502 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
503 for (const auto &[key, isAccessor] : properties) {
504 attributes.SetOffset(index);
505 attributes.SetIsAccessor(isAccessor);
506 if (key == "[Symbol.species]") {
507 keyString = env->GetSpeciesSymbol();
508 } else {
509 keyString = JSHandle<JSTaggedValue>(factory_->NewFromUtf8ReadOnly(key));
510 }
511 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
512 }
513 JSHandle<JSHClass> sobjPrototypeHClass =
514 factory_->NewSEcmaHClass(JSSharedFunction::SIZE, length, JSType::JS_SHARED_FUNCTION,
515 JSHandle<JSTaggedValue>(sFuncPrototype), JSHandle<JSTaggedValue>(layout));
516 sobjPrototypeHClass->SetConstructor(true);
517 sobjPrototypeHClass->SetCallable(true);
518 return sobjPrototypeHClass;
519 }
520
CreateSSetFunctionHClass(const JSHandle<JSFunction> & sFuncPrototype) const521 JSHandle<JSHClass> Builtins::CreateSSetFunctionHClass(const JSHandle<JSFunction> &sFuncPrototype) const
522 {
523 uint32_t index = 0;
524 auto env = vm_->GetGlobalEnv();
525 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
526 attributes.SetIsInlinedProps(true);
527 attributes.SetRepresentation(Representation::TAGGED);
528 auto properties = BuiltinsSharedSet::GetFunctionProperties();
529 uint32_t length = properties.size();
530 JSHandle<JSTaggedValue> keyString;
531 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
532 for (const auto &[key, isAccessor] : properties) {
533 attributes.SetOffset(index);
534 attributes.SetIsAccessor(isAccessor);
535 if (key == "[Symbol.species]") {
536 keyString = env->GetSpeciesSymbol();
537 } else {
538 keyString = JSHandle<JSTaggedValue>(factory_->NewFromUtf8ReadOnly(key));
539 }
540 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
541 }
542 JSHandle<JSHClass> sobjPrototypeHClass =
543 factory_->NewSEcmaHClass(JSSharedFunction::SIZE, length, JSType::JS_SHARED_FUNCTION,
544 JSHandle<JSTaggedValue>(sFuncPrototype), JSHandle<JSTaggedValue>(layout));
545 sobjPrototypeHClass->SetConstructor(true);
546 sobjPrototypeHClass->SetCallable(true);
547 return sobjPrototypeHClass;
548 }
549
CreateSMapFunctionHClass(const JSHandle<JSFunction> & sFuncPrototype) const550 JSHandle<JSHClass> Builtins::CreateSMapFunctionHClass(const JSHandle<JSFunction> &sFuncPrototype) const
551 {
552 uint32_t index = 0;
553 auto env = vm_->GetGlobalEnv();
554 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
555 attributes.SetIsInlinedProps(true);
556 attributes.SetRepresentation(Representation::TAGGED);
557 auto properties = BuiltinsSharedMap::GetFunctionProperties();
558 uint32_t length = properties.size();
559 JSHandle<JSTaggedValue> keyString;
560 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
561 for (const auto &[key, isAccessor] : properties) {
562 attributes.SetOffset(index);
563 attributes.SetIsAccessor(isAccessor);
564 if (key == "[Symbol.species]") {
565 keyString = env->GetSpeciesSymbol();
566 } else {
567 keyString = JSHandle<JSTaggedValue>(factory_->NewFromUtf8ReadOnly(key));
568 }
569 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
570 }
571 JSHandle<JSHClass> sobjPrototypeHClass =
572 factory_->NewSEcmaHClass(JSSharedFunction::SIZE, length, JSType::JS_SHARED_FUNCTION,
573 JSHandle<JSTaggedValue>(sFuncPrototype), JSHandle<JSTaggedValue>(layout));
574 sobjPrototypeHClass->SetConstructor(true);
575 sobjPrototypeHClass->SetCallable(true);
576 return sobjPrototypeHClass;
577 }
578
CreateBitVectorFunctionHClass(const JSHandle<JSFunction> & sFuncPrototype) const579 JSHandle<JSHClass> Builtins::CreateBitVectorFunctionHClass(const JSHandle<JSFunction> &sFuncPrototype) const
580 {
581 uint32_t index = 0;
582 auto env = vm_->GetGlobalEnv();
583 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
584 attributes.SetIsInlinedProps(true);
585 attributes.SetRepresentation(Representation::TAGGED);
586 auto properties = ContainersBitVector::GetFunctionProperties();
587 uint32_t length = properties.size();
588 JSHandle<JSTaggedValue> keyString;
589 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
590 for (const auto &[key, isAccessor] : properties) {
591 attributes.SetOffset(index);
592 attributes.SetIsAccessor(isAccessor);
593 if (key == "[Symbol.species]") {
594 keyString = env->GetSpeciesSymbol();
595 } else {
596 keyString = JSHandle<JSTaggedValue>(factory_->NewFromUtf8ReadOnly(key));
597 }
598 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
599 }
600 JSHandle<JSHClass> sobjPrototypeHClass =
601 factory_->NewSEcmaHClass(JSSharedFunction::SIZE, length, JSType::JS_SHARED_FUNCTION,
602 JSHandle<JSTaggedValue>(sFuncPrototype), JSHandle<JSTaggedValue>(layout));
603 sobjPrototypeHClass->SetConstructor(true);
604 sobjPrototypeHClass->SetCallable(true);
605 return sobjPrototypeHClass;
606 }
607
CreateSFunctionPrototypeHClass(const JSHandle<JSTaggedValue> & sObjPrototypeVal) const608 JSHandle<JSHClass> Builtins::CreateSFunctionPrototypeHClass(const JSHandle<JSTaggedValue> &sObjPrototypeVal) const
609 {
610 uint32_t index = 0;
611 auto env = vm_->GetGlobalEnv();
612 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
613 attributes.SetIsInlinedProps(true);
614 attributes.SetRepresentation(Representation::TAGGED);
615 auto properties = Function::GetFunctionPrototypeProperties();
616 uint32_t length = properties.size();
617 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
618 JSHandle<JSTaggedValue> keyString;
619 for (const base::BuiltinsPropertyConfig &each : properties) {
620 attributes.SetOffset(index);
621 attributes.SetIsAccessor(each.GetIsAccessor());
622 if (each.GetName() == "[Symbol.hasInstance]") {
623 keyString = env->GetHasInstanceSymbol();
624 } else {
625 keyString = JSHandle<JSTaggedValue>(factory_->NewFromUtf8ReadOnly(each.GetName()));
626 }
627 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
628 }
629 JSHandle<JSHClass> sobjPrototypeHClass =
630 factory_->NewSEcmaHClass(JSSharedFunction::SIZE, length, JSType::JS_SHARED_FUNCTION, sObjPrototypeVal,
631 JSHandle<JSTaggedValue>(layout));
632 sobjPrototypeHClass->SetCallable(true);
633 return sobjPrototypeHClass;
634 }
635
CreateSArrayBufferPrototypeHClass(const JSHandle<JSObject> & sObjPrototype) const636 JSHandle<JSHClass> Builtins::CreateSArrayBufferPrototypeHClass(const JSHandle<JSObject> &sObjPrototype) const
637 {
638 uint32_t index = 0;
639 auto env = vm_->GetGlobalEnv();
640 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
641 attributes.SetIsInlinedProps(true);
642 attributes.SetRepresentation(Representation::TAGGED);
643 auto properties = BuiltinsSendableArrayBuffer::GetPrototypeProperties();
644 uint32_t length = properties.size();
645 ASSERT(length == BuiltinsSendableArrayBuffer::GetNumPrototypeInlinedProperties());
646 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
647 JSHandle<JSTaggedValue> keyString;
648 for (const auto &[key, isAccessor] : properties) {
649 attributes.SetOffset(index);
650 attributes.SetIsAccessor(isAccessor);
651 if (key == "[Symbol.toStringTag]") {
652 keyString = env->GetToStringTagSymbol();
653 } else {
654 keyString = JSHandle<JSTaggedValue>(factory_->NewFromUtf8ReadOnly(key));
655 }
656 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
657 }
658 JSHandle<JSHClass> sArrayBufferPrototypeHClass =
659 factory_->NewSEcmaHClass(JSSharedObject::SIZE, length, JSType::JS_SHARED_OBJECT,
660 JSHandle<JSTaggedValue>(sObjPrototype),
661 JSHandle<JSTaggedValue>(layout));
662 return sArrayBufferPrototypeHClass;
663 }
664
CreateSSetPrototypeHClass(const JSHandle<JSObject> & sObjPrototype) const665 JSHandle<JSHClass> Builtins::CreateSSetPrototypeHClass(const JSHandle<JSObject> &sObjPrototype) const
666 {
667 uint32_t index = 0;
668 auto env = vm_->GetGlobalEnv();
669 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
670 attributes.SetIsInlinedProps(true);
671 attributes.SetRepresentation(Representation::TAGGED);
672 auto properties = BuiltinsSharedSet::GetPrototypeProperties();
673 uint32_t length = properties.size();
674 ASSERT(length == BuiltinsSharedSet::GetNumPrototypeInlinedProperties());
675 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
676 JSHandle<JSTaggedValue> keyString;
677 for (const auto &[key, isAccessor] : properties) {
678 attributes.SetOffset(index);
679 attributes.SetIsAccessor(isAccessor);
680 if (key == "[Symbol.iterator]") {
681 keyString = env->GetIteratorSymbol();
682 } else if (key == "[Symbol.toStringTag]") {
683 keyString = env->GetToStringTagSymbol();
684 } else {
685 keyString = JSHandle<JSTaggedValue>(factory_->NewFromUtf8ReadOnly(key));
686 }
687 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
688 }
689 JSHandle<JSHClass> sSetPrototypeHClass =
690 factory_->NewSEcmaHClass(JSSharedObject::SIZE, length, JSType::JS_SHARED_OBJECT,
691 JSHandle<JSTaggedValue>(sObjPrototype),
692 JSHandle<JSTaggedValue>(layout));
693 return sSetPrototypeHClass;
694 }
695
CreateSMapPrototypeHClass(const JSHandle<JSObject> & sObjPrototype) const696 JSHandle<JSHClass> Builtins::CreateSMapPrototypeHClass(const JSHandle<JSObject> &sObjPrototype) const
697 {
698 uint32_t index = 0;
699 auto env = vm_->GetGlobalEnv();
700 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
701 attributes.SetIsInlinedProps(true);
702 attributes.SetRepresentation(Representation::TAGGED);
703 auto properties = BuiltinsSharedMap::GetPrototypeProperties();
704 uint32_t length = properties.size();
705 ASSERT(length == BuiltinsSharedMap::GetNumPrototypeInlinedProperties());
706 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
707 JSHandle<JSTaggedValue> keyString;
708 for (const auto &[key, isAccessor] : properties) {
709 attributes.SetOffset(index);
710 attributes.SetIsAccessor(isAccessor);
711 if (key == "[Symbol.iterator]") {
712 keyString = env->GetIteratorSymbol();
713 } else if (key == "[Symbol.toStringTag]") {
714 keyString = env->GetToStringTagSymbol();
715 } else {
716 keyString = JSHandle<JSTaggedValue>(factory_->NewFromUtf8ReadOnly(key));
717 }
718 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
719 }
720 JSHandle<JSHClass> sMapPrototypeHClass =
721 factory_->NewSEcmaHClass(JSSharedObject::SIZE, length, JSType::JS_SHARED_OBJECT,
722 JSHandle<JSTaggedValue>(sObjPrototype),
723 JSHandle<JSTaggedValue>(layout));
724 return sMapPrototypeHClass;
725 }
726
CreateBitVectorPrototypeHClass(const JSHandle<JSObject> & sObjPrototype) const727 JSHandle<JSHClass> Builtins::CreateBitVectorPrototypeHClass(const JSHandle<JSObject> &sObjPrototype) const
728 {
729 uint32_t index = 0;
730 auto env = vm_->GetGlobalEnv();
731 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
732 attributes.SetIsInlinedProps(true);
733 attributes.SetRepresentation(Representation::TAGGED);
734 auto properties = ContainersBitVector::GetPrototypeProperties();
735 uint32_t length = properties.size();
736 ASSERT(length == ContainersBitVector::GetNumPrototypeInlinedProperties());
737 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
738 JSHandle<JSTaggedValue> keyString;
739 for (const auto &[key, isAccessor] : properties) {
740 attributes.SetOffset(index);
741 attributes.SetIsAccessor(isAccessor);
742 if (key == "[Symbol.iterator]") {
743 keyString = env->GetIteratorSymbol();
744 } else if (key == "[Symbol.toStringTag]") {
745 keyString = env->GetToStringTagSymbol();
746 } else {
747 keyString = JSHandle<JSTaggedValue>(factory_->NewFromUtf8ReadOnly(key));
748 }
749 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
750 }
751 JSHandle<JSHClass> sBitVectorPrototypeHClass =
752 factory_->NewSEcmaHClass(JSSharedObject::SIZE, length, JSType::JS_SHARED_OBJECT,
753 JSHandle<JSTaggedValue>(sObjPrototype),
754 JSHandle<JSTaggedValue>(layout));
755 return sBitVectorPrototypeHClass;
756 }
757
CreateSArrayPrototypeHClass(const JSHandle<JSObject> & sObjPrototype) const758 JSHandle<JSHClass> Builtins::CreateSArrayPrototypeHClass(const JSHandle<JSObject> &sObjPrototype) const
759 {
760 uint32_t index = 0;
761 auto env = vm_->GetGlobalEnv();
762 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
763 attributes.SetIsInlinedProps(true);
764 attributes.SetRepresentation(Representation::TAGGED);
765 auto properties = BuiltinsSharedArray::GetPrototypeProperties();
766 uint32_t length = properties.size();
767 ASSERT(length == BuiltinsSharedArray::GetNumPrototypeInlinedProperties());
768 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
769 JSHandle<JSTaggedValue> keyString;
770 for (const auto &[key, isAccessor] : properties) {
771 attributes.SetOffset(index);
772 attributes.SetIsAccessor(isAccessor);
773 if (key == "[Symbol.iterator]") {
774 keyString = env->GetIteratorSymbol();
775 } else if (key == "[Symbol.toStringTag]") {
776 keyString = env->GetToStringTagSymbol();
777 } else {
778 keyString = JSHandle<JSTaggedValue>(factory_->NewFromUtf8ReadOnly(key));
779 }
780 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
781 }
782 JSHandle<JSHClass> sArrayPrototypeHClass =
783 factory_->NewSEcmaHClass(JSSharedArray::SIZE, length, JSType::JS_SHARED_ARRAY,
784 JSHandle<JSTaggedValue>(sObjPrototype),
785 JSHandle<JSTaggedValue>(layout));
786 return sArrayPrototypeHClass;
787 }
788
CreateSArrayFunctionHClass(const JSHandle<JSFunction> & sFuncPrototype) const789 JSHandle<JSHClass> Builtins::CreateSArrayFunctionHClass(const JSHandle<JSFunction> &sFuncPrototype) const
790 {
791 uint32_t index = 0;
792 auto env = vm_->GetGlobalEnv();
793 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
794 attributes.SetIsInlinedProps(true);
795 attributes.SetRepresentation(Representation::TAGGED);
796 auto properties = BuiltinsSharedArray::GetFunctionProperties();
797 uint32_t length = properties.size();
798 JSHandle<JSTaggedValue> keyString;
799 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
800 for (const auto &[key, isAccessor] : properties) {
801 LOG_ECMA(DEBUG) << "CreateSArrayFunctionHClass " << key;
802 attributes.SetOffset(index);
803 attributes.SetIsAccessor(isAccessor);
804 if (key == "[Symbol.species]") {
805 keyString = env->GetSpeciesSymbol();
806 } else {
807 keyString = JSHandle<JSTaggedValue>(factory_->NewFromUtf8ReadOnly(key));
808 }
809 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
810 }
811 JSHandle<JSHClass> sobjPrototypeHClass =
812 factory_->NewSEcmaHClass(JSSharedFunction::SIZE, length, JSType::JS_SHARED_FUNCTION,
813 JSHandle<JSTaggedValue>(sFuncPrototype), JSHandle<JSTaggedValue>(layout));
814 sobjPrototypeHClass->SetConstructor(true);
815 sobjPrototypeHClass->SetCallable(true);
816 return sobjPrototypeHClass;
817 }
818
SetSFunctionName(const JSHandle<JSFunction> & ctor,std::string_view name) const819 void Builtins::SetSFunctionName(const JSHandle<JSFunction> &ctor, std::string_view name) const
820 {
821 JSHandle<JSTaggedValue> nameString(factory_->NewFromUtf8ReadOnly(name));
822 SetSFunctionName(ctor, nameString);
823 }
824
SetSFunctionName(const JSHandle<JSFunction> & ctor,const JSHandle<JSTaggedValue> & name) const825 void Builtins::SetSFunctionName(const JSHandle<JSFunction> &ctor, const JSHandle<JSTaggedValue> &name) const
826 {
827 auto nameIndex = JSFunction::NAME_INLINE_PROPERTY_INDEX;
828 ctor->SetPropertyInlinedProps(thread_, nameIndex, name.GetTaggedValue());
829 }
830
SetSFunctionLength(const JSHandle<JSFunction> & ctor,int length) const831 void Builtins::SetSFunctionLength(const JSHandle<JSFunction> &ctor, int length) const
832 {
833 JSTaggedValue taggedLength(length);
834 auto lengthIndex = JSFunction::LENGTH_INLINE_PROPERTY_INDEX;
835 ctor->SetPropertyInlinedProps(thread_, lengthIndex, taggedLength);
836 }
837
SetSFunctionPrototype(const JSHandle<JSFunction> & ctor,const JSTaggedValue & prototype) const838 void Builtins::SetSFunctionPrototype(const JSHandle<JSFunction> &ctor, const JSTaggedValue &prototype) const
839 {
840 auto prototypeIndex = JSFunction::PROTOTYPE_INLINE_PROPERTY_INDEX;
841 ctor->SetPropertyInlinedProps(thread_, prototypeIndex, prototype);
842 }
843
InitializeSCtor(const JSHandle<JSHClass> & protoHClass,const JSHandle<JSFunction> & ctor,std::string_view name,int length) const844 void Builtins::InitializeSCtor(const JSHandle<JSHClass> &protoHClass, const JSHandle<JSFunction> &ctor,
845 std::string_view name, int length) const
846 {
847 SetSFunctionLength(ctor, length);
848 SetSFunctionName(ctor, name);
849 SetSFunctionPrototype(ctor, protoHClass->GetProto());
850 ctor->SetProtoOrHClass(thread_, protoHClass);
851 }
852
NewSFunction(const JSHandle<GlobalEnv> & env,const JSHandle<JSTaggedValue> & key,EcmaEntrypoint func,int length,kungfu::BuiltinsStubCSigns::ID builtinId) const853 JSHandle<JSFunction> Builtins::NewSFunction(const JSHandle<GlobalEnv> &env, const JSHandle<JSTaggedValue> &key,
854 EcmaEntrypoint func, int length,
855 kungfu::BuiltinsStubCSigns::ID builtinId) const
856 {
857 JSHandle<JSHClass> hclass = JSHandle<JSHClass>::Cast(env->GetSFunctionClassWithoutAccessor());
858 JSHandle<JSFunction> function = factory_->NewSFunctionByHClass(reinterpret_cast<void *>(func),
859 hclass, FunctionKind::NORMAL_FUNCTION, builtinId, MemSpaceType::SHARED_NON_MOVABLE);
860 SetSFunctionLength(function, length);
861 SetSFunctionName(function, key);
862 function->GetJSHClass()->SetExtensible(false);
863 return function;
864 }
865
SetSFunction(const JSHandle<GlobalEnv> & env,const JSHandle<JSObject> & obj,std::string_view key,EcmaEntrypoint func,uint32_t index,int length,kungfu::BuiltinsStubCSigns::ID builtinId) const866 void Builtins::SetSFunction(const JSHandle<GlobalEnv> &env, const JSHandle<JSObject> &obj, std::string_view key,
867 EcmaEntrypoint func, uint32_t index, int length,
868 kungfu::BuiltinsStubCSigns::ID builtinId) const
869 {
870 JSHandle<JSTaggedValue> keyString(factory_->NewFromUtf8ReadOnly(key));
871 SetSFunction(env, obj, keyString, func, index, length, builtinId);
872 }
873
SetSFunction(const JSHandle<GlobalEnv> & env,const JSHandle<JSObject> & obj,const JSHandle<JSTaggedValue> & key,EcmaEntrypoint func,uint32_t index,int length,kungfu::BuiltinsStubCSigns::ID builtinId) const874 void Builtins::SetSFunction(const JSHandle<GlobalEnv> &env, const JSHandle<JSObject> &obj,
875 const JSHandle<JSTaggedValue> &key, EcmaEntrypoint func, uint32_t index, int length,
876 kungfu::BuiltinsStubCSigns::ID builtinId) const
877 {
878 JSHandle<JSFunction> function(NewSFunction(env, key, func, length, builtinId));
879 obj->SetPropertyInlinedProps(thread_, index, function.GetTaggedValue());
880 }
881
SetSAccessor(const JSHandle<JSObject> & obj,uint32_t index,const JSHandle<JSTaggedValue> & getter,const JSHandle<JSTaggedValue> & setter) const882 void Builtins::SetSAccessor(const JSHandle<JSObject> &obj, uint32_t index,
883 const JSHandle<JSTaggedValue> &getter, const JSHandle<JSTaggedValue> &setter) const
884 {
885 JSHandle<AccessorData> accessor = factory_->NewSAccessorData();
886 accessor->SetGetter(thread_, getter);
887 accessor->SetSetter(thread_, setter);
888 obj->SetPropertyInlinedProps(thread_, index, accessor.GetTaggedValue());
889 }
890
CreateSGetterSetter(const JSHandle<GlobalEnv> & env,EcmaEntrypoint func,std::string_view name,int length) const891 JSHandle<JSTaggedValue> Builtins::CreateSGetterSetter(const JSHandle<GlobalEnv> &env, EcmaEntrypoint func,
892 std::string_view name, int length) const
893 {
894 JSHandle<JSTaggedValue> funcName(factory_->NewFromUtf8ReadOnly(name));
895 JSHandle<JSFunction> function = NewSFunction(env, funcName, func, length);
896 return JSHandle<JSTaggedValue>(function);
897 }
898
SharedStrictModeForbiddenAccessCallerArguments(const JSHandle<GlobalEnv> & env,uint32_t & index,const JSHandle<JSObject> & prototype) const899 void Builtins::SharedStrictModeForbiddenAccessCallerArguments(const JSHandle<GlobalEnv> &env, uint32_t &index,
900 const JSHandle<JSObject> &prototype) const
901 {
902 JSHandle<JSHClass> hclass = JSHandle<JSHClass>::Cast(env->GetSFunctionClassWithoutProto());
903 JSHandle<JSFunction> func =
904 factory_->NewSFunctionWithAccessor(
905 reinterpret_cast<void *>(JSFunction::AccessCallerArgumentsThrowTypeError), hclass,
906 FunctionKind::NORMAL_FUNCTION);
907 // "caller"
908 SetSAccessor(prototype, index++, JSHandle<JSTaggedValue>(func), JSHandle<JSTaggedValue>(func));
909 // "arguments"
910 SetSAccessor(prototype, index++, JSHandle<JSTaggedValue>(func), JSHandle<JSTaggedValue>(func));
911 }
912
InitializeSSymbolAttributes(const JSHandle<GlobalEnv> & env)913 void Builtins::InitializeSSymbolAttributes(const JSHandle<GlobalEnv> &env)
914 {
915 JSHandle<JSTaggedValue> hasInstanceSymbol(
916 factory_->NewSWellKnownSymbolWithChar("Symbol.hasInstance"));
917 JSHandle<JSTaggedValue> isConcatSpreadableSymbol(
918 factory_->NewSWellKnownSymbolWithChar("Symbol.isConcatSpreadable"));
919 JSHandle<JSTaggedValue> toStringTagSymbol(
920 factory_->NewSWellKnownSymbolWithChar("Symbol.toStringTag"));
921 JSHandle<JSTaggedValue> asyncIteratorSymbol(
922 factory_->NewSPublicSymbolWithChar("Symbol.asyncIterator"));
923 JSHandle<JSTaggedValue> matchSymbol(
924 factory_->NewSPublicSymbolWithChar("Symbol.match"));
925 JSHandle<JSTaggedValue> searchSymbol(
926 factory_->NewSPublicSymbolWithChar("Symbol.search"));
927 JSHandle<JSTaggedValue> toPrimitiveSymbol(
928 factory_->NewSPublicSymbolWithChar("Symbol.toPrimitive"));
929 JSHandle<JSTaggedValue> unscopablesSymbol(
930 factory_->NewSPublicSymbolWithChar("Symbol.unscopables"));
931 JSHandle<JSTaggedValue> nativeBindingSymbol(
932 factory_->NewSPublicSymbolWithChar("Symbol.nativeBinding"));
933
934 // Symbol attributes with detectors
935 // Create symbol string before create symbol to allocate symbol continuously
936 // Attention: Symbol serialization & deserialization are not supported now and
937 // the order of symbols and symbol-strings must be maintained too when
938 // Symbol serialization & deserialization are ready.
939 #define INIT_SYMBOL_STRING(name, description, key) \
940 { \
941 [[maybe_unused]] JSHandle<EcmaString> string = factory_->NewFromUtf8ReadOnly(description); \
942 }
943 DETECTOR_SYMBOL_LIST(INIT_SYMBOL_STRING)
944 #undef INIT_SYMBOL_STRING
945
946 #define INIT_PUBLIC_SYMBOL(name, description, key) \
947 JSHandle<JSSymbol> key##Symbol = factory_->NewSEmptySymbol(); \
948 JSHandle<EcmaString> key##String = factory_->NewFromUtf8ReadOnly(description); \
949 key##Symbol->SetDescription(thread_, key##String.GetTaggedValue()); \
950 key##Symbol->SetHashField(SymbolTable::Hash(key##String.GetTaggedValue()));
951 DETECTOR_SYMBOL_LIST(INIT_PUBLIC_SYMBOL)
952 #undef INIT_PUBLIC_SYMBOL
953
954 #define REGISTER_SYMBOL(name, Name) \
955 env->Set##Name##Symbol(thread_, name##Symbol);
956 BUILTIN_ALL_SYMBOLS(REGISTER_SYMBOL)
957 #undef REGISTER_SYMBOL
958 }
959
InitializeArrayPrototype(JSHandle<JSHClass> & arrBaseFuncInstanceHClass) const960 JSHandle<JSObject> Builtins::InitializeArrayPrototype(JSHandle<JSHClass> &arrBaseFuncInstanceHClass) const
961 {
962 JSHandle<JSObject> arrFuncPrototype = factory_->NewSharedOldSpaceJSObjectWithInit(arrBaseFuncInstanceHClass);
963 auto accessor = thread_->GlobalConstants()->GetSharedArrayLengthAccessor();
964 int32_t protoFieldIndex = JSSharedArray::LENGTH_INLINE_PROPERTY_INDEX;
965 static_assert(JSSharedArray::LENGTH_INLINE_PROPERTY_INDEX == 0);
966 arrFuncPrototype->SetPropertyInlinedProps(thread_, protoFieldIndex++, accessor);
967 return arrFuncPrototype;
968 }
969
InitializeArrayPrototypeHClass(const JSHandle<JSObject> & arrFuncPrototype) const970 JSHandle<JSHClass> Builtins::InitializeArrayPrototypeHClass(const JSHandle<JSObject> &arrFuncPrototype) const
971 {
972 JSHandle<JSTaggedValue> arrFuncPrototypeValue(arrFuncPrototype);
973 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(1);
974 PropertyAttributes attributes = PropertyAttributes::DefaultAccessor(true, false, false);
975 attributes.SetIsInlinedProps(true);
976 attributes.SetRepresentation(Representation::TAGGED);
977 layout->AddKey(thread_, 0, thread_->GlobalConstants()->GetHandledLengthString().GetTaggedValue(), attributes);
978
979 JSHandle<JSHClass> arrFuncInstanceHClass = factory_->NewSEcmaHClass(
980 JSSharedArray::SIZE, 1, JSType::JS_SHARED_ARRAY, arrFuncPrototypeValue, JSHandle<JSTaggedValue>::Cast(layout));
981 arrFuncInstanceHClass->SetExtensible(false);
982 return arrFuncInstanceHClass;
983 }
984
InitializeSharedArray(const JSHandle<GlobalEnv> & env,const JSHandle<JSObject> & sObjIHClass,JSHandle<JSFunction> & sFuncPrototype) const985 void Builtins::InitializeSharedArray(const JSHandle<GlobalEnv> &env, const JSHandle<JSObject> &sObjIHClass,
986 JSHandle<JSFunction> &sFuncPrototype) const
987 {
988 [[maybe_unused]] EcmaHandleScope scope(thread_);
989 const GlobalEnvConstants *globalConst = thread_->GlobalConstants();
990 // Arraybase.prototype
991 JSHandle<JSHClass> arrBaseFuncInstanceHClass = CreateSArrayPrototypeHClass(sObjIHClass);
992
993 // Array.prototype
994 JSHandle<JSObject> arrFuncPrototype = InitializeArrayPrototype(arrBaseFuncInstanceHClass);
995 // Array.prototype_or_hclass
996 JSHandle<JSHClass> arrFuncInstanceHClass = InitializeArrayPrototypeHClass(arrFuncPrototype);
997 int32_t protoFieldIndex = JSSharedArray::LENGTH_INLINE_PROPERTY_INDEX + 1;
998
999 // SharedArray.hclass
1000 JSHandle<JSHClass> arrayFuncHClass = CreateSArrayFunctionHClass(sFuncPrototype);
1001 arrayFuncHClass->SetExtensible(false);
1002 // SharedArray() = new Function()
1003 JSHandle<JSFunction> arrayFunction =
1004 factory_->NewSFunctionByHClass(reinterpret_cast<void *>(BuiltinsSharedArray::ArrayConstructor), arrayFuncHClass,
1005 FunctionKind::BUILTIN_CONSTRUCTOR);
1006
1007 InitializeSCtor(arrFuncInstanceHClass, arrayFunction, "SendableArray", FunctionLength::ZERO);
1008
1009 arrFuncPrototype->SetPropertyInlinedProps(thread_, protoFieldIndex++, arrayFunction.GetTaggedValue());
1010 JSHandle<JSObject> globalObject(thread_, env->GetGlobalObject());
1011 JSHandle<JSTaggedValue> nameString(factory_->NewFromUtf8ReadOnly("SendableArray"));
1012 PropertyDescriptor desc(thread_, JSHandle<JSTaggedValue>::Cast(arrayFunction), false, false, false);
1013 JSObject::DefineOwnProperty(thread_, globalObject, nameString, desc);
1014 RETURN_IF_ABRUPT_COMPLETION(thread_);
1015 for (const base::BuiltinFunctionEntry &entry : BuiltinsSharedArray::GetSharedArrayPrototypeFunctions()) {
1016 SetSFunction(env, arrFuncPrototype, entry.GetName(), entry.GetEntrypoint(), protoFieldIndex++,
1017 entry.GetLength(), entry.GetBuiltinStubId());
1018 }
1019
1020 // %ArrayPrototype% [ @@iterator ]
1021 JSHandle<JSTaggedValue> values(factory_->NewFromASCIIReadOnly("values"));
1022 JSHandle<JSTaggedValue> valuesFunc =
1023 JSObject::GetMethod(thread_, JSHandle<JSTaggedValue>::Cast(arrFuncPrototype), values);
1024 RETURN_IF_ABRUPT_COMPLETION(thread_);
1025 int32_t funcFieldIndex = 3; // 3: length, name, prototype
1026 for (const base::BuiltinFunctionEntry &entry : BuiltinsSharedArray::GetSharedArrayFunctions()) {
1027 SetSFunction(env, JSHandle<JSObject>(arrayFunction), entry.GetName(), entry.GetEntrypoint(), funcFieldIndex++,
1028 entry.GetLength(), entry.GetBuiltinStubId());
1029 }
1030
1031 // %SetPrototype% [ @@iterator ]
1032 arrFuncPrototype->SetPropertyInlinedProps(thread_, protoFieldIndex++, valuesFunc.GetTaggedValue());
1033
1034 // 22.1.2.5 get %Array% [ @@species ]
1035 JSHandle<JSTaggedValue> speciesGetter =
1036 CreateSGetterSetter(env, BuiltinsSharedArray::Species, "[Symbol.species]", FunctionLength::ZERO);
1037 SetSAccessor(JSHandle<JSObject>(arrayFunction), funcFieldIndex++, speciesGetter,
1038 globalConst->GetHandledUndefined());
1039
1040 // Array.prototype [ @@unscopables ]
1041 JSHandle<JSTaggedValue> unscopablesGetter =
1042 CreateSGetterSetter(env, BuiltinsSharedArray::Unscopables, "[Symbol.unscopables]", FunctionLength::ZERO);
1043 SetSAccessor(JSHandle<JSObject>(arrFuncPrototype), protoFieldIndex++, unscopablesGetter,
1044 globalConst->GetHandledUndefined());
1045 arrBaseFuncInstanceHClass->SetExtensible(false);
1046 env->SetSharedArrayFunction(thread_, arrayFunction);
1047 env->SetSharedArrayPrototype(thread_, arrFuncPrototype);
1048 }
1049
InitializeSharedBitVector(const JSHandle<GlobalEnv> & env,const JSHandle<JSObject> & sObjPrototype,const JSHandle<JSFunction> & sFuncPrototype) const1050 void Builtins::InitializeSharedBitVector(const JSHandle<GlobalEnv> &env, const JSHandle<JSObject> &sObjPrototype,
1051 const JSHandle<JSFunction> &sFuncPrototype) const
1052 {
1053 [[maybe_unused]] EcmaHandleScope scope(thread_);
1054 auto globalConst = const_cast<GlobalEnvConstants*>(thread_->GlobalConstants());
1055 // BitVector.prototype
1056 JSHandle<JSHClass> prototypeHClass = CreateBitVectorPrototypeHClass(sObjPrototype);
1057 JSHandle<JSObject> bitVectorFuncPrototype = factory_->NewSharedOldSpaceJSObjectWithInit(prototypeHClass);
1058 JSHandle<JSTaggedValue> bitVectorFuncPrototypeValue(bitVectorFuncPrototype);
1059
1060 // BitVector.prototype_or_hclass
1061 auto emptySLayout = globalConst->GetHandledEmptySLayoutInfo();
1062 JSHandle<JSHClass> bitVectorInstanceClass =
1063 factory_->NewSEcmaHClass(JSAPIBitVector::SIZE, 0,
1064 JSType::JS_API_BITVECTOR, bitVectorFuncPrototypeValue, emptySLayout);
1065
1066 // BitVector.hclass
1067 JSHandle<JSHClass> bitVectorFuncHClass = CreateBitVectorFunctionHClass(sFuncPrototype);
1068 bitVectorFuncHClass->SetExtensible(false);
1069
1070 // BitVector() = new Function()
1071 JSHandle<JSFunction> bitVectorFunction =
1072 factory_->NewSFunctionByHClass(reinterpret_cast<void *>(ContainersBitVector::BitVectorConstructor),
1073 bitVectorFuncHClass, FunctionKind::BUILTIN_CONSTRUCTOR);
1074 InitializeSCtor(bitVectorInstanceClass, bitVectorFunction, "BitVector", FunctionLength::ONE);
1075 // BitVector.prototype
1076 int32_t protoFieldIndex = 0;
1077 bitVectorFuncPrototype->SetPropertyInlinedProps(thread_, protoFieldIndex++, bitVectorFunction.GetTaggedValue());
1078 for (const base::BuiltinFunctionEntry &entry: ContainersBitVector::GetBitVectorPrototypeFunctions()) {
1079 SetSFunction(env, bitVectorFuncPrototype, entry.GetName(), entry.GetEntrypoint(), protoFieldIndex++,
1080 entry.GetLength(), entry.GetBuiltinStubId());
1081 }
1082 // @@StringTag
1083 JSHandle<JSTaggedValue> strTag(factory_->NewFromUtf8ReadOnly("BitVector"));
1084 bitVectorFuncPrototype->SetPropertyInlinedProps(thread_, protoFieldIndex++, strTag.GetTaggedValue());
1085
1086 JSHandle<JSTaggedValue> sizeGetter = CreateSGetterSetter(env, ContainersBitVector::GetSize, "size",
1087 FunctionLength::ZERO);
1088 JSHandle<JSTaggedValue> lengthGetter = CreateSGetterSetter(env, ContainersBitVector::GetSize, "length",
1089 FunctionLength::ZERO);
1090 SetSAccessor(bitVectorFuncPrototype, protoFieldIndex++, sizeGetter, globalConst->GetHandledUndefined());
1091 SetSAccessor(bitVectorFuncPrototype, protoFieldIndex++, lengthGetter, globalConst->GetHandledUndefined());
1092
1093 SetSFunction(env, bitVectorFuncPrototype, "[Symbol.iterator]",
1094 ContainersBitVector::GetIteratorObj, protoFieldIndex++, FunctionLength::ONE);
1095 env->SetBitVectorPrototype(thread_, bitVectorFuncPrototype);
1096 env->SetBitVectorFunction(thread_, bitVectorFunction);
1097 }
1098
1099
1100 // todo: remove sendableName when refactor
1101 #define BUILTIN_SHARED_TYPED_ARRAY_DEFINE_INITIALIZE(Type, ctorName, TYPE, bytesPerElement, sendableName) \
1102 void Builtins::InitializeS##Type(const JSHandle<GlobalEnv> &env, const JSHandle<JSHClass> &arrFuncClass) const \
1103 { \
1104 [[maybe_unused]] EcmaHandleScope scope(thread_); \
1105 const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); \
1106 auto emptySLayout = globalConst->GetHandledEmptySLayoutInfo(); \
1107 /* %SharedTypedArray%.prototype (where %SharedTypedArray% is one of Int8Array, Uint8Array, etc.) */ \
1108 JSHandle<JSObject> arrFuncPrototype = factory_->NewSharedOldSpaceJSObjectWithInit(arrFuncClass); \
1109 JSHandle<JSTaggedValue> arrFuncPrototypeValue(arrFuncPrototype); \
1110 /* %SharedTypedArray%.prototype_or_hclass */ \
1111 JSHandle<JSHClass> arrFuncInstanceHClass = factory_->NewSEcmaHClass( \
1112 JSSharedTypedArray::SIZE, 0, JSType::JS_SHARED_##TYPE, arrFuncPrototypeValue, emptySLayout); \
1113 JSHandle<JSHClass> arrFuncInstanceHClassOnHeap = factory_->NewSEcmaHClass( \
1114 JSSharedTypedArray::SIZE, 0, JSType::JS_SHARED_##TYPE, arrFuncPrototypeValue, emptySLayout); \
1115 arrFuncInstanceHClassOnHeap->SetIsOnHeap(true); \
1116 arrFuncInstanceHClass->SetHasConstructor(false); \
1117 /* %SharedTypedArray% = new Function() */ \
1118 JSHandle<JSHClass> specificTypedArrayFuncClass = JSHandle<JSHClass>::Cast( \
1119 env->GetSharedSpecificTypedArrayFunctionClass()); \
1120 JSHandle<JSFunction> arrayFunction = factory_->NewSFunctionByHClass( \
1121 reinterpret_cast<void *>(BuiltinsSharedTypedArray::Type##Constructor), specificTypedArrayFuncClass, \
1122 FunctionKind::BUILTIN_CONSTRUCTOR); \
1123 InitializeSCtor(arrFuncInstanceHClass, arrayFunction, #sendableName, FunctionLength::THREE); \
1124 JSHandle<JSObject> globalObject(thread_, env->GetGlobalObject()); \
1125 JSHandle<JSTaggedValue> nameString(factory_->NewFromUtf8ReadOnly(#sendableName)); \
1126 PropertyDescriptor desc(thread_, JSHandle<JSTaggedValue>::Cast(arrayFunction), false, false, false); \
1127 JSObject::DefineOwnProperty(thread_, globalObject, nameString, desc); \
1128 RETURN_IF_ABRUPT_COMPLETION(thread_); \
1129 /* 0: constructor index */ \
1130 uint32_t fieldIndex = 0; \
1131 arrFuncPrototype->SetPropertyInlinedProps(thread_, fieldIndex++, arrayFunction.GetTaggedValue()); \
1132 arrFuncPrototype->SetPropertyInlinedProps(thread_, fieldIndex, JSTaggedValue(bytesPerElement)); \
1133 fieldIndex = JSFunction::PROTOTYPE_INLINE_PROPERTY_INDEX + 1; \
1134 JSHandle<JSObject>(arrayFunction)->SetPropertyInlinedProps(thread_, fieldIndex, \
1135 JSTaggedValue(bytesPerElement)); \
1136 env->Set##ctorName##Function(thread_, arrayFunction); \
1137 env->Set##ctorName##FunctionPrototype(thread_, arrFuncPrototypeValue); \
1138 env->Set##ctorName##RootHclass(thread_, arrFuncInstanceHClass); \
1139 env->Set##ctorName##RootHclassOnHeap(thread_, arrFuncInstanceHClassOnHeap); \
1140 }
1141
BUILTIN_SHARED_TYPED_ARRAY_TYPES(BUILTIN_SHARED_TYPED_ARRAY_DEFINE_INITIALIZE)1142 BUILTIN_SHARED_TYPED_ARRAY_TYPES(BUILTIN_SHARED_TYPED_ARRAY_DEFINE_INITIALIZE)
1143 #undef BUILTIN_SHARED_TYPED_ARRAY_DEFINE_INITIALIZE
1144
1145 void Builtins::InitializeSTypedArray(const JSHandle<GlobalEnv> &env, const JSHandle<JSObject> &sObjPrototype,
1146 const JSHandle<JSFunction> &sFuncPrototype) const
1147 {
1148 [[maybe_unused]] EcmaHandleScope scope(thread_);
1149 const GlobalEnvConstants *globalConst = thread_->GlobalConstants();
1150 // SharedTypedArray.prototype
1151 JSHandle<JSHClass> typedArrFuncPrototypeHClass = CreateSTypedArrayPrototypeHClass(sObjPrototype);
1152 JSHandle<JSObject> typedArrFuncPrototype = factory_->NewSharedOldSpaceJSObjectWithInit(typedArrFuncPrototypeHClass);
1153 JSHandle<JSTaggedValue> typedArrFuncPrototypeValue(typedArrFuncPrototype);
1154
1155 // SharedTypedArray.prototype_or_hclass
1156 JSHandle<JSHClass> typedArrFuncInstanceHClass = CreateSSpecificTypedArrayInstanceHClass(
1157 typedArrFuncPrototype);
1158 // SharedTypedArray.hclass
1159 JSHandle<JSHClass> typedArrFuncHClass = CreateSTypedArrayFunctionHClass(sFuncPrototype);
1160 // SharedTypedArray = new Function()
1161 JSHandle<JSFunction> typedArrayFunction =
1162 factory_->NewSFunctionByHClass(reinterpret_cast<void *>(BuiltinsSharedTypedArray::TypedArrayBaseConstructor),
1163 typedArrFuncHClass, FunctionKind::BUILTIN_CONSTRUCTOR);
1164 InitializeSCtor(typedArrFuncInstanceHClass, typedArrayFunction, "SharedTypedArray", FunctionLength::ZERO);
1165
1166 // "constructor" property on the prototype
1167 uint32_t fieldIndex = 0; // constructor
1168 typedArrFuncPrototype->SetPropertyInlinedProps(thread_, fieldIndex++, typedArrayFunction.GetTaggedValue());
1169
1170 // SharedTypedArray.prototype method
1171 for (const base::BuiltinFunctionEntry &entry: BuiltinsSharedTypedArray::GetTypedArrayPrototypeFunctions()) {
1172 SetSFunction(env, typedArrFuncPrototype, entry.GetName(), entry.GetEntrypoint(), fieldIndex++,
1173 entry.GetLength(), entry.GetBuiltinStubId());
1174 }
1175 // SharedTypedArray.prototype get accessor
1176 for (const base::BuiltinFunctionEntry &entry: BuiltinsSharedTypedArray::GetTypedArrayPrototypeAccessors()) {
1177 JSHandle<JSTaggedValue> getter = CreateSGetterSetter(env, entry.GetEntrypoint(),
1178 entry.GetName(), entry.GetLength());
1179 SetSAccessor(typedArrFuncPrototype, fieldIndex++, getter, globalConst->GetHandledUndefined());
1180 }
1181
1182 // %SharedTypedArray%.prototype [ @@iterator ] ( )
1183 JSHandle<JSTaggedValue> values(factory_->NewFromASCIIReadOnly("values"));
1184 JSHandle<JSTaggedValue> valuesFunc =
1185 JSObject::GetMethod(thread_, JSHandle<JSTaggedValue>::Cast(typedArrFuncPrototype), values);
1186 RETURN_IF_ABRUPT_COMPLETION(thread_);
1187 typedArrFuncPrototype->SetPropertyInlinedProps(thread_, fieldIndex++, valuesFunc.GetTaggedValue());
1188
1189 // 22.2.3.31 get %SharedTypedArray%.prototype [ @@toStringTag ]
1190 JSHandle<JSTaggedValue> toStringTagGetter =
1191 CreateSGetterSetter(env, BuiltinsSharedTypedArray::ToStringTag, "[Symbol.toStringTag]", FunctionLength::ZERO);
1192 SetSAccessor(typedArrFuncPrototype, fieldIndex++, toStringTagGetter, globalConst->GetHandledUndefined());
1193
1194 uint32_t funcFieldIndex = JSFunction::PROTOTYPE_INLINE_PROPERTY_INDEX + 1; // length, name, prototype, ...
1195 // SharedTypedArray method
1196 for (const base::BuiltinFunctionEntry &entry: BuiltinsSharedTypedArray::GetTypedArrayFunctions()) {
1197 SetSFunction(env, JSHandle<JSObject>(typedArrayFunction), entry.GetName(), entry.GetEntrypoint(),
1198 funcFieldIndex++, entry.GetLength(), entry.GetBuiltinStubId());
1199 }
1200
1201 // 22.2.2.4 get %SharedTypedArray% [ @@species ]
1202 JSHandle<JSTaggedValue> speciesGetter =
1203 CreateSGetterSetter(env, BuiltinsSharedTypedArray::Species, "[Symbol.species]", FunctionLength::ZERO);
1204 SetSAccessor(JSHandle<JSObject>(typedArrayFunction), funcFieldIndex++, speciesGetter,
1205 globalConst->GetHandledUndefined());
1206
1207 env->SetSharedTypedArrayFunction(thread_, typedArrayFunction.GetTaggedValue());
1208 env->SetSharedTypedArrayPrototype(thread_, typedArrFuncPrototype);
1209
1210 JSHandle<JSHClass> specificTypedArrayFuncClass = CreateSSpecificTypedArrayFuncHClass(typedArrayFunction);
1211 env->SetSharedSpecificTypedArrayFunctionClass(thread_, specificTypedArrayFuncClass);
1212
1213 #define BUILTIN_SHARED_TYPED_ARRAY_CALL_INITIALIZE(Type, ctorName, TYPE, bytesPerElement, sendableName) \
1214 InitializeS##Type(env, typedArrFuncInstanceHClass);
1215 BUILTIN_SHARED_TYPED_ARRAY_TYPES(BUILTIN_SHARED_TYPED_ARRAY_CALL_INITIALIZE)
1216 #undef BUILTIN_SHARED_TYPED_ARRAY_CALL_INITIALIZE
1217 }
1218
CreateSTypedArrayPrototypeHClass(const JSHandle<JSObject> & sObjPrototype) const1219 JSHandle<JSHClass> Builtins::CreateSTypedArrayPrototypeHClass(const JSHandle<JSObject> &sObjPrototype) const
1220 {
1221 uint32_t index = 0;
1222 auto env = vm_->GetGlobalEnv();
1223 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
1224 attributes.SetIsInlinedProps(true);
1225 attributes.SetRepresentation(Representation::TAGGED);
1226 auto properties = BuiltinsSharedTypedArray::GetPrototypeProperties();
1227 uint32_t length = properties.size();
1228 ASSERT(length == BuiltinsSharedTypedArray::GetNumPrototypeInlinedProperties());
1229 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
1230 JSHandle<JSTaggedValue> keyString;
1231 for (const auto &[key, isAccessor] : properties) {
1232 attributes.SetOffset(index);
1233 attributes.SetIsAccessor(isAccessor);
1234 if (key == "[Symbol.iterator]") {
1235 keyString = env->GetIteratorSymbol();
1236 } else if (key == "[Symbol.toStringTag]") {
1237 keyString = env->GetToStringTagSymbol();
1238 } else {
1239 keyString = JSHandle<JSTaggedValue>(factory_->NewFromUtf8ReadOnly(key));
1240 }
1241 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
1242 }
1243 JSHandle<JSHClass> sTypedArrayPrototypeHClass =
1244 factory_->NewSEcmaHClass(JSSharedObject::SIZE, length, JSType::JS_SHARED_OBJECT,
1245 JSHandle<JSTaggedValue>(sObjPrototype),
1246 JSHandle<JSTaggedValue>(layout));
1247 return sTypedArrayPrototypeHClass;
1248 }
1249
CreateSTypedArrayFunctionHClass(const JSHandle<JSFunction> & sFuncPrototype) const1250 JSHandle<JSHClass> Builtins::CreateSTypedArrayFunctionHClass(const JSHandle<JSFunction> &sFuncPrototype) const
1251 {
1252 uint32_t index = 0;
1253 auto env = vm_->GetGlobalEnv();
1254 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
1255 attributes.SetIsInlinedProps(true);
1256 attributes.SetRepresentation(Representation::TAGGED);
1257 auto properties = BuiltinsSharedTypedArray::GetFunctionProperties();
1258 uint32_t length = properties.size();
1259 JSHandle<JSTaggedValue> keyString;
1260 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
1261 for (const auto &[key, isAccessor] : properties) {
1262 attributes.SetOffset(index);
1263 attributes.SetIsAccessor(isAccessor);
1264 if (key == "[Symbol.species]") {
1265 keyString = env->GetSpeciesSymbol();
1266 } else {
1267 keyString = JSHandle<JSTaggedValue>(factory_->NewFromUtf8ReadOnly(key));
1268 }
1269 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
1270 }
1271 JSHandle<JSHClass> sobjPrototypeHClass =
1272 factory_->NewSEcmaHClass(JSSharedFunction::SIZE, length, JSType::JS_SHARED_FUNCTION,
1273 JSHandle<JSTaggedValue>(sFuncPrototype), JSHandle<JSTaggedValue>(layout));
1274 sobjPrototypeHClass->SetConstructor(true);
1275 sobjPrototypeHClass->SetCallable(true);
1276 return sobjPrototypeHClass;
1277 }
1278
CreateSSpecificTypedArrayFuncHClass(const JSHandle<JSFunction> & sFuncPrototype) const1279 JSHandle<JSHClass> Builtins::CreateSSpecificTypedArrayFuncHClass(const JSHandle<JSFunction> &sFuncPrototype) const
1280 {
1281 uint32_t index = 0;
1282 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
1283 attributes.SetIsInlinedProps(true);
1284 attributes.SetRepresentation(Representation::TAGGED);
1285 auto properties = BuiltinsSharedTypedArray::GetSpecificFunctionProperties();
1286 uint32_t length = properties.size();
1287 JSHandle<JSTaggedValue> keyString;
1288 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
1289 for (const auto &[key, isAccessor] : properties) {
1290 attributes.SetOffset(index);
1291 attributes.SetIsAccessor(isAccessor);
1292 keyString = JSHandle<JSTaggedValue>(factory_->NewFromUtf8ReadOnly(key));
1293 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
1294 }
1295 JSHandle<JSHClass> sobjPrototypeHClass =
1296 factory_->NewSEcmaHClass(JSSharedFunction::SIZE, length, JSType::JS_SHARED_FUNCTION,
1297 JSHandle<JSTaggedValue>(sFuncPrototype), JSHandle<JSTaggedValue>(layout));
1298 sobjPrototypeHClass->SetConstructor(true);
1299 sobjPrototypeHClass->SetCallable(true);
1300 return sobjPrototypeHClass;
1301 }
1302
CreateSSpecificTypedArrayInstanceHClass(const JSHandle<JSObject> & sObjPrototype) const1303 JSHandle<JSHClass> Builtins::CreateSSpecificTypedArrayInstanceHClass(const JSHandle<JSObject> &sObjPrototype) const
1304 {
1305 uint32_t index = 0;
1306 PropertyAttributes attributes = PropertyAttributes::Default(false, false, false);
1307 attributes.SetIsInlinedProps(true);
1308 attributes.SetRepresentation(Representation::TAGGED);
1309 auto properties = BuiltinsSharedTypedArray::GetSpecificArrayPrototypeProperties();
1310 uint32_t length = properties.size();
1311 JSHandle<LayoutInfo> layout = factory_->CreateSLayoutInfo(length);
1312 JSHandle<JSTaggedValue> keyString;
1313 for (const auto &[key, isAccessor] : properties) {
1314 attributes.SetOffset(index);
1315 attributes.SetIsAccessor(isAccessor);
1316 keyString = JSHandle<JSTaggedValue>(factory_->NewFromUtf8ReadOnly(key));
1317 layout->AddKey(thread_, index++, keyString.GetTaggedValue(), attributes);
1318 }
1319 JSHandle<JSHClass> sSpecificTypedArrayPrototypeHClass =
1320 factory_->NewSEcmaHClass(JSSharedObject::SIZE, length, JSType::JS_SHARED_OBJECT,
1321 JSHandle<JSTaggedValue>(sObjPrototype),
1322 JSHandle<JSTaggedValue>(layout));
1323 return sSpecificTypedArrayPrototypeHClass;
1324 }
1325 } // namespace panda::ecmascript
1326