• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_MCR_CIRCUIT_BUILDER_H
17 #define ECMASCRIPT_COMPILER_MCR_CIRCUIT_BUILDER_H
18 
19 #include "ecmascript/compiler/circuit_builder.h"
20 #include "ecmascript/compiler/circuit_builder_helper.h"
21 #include "ecmascript/global_env.h"
22 #include "ecmascript/mem/region.h"
23 #include "ecmascript/method.h"
24 #include "ecmascript/js_function.h"
25 
26 namespace panda::ecmascript::kungfu {
27 
28 // bit operation
29 
TaggedIsInt(GateRef x)30 GateRef CircuitBuilder::TaggedIsInt(GateRef x)
31 {
32     x = ChangeTaggedPointerToInt64(x);
33     return Equal(Int64And(x, Int64(JSTaggedValue::TAG_MARK)),
34                  Int64(JSTaggedValue::TAG_INT));
35 }
36 
TaggedIsDouble(GateRef x)37 GateRef CircuitBuilder::TaggedIsDouble(GateRef x)
38 {
39     x = ChangeTaggedPointerToInt64(x);
40     x = Int64And(x, Int64(JSTaggedValue::TAG_MARK));
41     auto left = NotEqual(x, Int64(JSTaggedValue::TAG_INT));
42     auto right = NotEqual(x, Int64(JSTaggedValue::TAG_OBJECT));
43     return BitAnd(left, right);
44 }
45 
TaggedIsObject(GateRef x)46 GateRef CircuitBuilder::TaggedIsObject(GateRef x)
47 {
48     x = ChangeTaggedPointerToInt64(x);
49     return Equal(Int64And(x, Int64(JSTaggedValue::TAG_MARK)),
50                  Int64(JSTaggedValue::TAG_OBJECT));
51 }
52 
TaggedIsNumber(GateRef x)53 GateRef CircuitBuilder::TaggedIsNumber(GateRef x)
54 {
55     return BoolNot(TaggedIsObject(x));
56 }
57 
TaggedIsNumeric(GateRef glue,GateRef x)58 GateRef CircuitBuilder::TaggedIsNumeric(GateRef glue, GateRef x)
59 {
60     return LogicOrBuilder(env_).Or(TaggedIsNumber(x)).Or(TaggedIsBigInt(glue, x)).Done();
61 }
62 
TaggedObjectIsString(GateRef glue,GateRef obj)63 GateRef CircuitBuilder::TaggedObjectIsString(GateRef glue, GateRef obj)
64 {
65     GateRef objectType = GetObjectType(LoadHClass(glue, obj));
66     return BitAnd(
67         Int32LessThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::STRING_LAST))),
68         Int32GreaterThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::STRING_FIRST))));
69 }
70 
TaggedObjectIsString(GateRef glue,GateRef obj,const CompilationEnv * compilationEnv)71 GateRef CircuitBuilder::TaggedObjectIsString(GateRef glue, GateRef obj,
72                                              [[maybe_unused]] const CompilationEnv *compilationEnv)
73 {
74 #ifdef IMPOSSIBLE
75     if (compilationEnv != nullptr && compilationEnv->SupportIntrinsic()) {
76         std::string comment = "tagged_obj_is_string_intrinsic";
77         auto currentLabel = env_->GetCurrentLabel();
78         auto currentDepend = currentLabel->GetDepend();
79         GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
80         GateRef stringFirst = Int32(static_cast<int32_t>(JSType::STRING_FIRST));
81         GateRef stringLast = Int32(static_cast<int32_t>(JSType::STRING_LAST));
82         GateRef checkTaggedObjectIsString = GetCircuit()->NewGate(circuit_->CheckTaggedObjectIsString(),
83             MachineType::I1, { currentDepend, glue, obj, bitfieldOffset,  stringFirst, stringLast},
84             GateType::NJSValue(), comment.c_str());
85         currentLabel->SetDepend(checkTaggedObjectIsString);
86         return checkTaggedObjectIsString;
87     }
88 #endif
89     return TaggedObjectIsString(glue, obj);
90 }
91 
TaggedObjectIsShared(GateRef glue,GateRef obj)92 GateRef CircuitBuilder::TaggedObjectIsShared(GateRef glue, GateRef obj)
93 {
94     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), LoadHClass(glue, obj),
95         IntPtr(JSHClass::BIT_FIELD_OFFSET));
96     return Int32NotEqual(
97         Int32And(Int32LSR(bitfield, Int32(JSHClass::IsJSSharedBit::START_BIT)),
98                  Int32((1LU << JSHClass::IsJSSharedBit::SIZE) - 1)),
99         Int32(0));
100 }
101 
TaggedObjectIsEcmaObject(GateRef glue,GateRef obj)102 GateRef CircuitBuilder::TaggedObjectIsEcmaObject(GateRef glue, GateRef obj)
103 {
104     GateRef objectType = GetObjectType(LoadHClass(glue, obj));
105     return BitAnd(
106         Int32LessThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::ECMA_OBJECT_LAST))),
107         Int32GreaterThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::ECMA_OBJECT_FIRST))));
108 }
109 
TaggedObjectIsByteArray(GateRef glue,GateRef obj)110 GateRef CircuitBuilder::TaggedObjectIsByteArray(GateRef glue, GateRef obj)
111 {
112     GateRef objectType = GetObjectType(LoadHClass(glue, obj));
113     return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::BYTE_ARRAY)));
114 }
115 
TaggedObjectIsMap(GateRef glue,GateRef obj)116 GateRef CircuitBuilder::TaggedObjectIsMap(GateRef glue, GateRef obj)
117 {
118     GateRef objectType = GetObjectType(LoadHClass(glue, obj));
119     return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_MAP)));
120 }
121 
TaggedObjectIsDataView(GateRef glue,GateRef obj)122 GateRef CircuitBuilder::TaggedObjectIsDataView(GateRef glue, GateRef obj)
123 {
124     GateRef objectType = GetObjectType(LoadHClass(glue, obj));
125     return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_DATA_VIEW)));
126 }
127 
IsSpecialSlicedString(GateRef glue,GateRef obj)128 GateRef CircuitBuilder::IsSpecialSlicedString(GateRef glue, GateRef obj)
129 {
130     GateRef objectType = GetObjectType(LoadHClass(glue, obj));
131     GateRef isSlicedString = Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::SLICED_STRING)));
132     Label entry(env_);
133     SubCfgEntry(&entry);
134     Label exit(env_);
135     DEFVALUE(result, env_, VariableType::BOOL(), False());
136     Label isSlicedStr(env_);
137     BRANCH(isSlicedString, &isSlicedStr, &exit);
138     Bind(&isSlicedStr);
139     {
140         GateRef mixStartIndex = LoadConstOffset(VariableType::INT32(), obj, SlicedString::STARTINDEX_AND_FLAGS_OFFSET);
141         result = TruncInt32ToInt1(Int32And(mixStartIndex, Int32((1 << SlicedString::HasBackingStoreBit::SIZE) - 1)));
142         Jump(&exit);
143     }
144     Bind(&exit);
145     auto ret = *result;
146     SubCfgExit();
147     return ret;
148 }
149 
TaggedIsArrayIterator(GateRef glue,GateRef obj)150 GateRef CircuitBuilder::TaggedIsArrayIterator(GateRef glue, GateRef obj)
151 {
152     Label entry(env_);
153     SubCfgEntry(&entry);
154     Label exit(env_);
155     DEFVALUE(result, env_, VariableType::BOOL(), False());
156     Label isHeapObject(env_);
157     Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
158     Bind(&isHeapObject);
159     {
160         result = Int32Equal(GetObjectType(LoadHClass(glue, obj)),
161                             Int32(static_cast<int32_t>(JSType::JS_ARRAY_ITERATOR)));
162         Jump(&exit);
163     }
164     Bind(&exit);
165     auto ret = *result;
166     SubCfgExit();
167     return ret;
168 }
169 
TaggedIsBigInt(GateRef glue,GateRef obj)170 GateRef CircuitBuilder::TaggedIsBigInt(GateRef glue, GateRef obj)
171 {
172     Label entry(env_);
173     SubCfgEntry(&entry);
174     Label exit(env_);
175     DEFVALUE(result, env_, VariableType::BOOL(), False());
176     Label isHeapObject(env_);
177     BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
178     Bind(&isHeapObject);
179     {
180         result = Int32Equal(GetObjectType(LoadHClass(glue, obj)),
181                             Int32(static_cast<int32_t>(JSType::BIGINT)));
182         Jump(&exit);
183     }
184     Bind(&exit);
185     auto ret = *result;
186     SubCfgExit();
187     return ret;
188 }
189 
TaggedIsString(GateRef glue,GateRef obj)190 GateRef CircuitBuilder::TaggedIsString(GateRef glue, GateRef obj)
191 {
192     Label entry(env_);
193     SubCfgEntry(&entry);
194     Label exit(env_);
195     DEFVALUE(result, env_, VariableType::BOOL(), False());
196     Label isHeapObject(env_);
197     BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
198     Bind(&isHeapObject);
199     {
200         result = TaggedObjectIsString(glue, obj);
201         Jump(&exit);
202     }
203     Bind(&exit);
204     auto ret = *result;
205     SubCfgExit();
206     return ret;
207 }
208 
TaggedIsLineUtf8String(GateRef glue,GateRef obj)209 GateRef CircuitBuilder::TaggedIsLineUtf8String(GateRef glue, GateRef obj)
210 {
211     return LogicAndBuilder(env_).And(TaggedIsString(glue, obj))
212                                 .And(IsLineString(glue, obj))
213                                 .And(IsUtf8String(obj))
214                                 .Done();
215 }
216 
TaggedIsStringIterator(GateRef glue,GateRef obj)217 GateRef CircuitBuilder::TaggedIsStringIterator(GateRef glue, GateRef obj)
218 {
219     Label entry(env_);
220     SubCfgEntry(&entry);
221     Label exit(env_);
222     DEFVALUE(result, env_, VariableType::BOOL(), False());
223     Label isHeapObject(env_);
224     Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
225     Bind(&isHeapObject);
226     {
227         result = Int32Equal(GetObjectType(LoadHClass(glue, obj)),
228                             Int32(static_cast<int32_t>(JSType::JS_STRING_ITERATOR)));
229         Jump(&exit);
230     }
231     Bind(&exit);
232     auto ret = *result;
233     SubCfgExit();
234     return ret;
235 }
236 
TaggedIsSharedObj(GateRef glue,GateRef obj)237 GateRef CircuitBuilder::TaggedIsSharedObj(GateRef glue, GateRef obj)
238 {
239     Label entry(env_);
240     SubCfgEntry(&entry);
241     Label exit(env_);
242     DEFVALUE(result, env_, VariableType::BOOL(), False());
243     Label isHeapObject(env_);
244     BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
245     Bind(&isHeapObject);
246     {
247         result = TaggedObjectIsShared(glue, obj);
248         Jump(&exit);
249     }
250     Bind(&exit);
251     auto ret = *result;
252     SubCfgExit();
253     return ret;
254 }
255 
TaggedIsStableArray(GateRef glue,GateRef obj)256 GateRef CircuitBuilder::TaggedIsStableArray(GateRef glue, GateRef obj)
257 {
258     Label subentry(env_);
259     env_->SubCfgEntry(&subentry);
260     DEFVALUE(result, env_, VariableType::BOOL(), False());
261     Label exit(env_);
262     Label targetIsHeapObject(env_);
263     Label targetIsStableArray(env_);
264 
265     BRANCH(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit);
266     Bind(&targetIsHeapObject);
267     {
268         GateRef jsHclass = LoadHClass(glue, obj);
269         BRANCH(IsStableArray(jsHclass), &targetIsStableArray, &exit);
270         Bind(&targetIsStableArray);
271         {
272             GateRef globalEnv = circuit_->GetGlobalEnvCache();
273             result = GetArrayElementsGuardians(globalEnv);
274             Jump(&exit);
275         }
276     }
277     Bind(&exit);
278     auto res = *result;
279     env_->SubCfgExit();
280     return res;
281 }
282 
TaggedIsSymbol(GateRef glue,GateRef obj)283 GateRef CircuitBuilder::TaggedIsSymbol(GateRef glue, GateRef obj)
284 {
285     Label entry(env_);
286     SubCfgEntry(&entry);
287     Label exit(env_);
288     DEFVALUE(result, env_, VariableType::BOOL(), False());
289     Label isHeapObject(env_);
290     BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
291     Bind(&isHeapObject);
292     {
293         GateRef objType = GetObjectType(LoadHClass(glue, obj));
294         result = Equal(objType, Int32(static_cast<int32_t>(JSType::SYMBOL)));
295         Jump(&exit);
296     }
297     Bind(&exit);
298     auto ret = *result;
299     SubCfgExit();
300     return ret;
301 }
302 
TaggedIsStringOrSymbol(GateRef glue,GateRef obj)303 GateRef CircuitBuilder::TaggedIsStringOrSymbol(GateRef glue, GateRef obj)
304 {
305     Label entry(env_);
306     SubCfgEntry(&entry);
307     Label exit(env_);
308     DEFVALUE(result, env_, VariableType::BOOL(), False());
309     Label isHeapObject(env_);
310     BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
311     Bind(&isHeapObject);
312     {
313         result = TaggedObjectIsString(glue, obj);
314         Label isString(env_);
315         Label notString(env_);
316         BRANCH(*result, &exit, &notString);
317         Bind(&notString);
318         {
319             GateRef objType = GetObjectType(LoadHClass(glue, obj));
320             result = Equal(objType, Int32(static_cast<int32_t>(JSType::SYMBOL)));
321             Jump(&exit);
322         }
323     }
324     Bind(&exit);
325     auto ret = *result;
326     SubCfgExit();
327     return ret;
328 }
329 
TaggedIsEnumCache(GateRef glue,GateRef obj)330 GateRef CircuitBuilder::TaggedIsEnumCache(GateRef glue, GateRef obj)
331 {
332     Label entry(env_);
333     SubCfgEntry(&entry);
334     Label exit(env_);
335     DEFVALUE(result, env_, VariableType::BOOL(), False());
336     Label isHeapObject(env_);
337     BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
338     Bind(&isHeapObject);
339     {
340         GateRef objType = GetObjectType(LoadHClass(glue, obj));
341         result = Equal(objType, Int32(static_cast<int32_t>(JSType::ENUM_CACHE)));
342         Jump(&exit);
343     }
344     Bind(&exit);
345     auto ret = *result;
346     SubCfgExit();
347     return ret;
348 }
349 
TaggedIsProtoChangeMarker(GateRef glue,GateRef obj)350 GateRef CircuitBuilder::TaggedIsProtoChangeMarker(GateRef glue, GateRef obj)
351 {
352     Label entry(env_);
353     SubCfgEntry(&entry);
354     Label exit(env_);
355     DEFVALUE(result, env_, VariableType::BOOL(), False());
356     Label isHeapObject(env_);
357     BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
358     Bind(&isHeapObject);
359     {
360         GateRef objType = GetObjectType(LoadHClass(glue, obj));
361         result = Equal(objType, Int32(static_cast<int32_t>(JSType::PROTO_CHANGE_MARKER)));
362         Jump(&exit);
363     }
364     Bind(&exit);
365     auto ret = *result;
366     SubCfgExit();
367     return ret;
368 }
369 
TaggedObjectIsJSMap(GateRef glue,GateRef obj)370 GateRef CircuitBuilder::TaggedObjectIsJSMap(GateRef glue, GateRef obj)
371 {
372     GateRef objType = GetObjectType(LoadHClass(glue, obj));
373     return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_MAP)));
374 }
375 
TaggedObjectIsJSSet(GateRef glue,GateRef obj)376 GateRef CircuitBuilder::TaggedObjectIsJSSet(GateRef glue, GateRef obj)
377 {
378     GateRef objType = GetObjectType(LoadHClass(glue, obj));
379     return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_SET)));
380 }
381 
TaggedObjectIsJSDate(GateRef glue,GateRef obj)382 GateRef CircuitBuilder::TaggedObjectIsJSDate(GateRef glue, GateRef obj)
383 {
384     GateRef objType = GetObjectType(LoadHClass(glue, obj));
385     return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_DATE)));
386 }
387 
TaggedObjectIsTypedArray(GateRef glue,GateRef obj)388 GateRef CircuitBuilder::TaggedObjectIsTypedArray(GateRef glue, GateRef obj)
389 {
390     GateRef jsType = GetObjectType(LoadHClass(glue, obj));
391     return BitAnd(Int32GreaterThan(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY_FIRST))),
392                   Int32GreaterThanOrEqual(Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY_LAST)), jsType));
393 }
394 
TaggedObjectIsJSArray(GateRef glue,GateRef obj)395 GateRef CircuitBuilder::TaggedObjectIsJSArray(GateRef glue, GateRef obj)
396 {
397     GateRef objType = GetObjectType(LoadHClass(glue, obj));
398     return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_ARRAY)));
399 }
400 
TaggedIsBoundFunction(GateRef glue,GateRef obj)401 GateRef CircuitBuilder::TaggedIsBoundFunction(GateRef glue, GateRef obj)
402 {
403     GateRef objType = GetObjectType(LoadHClass(glue, obj));
404     return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_BOUND_FUNCTION)));
405 }
406 
JudgeAotAndFastCall(GateRef jsFunc,JudgeMethodType type)407 inline GateRef CircuitBuilder::JudgeAotAndFastCall(GateRef jsFunc, JudgeMethodType type)
408 {
409     GateRef bitFieldOffset = IntPtr(JSFunctionBase::BIT_FIELD_OFFSET);
410     GateRef bitField = LoadWithoutBarrier(VariableType::INT32(), jsFunc, bitFieldOffset);
411     switch (type) {
412         case JudgeMethodType::HAS_AOT: {
413             return Int32NotEqual(
414                 Int32And(
415                     Int32LSR(bitField, Int32(JSFunctionBase::IsCompiledCodeBit::START_BIT)),
416                     Int32((1U << JSFunctionBase::IsCompiledCodeBit::SIZE) - 1)),
417                 Int32(0));
418         }
419         case JudgeMethodType::HAS_AOT_FASTCALL: {
420             return Int32Equal(
421                 Int32And(
422                     bitField,
423                     Int32(JSFunctionBase::COMPILED_CODE_FASTCALL_BITS << JSFunctionBase::IsCompiledCodeBit::START_BIT)),
424                 Int32(JSFunctionBase::COMPILED_CODE_FASTCALL_BITS << JSFunctionBase::IsCompiledCodeBit::START_BIT));
425         }
426         case JudgeMethodType::HAS_AOT_NOTFASTCALL: {
427             GateRef fastCallField =
428                 Int32And(bitField,
429                     Int32(JSFunctionBase::COMPILED_CODE_FASTCALL_BITS << JSFunctionBase::IsCompiledCodeBit::START_BIT));
430             GateRef hasAot = Int32(1U << JSFunctionBase::IsCompiledCodeBit::START_BIT);
431             return Int32Equal(fastCallField, hasAot);
432         }
433         default:
434             UNREACHABLE();
435     }
436 }
437 
BothAreString(GateRef glue,GateRef x,GateRef y)438 GateRef CircuitBuilder::BothAreString(GateRef glue, GateRef x, GateRef y)
439 {
440     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(TaggedIsHeapObject(y))
441         .And(TaggedObjectIsString(glue, x)).And(TaggedObjectIsString(glue, y)).Done();
442 }
443 
TaggedIsHole(GateRef x)444 GateRef CircuitBuilder::TaggedIsHole(GateRef x)
445 {
446     return Equal(x, HoleConstant());
447 }
448 
TaggedIsNullPtr(GateRef x)449 GateRef CircuitBuilder::TaggedIsNullPtr(GateRef x)
450 {
451     return Equal(x, NullPtrConstant());
452 }
453 
IsSpecialHole(GateRef x)454 GateRef CircuitBuilder::IsSpecialHole(GateRef x)
455 {
456     return Equal(x, SpecialHoleConstant());
457 }
458 
IsNotSpecialHole(GateRef x)459 GateRef CircuitBuilder::IsNotSpecialHole(GateRef x)
460 {
461     return NotEqual(x, SpecialHoleConstant());
462 }
463 
TaggedIsNotHole(GateRef x)464 GateRef CircuitBuilder::TaggedIsNotHole(GateRef x)
465 {
466     return NotEqual(x, HoleConstant());
467 }
468 
TaggedIsUndefined(GateRef x)469 GateRef CircuitBuilder::TaggedIsUndefined(GateRef x)
470 {
471     return Equal(x, UndefineConstant());
472 }
473 
TaggedIsException(GateRef x)474 GateRef CircuitBuilder::TaggedIsException(GateRef x)
475 {
476     return Equal(x, ExceptionConstant());
477 }
478 
TaggedIsSpecial(GateRef x)479 GateRef CircuitBuilder::TaggedIsSpecial(GateRef x)
480 {
481     return LogicOrBuilder(env_)
482         .Or(TaggedIsHole(x))
483         .Or(Equal(Int64And(ChangeTaggedPointerToInt64(x), Int64(JSTaggedValue::TAG_SPECIAL_MASK)),
484                   Int64(JSTaggedValue::TAG_SPECIAL)))
485         .Done();
486 }
487 
TaggedIsHeapObject(GateRef x)488 GateRef CircuitBuilder::TaggedIsHeapObject(GateRef x)
489 {
490     x = ChangeTaggedPointerToInt64(x);
491     auto t = Int64And(x, Int64(JSTaggedValue::TAG_HEAPOBJECT_MASK), GateType::Empty(), "checkHeapObject");
492     return Equal(t, Int64(0), "checkHeapObject");
493 }
494 
TaggedIsHeapObject(GateRef x,const CompilationEnv * compilationEnv)495 GateRef CircuitBuilder::TaggedIsHeapObject(GateRef x, const CompilationEnv *compilationEnv)
496 {
497     if (compilationEnv != nullptr && compilationEnv->SupportIntrinsic() && !acc_.IsConstant(x)) {
498         return GetCircuit()->NewGate(circuit_->TaggedIsHeapObjectIntrinsic(),
499             MachineType::I1, { x, Int64(JSTaggedValue::TAG_HEAPOBJECT_MASK) },
500             GateType::NJSValue(), "checkHeapObjectIntrinsic");
501     }
502     return TaggedIsHeapObject(x);
503 }
504 
TaggedIsJSFunction(GateRef glue,GateRef x)505 GateRef CircuitBuilder::TaggedIsJSFunction(GateRef glue, GateRef x)
506 {
507     GateRef objectType = GetObjectType(LoadHClass(glue, x));
508     GateRef greater = Int32GreaterThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::JS_FUNCTION_FIRST)));
509     GateRef less = Int32LessThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::JS_FUNCTION_LAST)));
510     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(BitAnd(greater, less)).Done();
511 }
512 
TaggedIsAsyncGeneratorObject(GateRef glue,GateRef x)513 GateRef CircuitBuilder::TaggedIsAsyncGeneratorObject(GateRef glue, GateRef x)
514 {
515     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x))
516                                 .And(IsJsType(glue, x, JSType::JS_ASYNC_GENERATOR_OBJECT)).Done();
517 }
518 
TaggedIsJSGlobalObject(GateRef glue,GateRef x)519 GateRef CircuitBuilder::TaggedIsJSGlobalObject(GateRef glue, GateRef x)
520 {
521     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(glue, x, JSType::JS_GLOBAL_OBJECT)).Done();
522 }
523 
TaggedIsGeneratorObject(GateRef glue,GateRef x)524 GateRef CircuitBuilder::TaggedIsGeneratorObject(GateRef glue, GateRef x)
525 {
526     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(glue, x, JSType::JS_GENERATOR_OBJECT)).Done();
527 }
528 
TaggedIsJSArray(GateRef glue,GateRef x)529 GateRef CircuitBuilder::TaggedIsJSArray(GateRef glue, GateRef x)
530 {
531     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(glue, x, JSType::JS_ARRAY)).Done();
532 }
533 
TaggedIsJSProxy(GateRef glue,GateRef x)534 GateRef CircuitBuilder::TaggedIsJSProxy(GateRef glue, GateRef x)
535 {
536     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(glue, x, JSType::JS_PROXY)).Done();
537 }
538 
TaggedIsPropertyBox(GateRef glue,GateRef x)539 GateRef CircuitBuilder::TaggedIsPropertyBox(GateRef glue, GateRef x)
540 {
541     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(glue, x, JSType::PROPERTY_BOX)).Done();
542 }
543 
TaggedIsWeak(GateRef x)544 GateRef CircuitBuilder::TaggedIsWeak(GateRef x)
545 {
546     return LogicAndBuilder(env_)
547         .And(TaggedIsHeapObject(x))
548         .And(Equal(Int64And(ChangeTaggedPointerToInt64(x), Int64(JSTaggedValue::TAG_WEAK)), Int64(1)))
549         .Done();
550 }
551 
TaggedIsPrototypeHandler(GateRef glue,GateRef x)552 GateRef CircuitBuilder::TaggedIsPrototypeHandler(GateRef glue, GateRef x)
553 {
554     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(glue, x, JSType::PROTOTYPE_HANDLER)).Done();
555 }
556 
TaggedIsTransitionHandler(GateRef glue,GateRef x)557 GateRef CircuitBuilder::TaggedIsTransitionHandler(GateRef glue, GateRef x)
558 {
559     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(glue, x, JSType::TRANSITION_HANDLER)).Done();
560 }
561 
TaggedIsStoreAOTHandler(GateRef glue,GateRef x)562 GateRef CircuitBuilder::TaggedIsStoreAOTHandler(GateRef glue, GateRef x)
563 {
564     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(glue, x, JSType::STORE_TS_HANDLER)).Done();
565 }
566 
TaggedIsTransWithProtoHandler(GateRef glue,GateRef x)567 GateRef CircuitBuilder::TaggedIsTransWithProtoHandler(GateRef glue, GateRef x)
568 {
569     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x))
570         .And(IsJsType(glue, x, JSType::TRANS_WITH_PROTO_HANDLER)).Done();
571 }
572 
TaggedIsUndefinedOrNull(GateRef x)573 GateRef CircuitBuilder::TaggedIsUndefinedOrNull(GateRef x)
574 {
575     x = ChangeTaggedPointerToInt64(x);
576     GateRef heapObjMask = Int64(JSTaggedValue::TAG_HEAPOBJECT_MASK);
577     GateRef tagSpecial = Int64(JSTaggedValue::TAG_SPECIAL);
578     GateRef andGate = Int64And(x, heapObjMask);
579     GateRef result = Equal(andGate, tagSpecial);
580     return result;
581 }
582 
TaggedIsUndefinedOrNullOrHole(GateRef x)583 GateRef CircuitBuilder::TaggedIsUndefinedOrNullOrHole(GateRef x)
584 {
585     return BitOr(TaggedIsHole(x), TaggedIsUndefinedOrNull(x));
586 }
587 
TaggedIsNotUndefinedAndNull(GateRef x)588 GateRef CircuitBuilder::TaggedIsNotUndefinedAndNull(GateRef x)
589 {
590     x = ChangeTaggedPointerToInt64(x);
591     GateRef heapObjMask = Int64(JSTaggedValue::TAG_HEAPOBJECT_MASK);
592     GateRef tagSpecial = Int64(JSTaggedValue::TAG_SPECIAL);
593     GateRef andGate = Int64And(x, heapObjMask);
594     GateRef result = NotEqual(andGate, tagSpecial);
595     return result;
596 }
597 
TaggedIsNotUndefinedAndNullAndHole(GateRef x)598 GateRef CircuitBuilder::TaggedIsNotUndefinedAndNullAndHole(GateRef x)
599 {
600     return BitAnd(TaggedIsNotHole(x), TaggedIsNotUndefinedAndNull(x));
601 }
602 
TaggedIsUndefinedOrHole(GateRef x)603 GateRef CircuitBuilder::TaggedIsUndefinedOrHole(GateRef x)
604 {
605     GateRef isUndefined = TaggedIsUndefined(x);
606     GateRef isHole = TaggedIsHole(x);
607     GateRef result = BitOr(isHole, isUndefined);
608     return result;
609 }
610 
TaggedTrue()611 GateRef CircuitBuilder::TaggedTrue()
612 {
613     return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_TRUE, GateType::TaggedValue());
614 }
615 
TaggedFalse()616 GateRef CircuitBuilder::TaggedFalse()
617 {
618     return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_FALSE, GateType::TaggedValue());
619 }
620 
TaggedIsTrue(GateRef x)621 GateRef CircuitBuilder::TaggedIsTrue(GateRef x)
622 {
623     return Equal(x, TaggedTrue());
624 }
625 
TaggedIsFalse(GateRef x)626 GateRef CircuitBuilder::TaggedIsFalse(GateRef x)
627 {
628     return Equal(x, TaggedFalse());
629 }
630 
TaggedIsNull(GateRef x)631 GateRef CircuitBuilder::TaggedIsNull(GateRef x)
632 {
633     return Equal(x, NullConstant());
634 }
635 
TaggedIsNotNull(GateRef x)636 GateRef CircuitBuilder::TaggedIsNotNull(GateRef x)
637 {
638     return NotEqual(x, NullConstant());
639 }
640 
TaggedIsBoolean(GateRef x)641 GateRef CircuitBuilder::TaggedIsBoolean(GateRef x)
642 {
643     return BitOr(TaggedIsFalse(x), TaggedIsTrue(x));
644 }
645 
TaggedIsNativePointer(GateRef glue,GateRef x)646 GateRef CircuitBuilder::TaggedIsNativePointer(GateRef glue, GateRef x)
647 {
648     return LogicAndBuilder(env_)
649         .And(TaggedIsHeapObject(x))
650         .And(IsJsType(glue, x, JSType::JS_NATIVE_POINTER)).Done();
651 }
652 
TaggedGetInt(GateRef x)653 GateRef CircuitBuilder::TaggedGetInt(GateRef x)
654 {
655     x = ChangeTaggedPointerToInt64(x);
656     return TruncInt64ToInt32(Int64And(x, Int64(~JSTaggedValue::TAG_MARK)));
657 }
658 
TypedCallBuiltin(GateRef hirGate,const std::vector<GateRef> & args,BuiltinsStubCSigns::ID id,bool isSideEffect)659 inline GateRef CircuitBuilder::TypedCallBuiltin(GateRef hirGate, const std::vector<GateRef> &args,
660                                                 BuiltinsStubCSigns::ID id, bool isSideEffect)
661 {
662     auto currentLabel = env_->GetCurrentLabel();
663     auto currentControl = currentLabel->GetControl();
664     auto currentDepend = currentLabel->GetDepend();
665 
666     std::vector<GateRef> inList { currentControl, currentDepend };
667     inList.insert(inList.end(), args.begin(), args.end());
668     inList.push_back(Int16(static_cast<int16_t>(id)));
669     AppendFrameState(inList, hirGate);
670 
671     auto builtinOp = TypedCallOperator(hirGate, MachineType::I64, inList, isSideEffect);
672     currentLabel->SetControl(builtinOp);
673     currentLabel->SetDepend(builtinOp);
674     return builtinOp;
675 }
676 
CallNewBuiltin(GateRef hirGate,std::vector<GateRef> & args)677 inline GateRef CircuitBuilder::CallNewBuiltin(GateRef hirGate, std::vector<GateRef> &args)
678 {
679     auto curLable = env_->GetCurrentLabel();
680     std::vector<GateRef> inList {curLable->GetControl(), curLable->GetDepend()};
681     inList.insert(inList.end(), args.begin(), args.end());
682     AppendFrameState(inList, hirGate);
683     auto callGate = GetCircuit()->NewGate(circuit_->CallNewBuiltin(args.size(), acc_.TryGetPcOffset(hirGate)),
684                                           MachineType::I64, inList.size(), inList.data(), GateType::AnyType());
685     curLable->SetControl(callGate);
686     curLable->SetDepend(callGate);
687     return callGate;
688 }
689 
690 template<TypedBinOp Op>
TypedBinaryOp(GateRef x,GateRef y,ParamType paramType)691 GateRef CircuitBuilder::TypedBinaryOp(GateRef x, GateRef y, ParamType paramType)
692 {
693     auto currentLabel = env_->GetCurrentLabel();
694     auto currentControl = currentLabel->GetControl();
695     auto currentDepend = currentLabel->GetDepend();
696     uint64_t value = TypedBinaryAccessor::ToValue(paramType, Op);
697     auto numberBinaryOp = GetCircuit()->NewGate(circuit_->TypedBinaryOp(value),
698         MachineType::I64, {currentControl, currentDepend, x, y}, GateType::AnyType());
699     currentLabel->SetControl(numberBinaryOp);
700     currentLabel->SetDepend(numberBinaryOp);
701     return numberBinaryOp;
702 }
703 
704 template<TypedCallTargetCheckOp Op>
JSNoGCCallThisTargetTypeCheck(GateRef func,GateRef methodId,GateRef gate)705 GateRef CircuitBuilder::JSNoGCCallThisTargetTypeCheck(GateRef func, GateRef methodId, GateRef gate)
706 {
707     auto currentLabel = env_->GetCurrentLabel();
708     auto currentControl = currentLabel->GetControl();
709     auto currentDepend = currentLabel->GetDepend();
710     auto frameState = acc_.GetFrameState(gate);
711     uint64_t value = TypedCallTargetCheckAccessor::ToValue(Op);
712     GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(value), MachineType::I1,
713         {currentControl, currentDepend, func, methodId, frameState}, GateType::NJSValue());
714     currentLabel->SetControl(ret);
715     currentLabel->SetDepend(ret);
716     return ret;
717 }
718 
719 template<TypedCallTargetCheckOp Op>
JSCallTargetTypeCheck(GateRef func,GateRef methodIndex,GateRef gate)720 GateRef CircuitBuilder::JSCallTargetTypeCheck(GateRef func, GateRef methodIndex, GateRef gate)
721 {
722     auto currentLabel = env_->GetCurrentLabel();
723     auto currentControl = currentLabel->GetControl();
724     auto currentDepend = currentLabel->GetDepend();
725     auto frameState = acc_.GetFrameState(gate);
726     uint64_t value = TypedCallTargetCheckAccessor::ToValue(Op);
727     GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(value), MachineType::I1,
728         {currentControl, currentDepend, func, methodIndex, frameState}, GateType::NJSValue());
729     currentLabel->SetControl(ret);
730     currentLabel->SetDepend(ret);
731     return ret;
732 }
733 
734 template<TypedUnOp Op>
TypedUnaryOp(GateRef x,ParamType paramType)735 GateRef CircuitBuilder::TypedUnaryOp(GateRef x, ParamType paramType)
736 {
737     auto currentLabel = env_->GetCurrentLabel();
738     auto currentControl = currentLabel->GetControl();
739     auto currentDepend = currentLabel->GetDepend();
740     uint64_t value = TypedUnaryAccessor::ToValue(paramType, Op);
741     auto numberUnaryOp = GetCircuit()->NewGate(circuit_->TypedUnaryOp(value),
742         MachineType::I64, {currentControl, currentDepend, x}, GateType::AnyType());
743     currentLabel->SetControl(numberUnaryOp);
744     currentLabel->SetDepend(numberUnaryOp);
745     return numberUnaryOp;
746 }
747 
748 template<TypedJumpOp Op>
TypedConditionJump(GateRef x,ParamType paramType,uint32_t weight)749 GateRef CircuitBuilder::TypedConditionJump(GateRef x, ParamType paramType, uint32_t weight)
750 {
751     auto currentLabel = env_->GetCurrentLabel();
752     auto currentControl = currentLabel->GetControl();
753     auto currentDepend = currentLabel->GetDepend();
754     auto machineType = MachineType::NOVALUE;
755     auto jumpOp = TypedConditionJump(machineType, Op, weight, paramType, {currentControl, currentDepend, x});
756     currentLabel->SetControl(jumpOp);
757     currentLabel->SetDepend(jumpOp);
758     return jumpOp;
759 }
760 
761 template <TypedLoadOp Op>
LoadElement(GateRef receiver,GateRef index,OnHeapMode onHeap)762 GateRef CircuitBuilder::LoadElement(GateRef receiver, GateRef index, OnHeapMode onHeap)
763 {
764     auto currentLabel = env_->GetCurrentLabel();
765     auto currentControl = currentLabel->GetControl();
766     auto currentDepend = currentLabel->GetDepend();
767     LoadElementAccessor accessor(Op, onHeap);
768     auto ret = GetCircuit()->NewGate(GetCircuit()->LoadElement(accessor.ToValue()), MachineType::I64,
769                                      {currentControl, currentDepend, receiver, index}, GateType::AnyType());
770     currentLabel->SetControl(ret);
771     currentLabel->SetDepend(ret);
772     return ret;
773 }
774 
775 template <TypedStoreOp Op>
StoreElement(GateRef receiver,GateRef index,GateRef value,OnHeapMode onHeap)776 GateRef CircuitBuilder::StoreElement(GateRef receiver, GateRef index, GateRef value, OnHeapMode onHeap)
777 {
778     auto currentLabel = env_->GetCurrentLabel();
779     auto currentControl = currentLabel->GetControl();
780     auto currentDepend = currentLabel->GetDepend();
781     StoreElementAccessor accessor(Op, onHeap);
782     auto ret = GetCircuit()->NewGate(GetCircuit()->StoreElement(accessor.ToValue()), MachineType::NOVALUE,
783                                      {currentControl, currentDepend, receiver, index, value}, GateType::AnyType());
784     currentLabel->SetControl(ret);
785     currentLabel->SetDepend(ret);
786     return ret;
787 }
788 
PrimitiveToNumber(GateRef x,ParamType paramType)789 GateRef CircuitBuilder::PrimitiveToNumber(GateRef x, ParamType paramType)
790 {
791     auto currentLabel = env_->GetCurrentLabel();
792     auto currentControl = currentLabel->GetControl();
793     auto currentDepend = currentLabel->GetDepend();
794 
795     auto numberconvert = TypeConvert(MachineType::I64, paramType, GateType::NumberType(),
796                                      {currentControl, currentDepend, x});
797     currentLabel->SetControl(numberconvert);
798     currentLabel->SetDepend(numberconvert);
799     return numberconvert;
800 }
801 
LoadFromTaggedArray(GateRef array,size_t index)802 GateRef CircuitBuilder::LoadFromTaggedArray(GateRef array, size_t index)
803 {
804     auto dataOffset = TaggedArray::DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize();
805     return LoadConstOffset(VariableType::JS_ANY(), array, dataOffset);
806 }
807 
StoreToTaggedArray(GateRef array,size_t index,GateRef value)808 GateRef CircuitBuilder::StoreToTaggedArray(GateRef array, size_t index, GateRef value)
809 {
810     auto dataOffset = TaggedArray::DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize();
811     return StoreConstOffset(VariableType::JS_ANY(), array, dataOffset, value);
812 }
813 
TreeStringIsFlat(GateRef glue,GateRef string)814 GateRef CircuitBuilder::TreeStringIsFlat(GateRef glue, GateRef string)
815 {
816     GateRef second = GetSecondFromTreeString(glue, string);
817     GateRef len = GetLengthFromString(second);
818     return Int32Equal(len, Int32(0));
819 }
820 
GetFirstFromTreeString(GateRef glue,GateRef string)821 GateRef CircuitBuilder::GetFirstFromTreeString(GateRef glue, GateRef string)
822 {
823     GateRef offset = IntPtr(TreeString::FIRST_OFFSET);
824     return Load(VariableType::JS_POINTER(), glue, string, offset);
825 }
826 
GetSecondFromTreeString(GateRef glue,GateRef string)827 GateRef CircuitBuilder::GetSecondFromTreeString(GateRef glue, GateRef string)
828 {
829     GateRef offset = IntPtr(TreeString::SECOND_OFFSET);
830     return Load(VariableType::JS_POINTER(), glue, string, offset);
831 }
832 
GetValueFromTaggedArray(GateRef glue,GateRef array,GateRef index)833 GateRef CircuitBuilder::GetValueFromTaggedArray(GateRef glue, GateRef array, GateRef index)
834 {
835     GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
836     GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
837     return Load(VariableType::JS_ANY(), glue, array, dataOffset);
838 }
839 
GetValueFromTaggedArray(GateRef glue,GateRef array,GateRef index,GateRef depend)840 GateRef CircuitBuilder::GetValueFromTaggedArray(GateRef glue, GateRef array, GateRef index, GateRef depend)
841 {
842     GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
843     GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
844     return Load(VariableType::JS_ANY(), glue, array, dataOffset, depend);
845 }
846 
GetValueFromTaggedArray(VariableType valType,GateRef array,GateRef index)847 GateRef CircuitBuilder::GetValueFromTaggedArray(VariableType valType, GateRef array, GateRef index)
848 {
849     GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
850     GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
851     // valType is all PrimitiveType, barrier is not needed
852     return LoadWithoutBarrier(valType, array, dataOffset);
853 }
854 
GetValueFromJSArrayWithElementsKind(VariableType type,GateRef array,GateRef index)855 GateRef CircuitBuilder::GetValueFromJSArrayWithElementsKind(VariableType type, GateRef array, GateRef index)
856 {
857     GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
858     GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
859     // valType is all PrimitiveType, barrier is not needed
860     return LoadWithoutBarrier(type, array, dataOffset);
861 }
862 
SetValueToTaggedArray(VariableType valType,GateRef glue,GateRef array,GateRef index,GateRef val)863 void CircuitBuilder::SetValueToTaggedArray(VariableType valType, GateRef glue,
864                                            GateRef array, GateRef index, GateRef val)
865 {
866     GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
867     GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
868     Store(valType, glue, array, dataOffset, val);
869 }
870 
GetArrayElementsGuardians(GateRef env)871 GateRef CircuitBuilder::GetArrayElementsGuardians(GateRef env)
872 {
873     GateRef offset = IntPtr(GlobalEnv::BIT_FIELD_OFFSET);
874     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), env, offset);
875     return TruncInt32ToInt1(Int32And(Int32LSR(bitfield,
876         Int32(GlobalEnv::ArrayPrototypeChangedGuardiansBits::START_BIT)),
877         Int32((1LU << GlobalEnv::ArrayPrototypeChangedGuardiansBits::SIZE) - 1)));
878 }
879 
GetMapIteratorDetector(GateRef env)880 GateRef CircuitBuilder::GetMapIteratorDetector(GateRef env)
881 {
882     GateRef offset = IntPtr(GlobalEnv::BIT_FIELD_OFFSET);
883     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), env, offset);
884     return TruncInt32ToInt1(Int32And(Int32LSR(bitfield,
885         Int32(GlobalEnv::MapIteratorDetectorBits::START_BIT)),
886         Int32((1LU << GlobalEnv::MapIteratorDetectorBits::SIZE) - 1)));
887 }
888 
GetSetIteratorDetector(GateRef env)889 GateRef CircuitBuilder::GetSetIteratorDetector(GateRef env)
890 {
891     GateRef offset = IntPtr(GlobalEnv::BIT_FIELD_OFFSET);
892     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), env, offset);
893     return TruncInt32ToInt1(Int32And(Int32LSR(bitfield,
894         Int32(GlobalEnv::SetIteratorDetectorBits::START_BIT)),
895         Int32((1LU << GlobalEnv::SetIteratorDetectorBits::SIZE) - 1)));
896 }
897 
GetStringIteratorDetector(GateRef env)898 GateRef CircuitBuilder::GetStringIteratorDetector(GateRef env)
899 {
900     GateRef offset = IntPtr(GlobalEnv::BIT_FIELD_OFFSET);
901     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), env, offset);
902     return TruncInt32ToInt1(Int32And(Int32LSR(bitfield,
903         Int32(GlobalEnv::StringIteratorDetectorBits::START_BIT)),
904         Int32((1LU << GlobalEnv::StringIteratorDetectorBits::SIZE) - 1)));
905 }
906 
GetArrayIteratorDetector(GateRef env)907 GateRef CircuitBuilder::GetArrayIteratorDetector(GateRef env)
908 {
909     GateRef offset = IntPtr(GlobalEnv::BIT_FIELD_OFFSET);
910     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), env, offset);
911     return TruncInt32ToInt1(Int32And(Int32LSR(bitfield,
912         Int32(GlobalEnv::ArrayIteratorDetectorBits::START_BIT)),
913         Int32((1LU << GlobalEnv::ArrayIteratorDetectorBits::SIZE) - 1)));
914 }
915 
GetTypedArrayIteratorDetector(GateRef env)916 GateRef CircuitBuilder::GetTypedArrayIteratorDetector(GateRef env)
917 {
918     GateRef offset = IntPtr(GlobalEnv::BIT_FIELD_OFFSET);
919     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), env, offset);
920     return TruncInt32ToInt1(Int32And(Int32LSR(bitfield,
921         Int32(GlobalEnv::TypedArrayIteratorDetectorBits::START_BIT)),
922         Int32((1LU << GlobalEnv::TypedArrayIteratorDetectorBits::SIZE) - 1)));
923 }
924 
GetTypedArraySpeciesProtectDetector(GateRef env)925 GateRef CircuitBuilder::GetTypedArraySpeciesProtectDetector(GateRef env)
926 {
927     GateRef offset = IntPtr(GlobalEnv::BIT_FIELD_OFFSET);
928     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), env, offset);
929     return TruncInt32ToInt1(Int32And(Int32LSR(bitfield,
930         Int32(GlobalEnv::TypedArraySpeciesProtectDetectorBits::START_BIT)),
931         Int32((1LU << GlobalEnv::TypedArraySpeciesProtectDetectorBits::SIZE) - 1)));
932 }
933 }
934 #endif  // ECMASCRIPT_COMPILER_MCR_CIRCUIT_BUILDER_H
935