• 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/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