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