1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef ECMASCRIPT_COMPILER_HCR_CIRCUIT_BUILDER_H
17 #define ECMASCRIPT_COMPILER_HCR_CIRCUIT_BUILDER_H
18
19 #include "ecmascript/compiler/circuit_builder_helper.h"
20 #include "ecmascript/mem/region.h"
21 #include "ecmascript/js_function.h"
22
23 namespace panda::ecmascript::kungfu {
24
IsSpecial(GateRef x,JSTaggedType type)25 GateRef CircuitBuilder::IsSpecial(GateRef x, JSTaggedType type)
26 {
27 auto specialValue = circuit_->GetConstantGate(
28 MachineType::I64, type, GateType::TaggedValue());
29
30 return Equal(x, specialValue);
31 }
32
IsJSHClass(GateRef obj)33 inline GateRef CircuitBuilder::IsJSHClass(GateRef obj)
34 {
35 return Int32Equal(GetObjectType(LoadHClass(obj)), Int32(static_cast<int32_t>(JSType::HCLASS)));
36 }
37
IsJSFunction(GateRef obj)38 inline GateRef CircuitBuilder::IsJSFunction(GateRef obj)
39 {
40 GateRef objectType = GetObjectType(LoadHClass(obj));
41 GateRef greater = Int32GreaterThanOrEqual(objectType,
42 Int32(static_cast<int32_t>(JSType::JS_FUNCTION_FIRST)));
43 GateRef less = Int32LessThanOrEqual(objectType,
44 Int32(static_cast<int32_t>(JSType::JS_FUNCTION_LAST)));
45 return BitAnd(greater, less);
46 }
47
IsJsType(GateRef obj,JSType type)48 GateRef CircuitBuilder::IsJsType(GateRef obj, JSType type)
49 {
50 GateRef objectType = GetObjectType(LoadHClass(obj));
51 return Equal(objectType, Int32(static_cast<int32_t>(type)));
52 }
53
IsJSObject(GateRef obj)54 GateRef CircuitBuilder::IsJSObject(GateRef obj)
55 {
56 Label entryPass(env_);
57 SubCfgEntry(&entryPass);
58 DEFVALUE(result, env_, VariableType::BOOL(), False());
59 Label heapObj(env_);
60 Label exit(env_);
61 GateRef isHeapObject = TaggedIsHeapObject(obj);
62 BRANCH(isHeapObject, &heapObj, &exit);
63 Bind(&heapObj);
64 {
65 GateRef objectType = GetObjectType(LoadHClass(obj));
66 result = BitAnd(
67 Int32LessThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT_LAST))),
68 Int32GreaterThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT_FIRST))));
69 Jump(&exit);
70 }
71 Bind(&exit);
72 auto ret = *result;
73 SubCfgExit();
74 return ret;
75 }
76
IsCallableFromBitField(GateRef bitfield)77 GateRef CircuitBuilder::IsCallableFromBitField(GateRef bitfield)
78 {
79 return NotEqual(
80 Int32And(Int32LSR(bitfield, Int32(JSHClass::CallableBit::START_BIT)),
81 Int32((1LU << JSHClass::CallableBit::SIZE) - 1)),
82 Int32(0));
83 }
84
IsCallable(GateRef obj)85 GateRef CircuitBuilder::IsCallable(GateRef obj)
86 {
87 GateRef hClass = LoadHClass(obj);
88 GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
89 GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
90 return IsCallableFromBitField(bitfield);
91 }
92
AlreadyDeopt(GateRef method)93 GateRef CircuitBuilder::AlreadyDeopt(GateRef method)
94 {
95 GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
96 GateRef extraLiteralInfo = Load(VariableType::INT64(), method, extraLiteralInfoOffset);
97 return AlreadyDeoptFromExtraLiteralInfo(extraLiteralInfo);
98 }
99
AlreadyDeoptFromExtraLiteralInfo(GateRef callfield)100 GateRef CircuitBuilder::AlreadyDeoptFromExtraLiteralInfo(GateRef callfield)
101 {
102 return NotEqual(Int64And(Int64LSR(callfield, Int64(Method::DeoptTypeBits::START_BIT)),
103 Int64((1LU << Method::DeoptTypeBits::SIZE) - 1)),
104 Int64(0));
105 }
106
IsPrototypeHClass(GateRef hClass)107 GateRef CircuitBuilder::IsPrototypeHClass(GateRef hClass)
108 {
109 GateRef bitfield = LoadConstOffset(VariableType::INT32(), hClass, JSHClass::BIT_FIELD_OFFSET);
110 return TruncInt32ToInt1(Int32And(Int32LSR(bitfield,
111 Int32(JSHClass::IsPrototypeBit::START_BIT)),
112 Int32((1LU << JSHClass::IsPrototypeBit::SIZE) - 1)));
113 }
114
IsJsProxy(GateRef obj)115 GateRef CircuitBuilder::IsJsProxy(GateRef obj)
116 {
117 GateRef objectType = GetObjectType(LoadHClass(obj));
118 return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_PROXY)));
119 }
120
IsTreeString(GateRef obj)121 GateRef CircuitBuilder::IsTreeString(GateRef obj)
122 {
123 GateRef objectType = GetObjectType(LoadHClass(obj));
124 return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::TREE_STRING)));
125 }
126
IsSlicedString(GateRef obj)127 GateRef CircuitBuilder::IsSlicedString(GateRef obj)
128 {
129 GateRef objectType = GetObjectType(LoadHClass(obj));
130 return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::SLICED_STRING)));
131 }
132
IsLineString(GateRef obj)133 GateRef CircuitBuilder::IsLineString(GateRef obj)
134 {
135 GateRef objectType = GetObjectType(LoadHClass(obj));
136 return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::LINE_STRING)));
137 }
138
IsConstantString(GateRef obj)139 GateRef CircuitBuilder::IsConstantString(GateRef obj)
140 {
141 GateRef objectType = GetObjectType(LoadHClass(obj));
142 return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::CONSTANT_STRING)));
143 }
144
ComputeSizeUtf8(GateRef length)145 GateRef CircuitBuilder::ComputeSizeUtf8(GateRef length)
146 {
147 return PtrAdd(IntPtr(LineEcmaString::DATA_OFFSET), length);
148 }
149
ComputeSizeUtf16(GateRef length)150 GateRef CircuitBuilder::ComputeSizeUtf16(GateRef length)
151 {
152 return PtrAdd(IntPtr(LineEcmaString::DATA_OFFSET), PtrMul(length, IntPtr(sizeof(uint16_t))));
153 }
154
AlignUp(GateRef x,GateRef alignment)155 GateRef CircuitBuilder::AlignUp(GateRef x, GateRef alignment)
156 {
157 GateRef x1 = PtrAdd(x, PtrSub(alignment, IntPtr(1)));
158 return IntPtrAnd(x1, IntPtrNot(PtrSub(alignment, IntPtr(1))));
159 }
160
IsDictionaryMode(GateRef object)161 inline GateRef CircuitBuilder::IsDictionaryMode(GateRef object)
162 {
163 GateRef type = GetObjectType(LoadHClass(object));
164 return Int32Equal(type, Int32(static_cast<int32_t>(JSType::TAGGED_DICTIONARY)));
165 }
166
IsStableArguments(GateRef hClass)167 GateRef CircuitBuilder::IsStableArguments(GateRef hClass)
168 {
169 GateRef objectType = GetObjectType(hClass);
170 GateRef isJsArguments = Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_ARGUMENTS)));
171 GateRef isStableElements = IsStableElements(hClass);
172 return BitAnd(isStableElements, isJsArguments);
173 }
174
IsStableArray(GateRef hClass)175 GateRef CircuitBuilder::IsStableArray(GateRef hClass)
176 {
177 GateRef objectType = GetObjectType(hClass);
178 GateRef isJsArray = Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_ARRAY)));
179 GateRef isStableElements = IsStableElements(hClass);
180 return BitAnd(isStableElements, isJsArray);
181 }
182
IsAOTLiteralInfo(GateRef x)183 GateRef CircuitBuilder::IsAOTLiteralInfo(GateRef x)
184 {
185 GateRef objType = GetObjectType(LoadHClass(x));
186 GateRef isAOTLiteralInfoObj = Equal(objType,
187 Int32(static_cast<int32_t>(JSType::AOT_LITERAL_INFO)));
188 return isAOTLiteralInfoObj;
189 }
190
LoadHClass(GateRef object)191 GateRef CircuitBuilder::LoadHClass(GateRef object)
192 {
193 GateRef offset = IntPtr(TaggedObject::HCLASS_OFFSET);
194 return Load(VariableType::JS_POINTER(), object, offset);
195 }
196
LoadHClassByConstOffset(GateRef object)197 GateRef CircuitBuilder::LoadHClassByConstOffset(GateRef object)
198 {
199 return LoadConstOffset(VariableType::JS_POINTER(), object, TaggedObject::HCLASS_OFFSET);
200 }
201
LoadPrototype(GateRef hclass)202 GateRef CircuitBuilder::LoadPrototype(GateRef hclass)
203 {
204 return LoadConstOffset(VariableType::JS_POINTER(), hclass, JSHClass::PROTOTYPE_OFFSET);
205 }
206
LoadPrototypeHClass(GateRef object)207 GateRef CircuitBuilder::LoadPrototypeHClass(GateRef object)
208 {
209 GateRef objectHClass = LoadHClassByConstOffset(object);
210 GateRef objectPrototype = LoadPrototype(objectHClass);
211 return LoadHClass(objectPrototype);
212 }
213
LoadPrototypeOfPrototypeHClass(GateRef object)214 GateRef CircuitBuilder::LoadPrototypeOfPrototypeHClass(GateRef object)
215 {
216 GateRef objectHClass = LoadHClassByConstOffset(object);
217 GateRef objectPrototype = LoadPrototype(objectHClass);
218 GateRef objectPrototypeHClass = LoadHClassByConstOffset(objectPrototype);
219 GateRef objectPrototypeOfPrototype = LoadPrototype(objectPrototypeHClass);
220 return LoadHClass(objectPrototypeOfPrototype);
221 }
222
GetObjectSizeFromHClass(GateRef hClass)223 GateRef CircuitBuilder::GetObjectSizeFromHClass(GateRef hClass)
224 {
225 // NOTE: check for special case of string and TAGGED_ARRAY
226 GateRef bitfield = Load(VariableType::INT32(), hClass, IntPtr(JSHClass::BIT_FIELD1_OFFSET));
227 GateRef objectSizeInWords = Int32And(Int32LSR(bitfield,
228 Int32(JSHClass::ObjectSizeInWordsBits::START_BIT)),
229 Int32((1LU << JSHClass::ObjectSizeInWordsBits::SIZE) - 1));
230 return PtrMul(ZExtInt32ToPtr(objectSizeInWords), IntPtr(JSTaggedValue::TaggedTypeSize()));
231 }
232
IsDictionaryModeByHClass(GateRef hClass)233 GateRef CircuitBuilder::IsDictionaryModeByHClass(GateRef hClass)
234 {
235 GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
236 GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
237 return NotEqual(Int32And(Int32LSR(bitfield,
238 Int32(JSHClass::IsDictionaryBit::START_BIT)),
239 Int32((1LU << JSHClass::IsDictionaryBit::SIZE) - 1)),
240 Int32(0));
241 }
242
StoreHClass(GateRef glue,GateRef object,GateRef hClass)243 void CircuitBuilder::StoreHClass(GateRef glue, GateRef object, GateRef hClass)
244 {
245 Store(VariableType::JS_POINTER(), glue, object, IntPtr(TaggedObject::HCLASS_OFFSET), hClass,
246 MemoryAttribute::NeedBarrier());
247 }
248
StoreHClassWithoutBarrier(GateRef glue,GateRef object,GateRef hClass)249 void CircuitBuilder::StoreHClassWithoutBarrier(GateRef glue, GateRef object, GateRef hClass)
250 {
251 Store(VariableType::JS_POINTER(), glue, object, IntPtr(TaggedObject::HCLASS_OFFSET), hClass,
252 MemoryAttribute::NoBarrier());
253 }
254
StorePrototype(GateRef glue,GateRef hclass,GateRef prototype)255 void CircuitBuilder::StorePrototype(GateRef glue, GateRef hclass, GateRef prototype)
256 {
257 Store(VariableType::JS_POINTER(), glue, hclass, IntPtr(JSHClass::PROTOTYPE_OFFSET), prototype);
258 }
259
GetObjectType(GateRef hClass)260 GateRef CircuitBuilder::GetObjectType(GateRef hClass)
261 {
262 GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
263 GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
264 return Int32And(bitfield, Int32((1LU << JSHClass::ObjectTypeBits::SIZE) - 1));
265 }
266
CanFastCall(GateRef jsFunc)267 inline GateRef CircuitBuilder::CanFastCall(GateRef jsFunc)
268 {
269 GateRef bitFieldOffset = IntPtr(JSFunctionBase::BIT_FIELD_OFFSET);
270 GateRef bitField = Load(VariableType::INT32(), jsFunc, bitFieldOffset);
271 return Int32NotEqual(
272 Int32And(
273 Int32LSR(bitField, Int32(JSFunctionBase::IsFastCallBit::START_BIT)),
274 Int32((1LU << JSFunctionBase::IsFastCallBit::SIZE) - 1)),
275 Int32(0));
276 }
277
GetElementsKindByHClass(GateRef hClass)278 GateRef CircuitBuilder::GetElementsKindByHClass(GateRef hClass)
279 {
280 GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
281 GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
282 return Int32And(Int32LSR(bitfield,
283 Int32(JSHClass::ElementsKindBits::START_BIT)),
284 Int32((1LLU << JSHClass::ElementsKindBits::SIZE) - 1));
285 }
286
HasConstructorByHClass(GateRef hClass)287 GateRef CircuitBuilder::HasConstructorByHClass(GateRef hClass)
288 {
289 GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
290 GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
291 return NotEqual(Int32And(Int32LSR(bitfield,
292 Int32(JSHClass::HasConstructorBits::START_BIT)),
293 Int32((1LU << JSHClass::HasConstructorBits::SIZE) - 1)),
294 Int32(0));
295 }
296
IsDictionaryElement(GateRef hClass)297 GateRef CircuitBuilder::IsDictionaryElement(GateRef hClass)
298 {
299 GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
300 GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
301 return NotEqual(Int32And(Int32LSR(bitfield,
302 Int32(JSHClass::DictionaryElementBits::START_BIT)),
303 Int32((1LU << JSHClass::DictionaryElementBits::SIZE) - 1)),
304 Int32(0));
305 }
306
IsStableElements(GateRef hClass)307 GateRef CircuitBuilder::IsStableElements(GateRef hClass)
308 {
309 GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
310 GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
311 return NotEqual(Int32And(Int32LSR(bitfield,
312 Int32(JSHClass::IsStableElementsBit::START_BIT)),
313 Int32((1LU << JSHClass::IsStableElementsBit::SIZE) - 1)),
314 Int32(0));
315 }
316
IsJSArrayPrototypeModified(GateRef hClass)317 GateRef CircuitBuilder::IsJSArrayPrototypeModified(GateRef hClass)
318 {
319 GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
320 GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
321 return NotEqual(Int32And(Int32LSR(bitfield,
322 Int32(JSHClass::IsJSArrayPrototypeModifiedBit::START_BIT)),
323 Int32((1LU << JSHClass::IsJSArrayPrototypeModifiedBit::SIZE) - 1)),
324 Int32(0));
325 }
326
HasConstructor(GateRef object)327 GateRef CircuitBuilder::HasConstructor(GateRef object)
328 {
329 GateRef hClass = LoadHClass(object);
330 return HasConstructorByHClass(hClass);
331 }
332
IsConstructor(GateRef object)333 GateRef CircuitBuilder::IsConstructor(GateRef object)
334 {
335 GateRef hClass = LoadHClass(object);
336 GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
337 GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
338 // decode
339 return Int32NotEqual(
340 Int32And(Int32LSR(bitfield, Int32(JSHClass::ConstructorBit::START_BIT)),
341 Int32((1LU << JSHClass::ConstructorBit::SIZE) - 1)),
342 Int32(0));
343 }
344
IsClassConstructor(GateRef object)345 GateRef CircuitBuilder::IsClassConstructor(GateRef object)
346 {
347 GateRef hClass = LoadHClass(object);
348 GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
349 GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
350 return IsClassConstructorWithBitField(bitfield);
351 }
352
IsClassConstructorWithBitField(GateRef bitfield)353 GateRef CircuitBuilder::IsClassConstructorWithBitField(GateRef bitfield)
354 {
355 auto classBitMask = 1LU << JSHClass::IsClassConstructorOrPrototypeBit::START_BIT;
356 auto ctorBitMask = 1LU << JSHClass::ConstructorBit::START_BIT;
357 auto mask = Int32(classBitMask | ctorBitMask);
358 auto classCtor = Int32And(bitfield, mask);
359 return Int32Equal(classCtor, mask);
360 }
361
IsExtensible(GateRef object)362 GateRef CircuitBuilder::IsExtensible(GateRef object)
363 {
364 GateRef hClass = LoadHClass(object);
365 GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
366 GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
367 return NotEqual(Int32And(Int32LSR(bitfield,
368 Int32(JSHClass::ExtensibleBit::START_BIT)),
369 Int32((1LU << JSHClass::ExtensibleBit::SIZE) - 1)),
370 Int32(0));
371 }
372
IsClassPrototype(GateRef object)373 GateRef CircuitBuilder::IsClassPrototype(GateRef object)
374 {
375 GateRef hClass = LoadHClass(object);
376 GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
377 GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
378 // decode
379 return IsClassPrototypeWithBitField(bitfield);
380 }
381
IsClassPrototypeWithBitField(GateRef bitfield)382 GateRef CircuitBuilder::IsClassPrototypeWithBitField(GateRef bitfield)
383 {
384 auto classBitMask = 1LU << JSHClass::IsClassConstructorOrPrototypeBit::START_BIT;
385 auto ptBitMask = 1LU << JSHClass::IsPrototypeBit::START_BIT;
386 auto mask = Int32(classBitMask | ptBitMask);
387 auto classPt = Int32And(bitfield, mask);
388 return Int32Equal(classPt, mask);
389 }
390
CreateWeakRef(GateRef x)391 GateRef CircuitBuilder::CreateWeakRef(GateRef x)
392 {
393 return PtrAdd(x, IntPtr(JSTaggedValue::TAG_WEAK));
394 }
395
LoadObjectFromWeakRef(GateRef x)396 GateRef CircuitBuilder::LoadObjectFromWeakRef(GateRef x)
397 {
398 return PtrAdd(x, IntPtr(-JSTaggedValue::TAG_WEAK));
399 }
400
401 // ctor is base but not builtin
IsBase(GateRef ctor)402 inline GateRef CircuitBuilder::IsBase(GateRef ctor)
403 {
404 GateRef method = GetMethodFromFunction(ctor);
405 GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
406 GateRef bitfield = Load(VariableType::INT32(), method, extraLiteralInfoOffset);
407
408 GateRef kind = Int32And(Int32LSR(bitfield, Int32(MethodLiteral::FunctionKindBits::START_BIT)),
409 Int32((1LU << MethodLiteral::FunctionKindBits::SIZE) - 1));
410 return Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(FunctionKind::CLASS_CONSTRUCTOR)));
411 }
412
IsDerived(GateRef ctor)413 inline GateRef CircuitBuilder::IsDerived(GateRef ctor)
414 {
415 GateRef method = GetMethodFromFunction(ctor);
416 GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
417 GateRef bitfield = Load(VariableType::INT32(), method, extraLiteralInfoOffset);
418
419 GateRef kind = Int32And(Int32LSR(bitfield, Int32(MethodLiteral::FunctionKindBits::START_BIT)),
420 Int32((1LU << MethodLiteral::FunctionKindBits::SIZE) - 1));
421 return Int32Equal(kind, Int32(static_cast<int32_t>(FunctionKind::DERIVED_CONSTRUCTOR)));
422 }
423
GetMethodId(GateRef func)424 inline GateRef CircuitBuilder::GetMethodId(GateRef func)
425 {
426 GateRef method = GetMethodFromFunction(func);
427 GateRef literalInfoOffset = IntPtr(Method::LITERAL_INFO_OFFSET);
428 GateRef literalInfo = Load(VariableType::INT64(), method, literalInfoOffset);
429 GateRef methodId = Int64And(Int64LSR(literalInfo, Int64(MethodLiteral::MethodIdBits::START_BIT)),
430 Int64((1LLU << MethodLiteral::MethodIdBits::SIZE) - 1));
431 return methodId;
432 }
433
GetBuiltinsId(GateRef func)434 inline GateRef CircuitBuilder::GetBuiltinsId(GateRef func)
435 {
436 GateRef method = GetMethodFromFunction(func);
437 GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
438 GateRef extraLiteralInfo = Load(VariableType::INT64(), method, extraLiteralInfoOffset);
439 GateRef builtinsId = Int64And(Int64LSR(extraLiteralInfo, Int64(MethodLiteral::BuiltinIdBits::START_BIT)),
440 Int64((1LLU << MethodLiteral::BuiltinIdBits::SIZE) - 1));
441 return builtinsId;
442 }
443 }
444 #endif // ECMASCRIPT_COMPILER_HCR_CIRCUIT_BUILDER_H
445