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, ¬String);
317 Bind(¬String);
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