• 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/mem/region.h"
22 #include "ecmascript/method.h"
23 #include "ecmascript/js_function.h"
24 
25 namespace panda::ecmascript::kungfu {
26 
27 // bit operation
28 
TaggedIsInt(GateRef x)29 GateRef CircuitBuilder::TaggedIsInt(GateRef x)
30 {
31     x = ChangeTaggedPointerToInt64(x);
32     return Equal(Int64And(x, Int64(JSTaggedValue::TAG_MARK)),
33                  Int64(JSTaggedValue::TAG_INT));
34 }
35 
TaggedIsDouble(GateRef x)36 GateRef CircuitBuilder::TaggedIsDouble(GateRef x)
37 {
38     x = ChangeTaggedPointerToInt64(x);
39     x = Int64And(x, Int64(JSTaggedValue::TAG_MARK));
40     auto left = NotEqual(x, Int64(JSTaggedValue::TAG_INT));
41     auto right = NotEqual(x, Int64(JSTaggedValue::TAG_OBJECT));
42     return BitAnd(left, right);
43 }
44 
TaggedIsObject(GateRef x)45 GateRef CircuitBuilder::TaggedIsObject(GateRef x)
46 {
47     x = ChangeTaggedPointerToInt64(x);
48     return Equal(Int64And(x, Int64(JSTaggedValue::TAG_MARK)),
49                  Int64(JSTaggedValue::TAG_OBJECT));
50 }
51 
TaggedIsNumber(GateRef x)52 GateRef CircuitBuilder::TaggedIsNumber(GateRef x)
53 {
54     return BoolNot(TaggedIsObject(x));
55 }
56 
TaggedIsNumeric(GateRef x)57 GateRef CircuitBuilder::TaggedIsNumeric(GateRef x)
58 {
59     return LogicOrBuilder(env_).Or(TaggedIsNumber(x)).Or(TaggedIsBigInt(x)).Done();
60 }
61 
TaggedObjectIsString(GateRef obj)62 GateRef CircuitBuilder::TaggedObjectIsString(GateRef obj)
63 {
64     GateRef objectType = GetObjectType(LoadHClass(obj));
65     return BitAnd(
66         Int32LessThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::STRING_LAST))),
67         Int32GreaterThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::STRING_FIRST))));
68 }
69 
TaggedObjectIsShared(GateRef obj)70 GateRef CircuitBuilder::TaggedObjectIsShared(GateRef obj)
71 {
72     GateRef bitfield = Load(VariableType::INT32(), LoadHClass(obj), IntPtr(JSHClass::BIT_FIELD_OFFSET));
73     return Int32NotEqual(
74         Int32And(Int32LSR(bitfield, Int32(JSHClass::IsJSSharedBit::START_BIT)),
75                  Int32((1LU << JSHClass::IsJSSharedBit::SIZE) - 1)),
76         Int32(0));
77 }
78 
TaggedObjectIsEcmaObject(GateRef obj)79 GateRef CircuitBuilder::TaggedObjectIsEcmaObject(GateRef obj)
80 {
81     GateRef objectType = GetObjectType(LoadHClass(obj));
82     return BitAnd(
83         Int32LessThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::ECMA_OBJECT_LAST))),
84         Int32GreaterThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::ECMA_OBJECT_FIRST))));
85 }
86 
TaggedObjectIsByteArray(GateRef obj)87 GateRef CircuitBuilder::TaggedObjectIsByteArray(GateRef obj)
88 {
89     GateRef objectType = GetObjectType(LoadHClass(obj));
90     return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::BYTE_ARRAY)));
91 }
92 
TaggedObjectIsMap(GateRef obj)93 GateRef CircuitBuilder::TaggedObjectIsMap(GateRef obj)
94 {
95     GateRef objectType = GetObjectType(LoadHClass(obj));
96     return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_MAP)));
97 }
98 
TaggedObjectIsDataView(GateRef obj)99 GateRef CircuitBuilder::TaggedObjectIsDataView(GateRef obj)
100 {
101     GateRef objectType = GetObjectType(LoadHClass(obj));
102     return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_DATA_VIEW)));
103 }
104 
IsSpecialSlicedString(GateRef obj)105 GateRef CircuitBuilder::IsSpecialSlicedString(GateRef obj)
106 {
107     GateRef objectType = GetObjectType(LoadHClass(obj));
108     GateRef isSlicedString = Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::SLICED_STRING)));
109     Label entry(env_);
110     SubCfgEntry(&entry);
111     Label exit(env_);
112     DEFVALUE(result, env_, VariableType::BOOL(), False());
113     Label isSlicedStr(env_);
114     BRANCH_CIR2(isSlicedString, &isSlicedStr, &exit);
115     Bind(&isSlicedStr);
116     {
117         GateRef hasBackingStore = LoadConstOffset(VariableType::INT32(), obj, SlicedString::BACKING_STORE_FLAG);
118         result = Int32Equal(hasBackingStore, Int32(EcmaString::HAS_BACKING_STORE));
119         Jump(&exit);
120     }
121     Bind(&exit);
122     auto ret = *result;
123     SubCfgExit();
124     return ret;
125 }
126 
TaggedIsBigInt(GateRef obj)127 GateRef CircuitBuilder::TaggedIsBigInt(GateRef obj)
128 {
129     Label entry(env_);
130     SubCfgEntry(&entry);
131     Label exit(env_);
132     DEFVALUE(result, env_, VariableType::BOOL(), False());
133     Label isHeapObject(env_);
134     BRANCH_CIR2(TaggedIsHeapObject(obj), &isHeapObject, &exit);
135     Bind(&isHeapObject);
136     {
137         result = Int32Equal(GetObjectType(LoadHClass(obj)),
138                             Int32(static_cast<int32_t>(JSType::BIGINT)));
139         Jump(&exit);
140     }
141     Bind(&exit);
142     auto ret = *result;
143     SubCfgExit();
144     return ret;
145 }
146 
TaggedIsString(GateRef obj)147 GateRef CircuitBuilder::TaggedIsString(GateRef obj)
148 {
149     Label entry(env_);
150     SubCfgEntry(&entry);
151     Label exit(env_);
152     DEFVALUE(result, env_, VariableType::BOOL(), False());
153     Label isHeapObject(env_);
154     BRANCH_CIR2(TaggedIsHeapObject(obj), &isHeapObject, &exit);
155     Bind(&isHeapObject);
156     {
157         result = TaggedObjectIsString(obj);
158         Jump(&exit);
159     }
160     Bind(&exit);
161     auto ret = *result;
162     SubCfgExit();
163     return ret;
164 }
165 
TaggedIsStringIterator(GateRef obj)166 GateRef CircuitBuilder::TaggedIsStringIterator(GateRef obj)
167 {
168     Label entry(env_);
169     SubCfgEntry(&entry);
170     Label exit(env_);
171     DEFVALUE(result, env_, VariableType::BOOL(), False());
172     Label isHeapObject(env_);
173     Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
174     Bind(&isHeapObject);
175     {
176         result = Int32Equal(GetObjectType(LoadHClass(obj)),
177                             Int32(static_cast<int32_t>(JSType::JS_STRING_ITERATOR)));
178         Jump(&exit);
179     }
180     Bind(&exit);
181     auto ret = *result;
182     SubCfgExit();
183     return ret;
184 }
185 
TaggedIsSharedObj(GateRef obj)186 GateRef CircuitBuilder::TaggedIsSharedObj(GateRef obj)
187 {
188     Label entry(env_);
189     SubCfgEntry(&entry);
190     Label exit(env_);
191     DEFVALUE(result, env_, VariableType::BOOL(), False());
192     Label isHeapObject(env_);
193     BRANCH_CIR2(TaggedIsHeapObject(obj), &isHeapObject, &exit);
194     Bind(&isHeapObject);
195     {
196         result = TaggedObjectIsShared(obj);
197         Jump(&exit);
198     }
199     Bind(&exit);
200     auto ret = *result;
201     SubCfgExit();
202     return ret;
203 }
204 
TaggedIsSymbol(GateRef obj)205 GateRef CircuitBuilder::TaggedIsSymbol(GateRef obj)
206 {
207     Label entry(env_);
208     SubCfgEntry(&entry);
209     Label exit(env_);
210     DEFVALUE(result, env_, VariableType::BOOL(), False());
211     Label isHeapObject(env_);
212     BRANCH_CIR2(TaggedIsHeapObject(obj), &isHeapObject, &exit);
213     Bind(&isHeapObject);
214     {
215         GateRef objType = GetObjectType(LoadHClass(obj));
216         result = Equal(objType, Int32(static_cast<int32_t>(JSType::SYMBOL)));
217         Jump(&exit);
218     }
219     Bind(&exit);
220     auto ret = *result;
221     SubCfgExit();
222     return ret;
223 }
224 
TaggedIsStringOrSymbol(GateRef obj)225 GateRef CircuitBuilder::TaggedIsStringOrSymbol(GateRef obj)
226 {
227     Label entry(env_);
228     SubCfgEntry(&entry);
229     Label exit(env_);
230     DEFVALUE(result, env_, VariableType::BOOL(), False());
231     Label isHeapObject(env_);
232     BRANCH_CIR2(TaggedIsHeapObject(obj), &isHeapObject, &exit);
233     Bind(&isHeapObject);
234     {
235         result = TaggedObjectIsString(obj);
236         Label isString(env_);
237         Label notString(env_);
238         BRANCH_CIR2(*result, &exit, &notString);
239         Bind(&notString);
240         {
241             GateRef objType = GetObjectType(LoadHClass(obj));
242             result = Equal(objType, Int32(static_cast<int32_t>(JSType::SYMBOL)));
243             Jump(&exit);
244         }
245     }
246     Bind(&exit);
247     auto ret = *result;
248     SubCfgExit();
249     return ret;
250 }
251 
TaggedIsProtoChangeMarker(GateRef obj)252 GateRef CircuitBuilder::TaggedIsProtoChangeMarker(GateRef obj)
253 {
254     Label entry(env_);
255     SubCfgEntry(&entry);
256     Label exit(env_);
257     DEFVALUE(result, env_, VariableType::BOOL(), False());
258     Label isHeapObject(env_);
259     BRANCH_CIR2(TaggedIsHeapObject(obj), &isHeapObject, &exit);
260     Bind(&isHeapObject);
261     {
262         GateRef objType = GetObjectType(LoadHClass(obj));
263         result = Equal(objType, Int32(static_cast<int32_t>(JSType::PROTO_CHANGE_MARKER)));
264         Jump(&exit);
265     }
266     Bind(&exit);
267     auto ret = *result;
268     SubCfgExit();
269     return ret;
270 }
271 
TaggedObjectIsJSMap(GateRef obj)272 GateRef CircuitBuilder::TaggedObjectIsJSMap(GateRef obj)
273 {
274     GateRef objType = GetObjectType(LoadHClass(obj));
275     return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_MAP)));
276 }
277 
TaggedObjectIsJSSet(GateRef obj)278 GateRef CircuitBuilder::TaggedObjectIsJSSet(GateRef obj)
279 {
280     GateRef objType = GetObjectType(LoadHClass(obj));
281     return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_SET)));
282 }
283 
TaggedObjectIsJSDate(GateRef obj)284 GateRef CircuitBuilder::TaggedObjectIsJSDate(GateRef obj)
285 {
286     GateRef objType = GetObjectType(LoadHClass(obj));
287     return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_DATE)));
288 }
289 
TaggedObjectIsTypedArray(GateRef obj)290 GateRef CircuitBuilder::TaggedObjectIsTypedArray(GateRef obj)
291 {
292     GateRef jsType = GetObjectType(LoadHClass(obj));
293     return BitAnd(Int32GreaterThan(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY_FIRST))),
294                   Int32GreaterThanOrEqual(Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY_LAST)), jsType));
295 }
296 
TaggedObjectIsJSArray(GateRef obj)297 GateRef CircuitBuilder::TaggedObjectIsJSArray(GateRef obj)
298 {
299     GateRef objType = GetObjectType(LoadHClass(obj));
300     return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_ARRAY)));
301 }
302 
TaggedIsBoundFunction(GateRef obj)303 GateRef CircuitBuilder::TaggedIsBoundFunction(GateRef obj)
304 {
305     GateRef objType = GetObjectType(LoadHClass(obj));
306     return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_BOUND_FUNCTION)));
307 }
308 
JudgeAotAndFastCall(GateRef jsFunc,JudgeMethodType type)309 inline GateRef CircuitBuilder::JudgeAotAndFastCall(GateRef jsFunc, JudgeMethodType type)
310 {
311     GateRef bitFieldOffset = IntPtr(JSFunctionBase::BIT_FIELD_OFFSET);
312     GateRef bitField = Load(VariableType::INT32(), jsFunc, bitFieldOffset);
313     switch (type) {
314         case JudgeMethodType::HAS_AOT: {
315             return Int32NotEqual(
316                 Int32And(
317                     Int32LSR(bitField, Int32(JSFunctionBase::IsCompiledCodeBit::START_BIT)),
318                     Int32((1U << JSFunctionBase::IsCompiledCodeBit::SIZE) - 1)),
319                 Int32(0));
320         }
321         case JudgeMethodType::HAS_AOT_FASTCALL: {
322             return Int32Equal(
323                 Int32And(
324                     bitField,
325                     Int32(JSFunctionBase::COMPILED_CODE_FASTCALL_BITS << JSFunctionBase::IsCompiledCodeBit::START_BIT)),
326                 Int32(JSFunctionBase::COMPILED_CODE_FASTCALL_BITS << JSFunctionBase::IsCompiledCodeBit::START_BIT));
327         }
328         case JudgeMethodType::HAS_AOT_NOTFASTCALL: {
329             GateRef fastCallField =
330                 Int32And(bitField,
331                     Int32(JSFunctionBase::COMPILED_CODE_FASTCALL_BITS << JSFunctionBase::IsCompiledCodeBit::START_BIT));
332             GateRef hasAot = Int32(1U << JSFunctionBase::IsCompiledCodeBit::START_BIT);
333             return Int32Equal(fastCallField, hasAot);
334         }
335         default:
336             UNREACHABLE();
337     }
338 }
339 
BothAreString(GateRef x,GateRef y)340 GateRef CircuitBuilder::BothAreString(GateRef x, GateRef y)
341 {
342     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(TaggedIsHeapObject(y))
343         .And(TaggedObjectIsString(x)).And(TaggedObjectIsString(y)).Done();
344 }
345 
TaggedIsHole(GateRef x)346 GateRef CircuitBuilder::TaggedIsHole(GateRef x)
347 {
348     return Equal(x, HoleConstant());
349 }
350 
TaggedIsNullPtr(GateRef x)351 GateRef CircuitBuilder::TaggedIsNullPtr(GateRef x)
352 {
353     return Equal(x, NullPtrConstant());
354 }
355 
IsSpecialHole(GateRef x)356 GateRef CircuitBuilder::IsSpecialHole(GateRef x)
357 {
358     return Equal(x, SpecialHoleConstant());
359 }
360 
IsNotSpecialHole(GateRef x)361 GateRef CircuitBuilder::IsNotSpecialHole(GateRef x)
362 {
363     return NotEqual(x, SpecialHoleConstant());
364 }
365 
TaggedIsNotHole(GateRef x)366 GateRef CircuitBuilder::TaggedIsNotHole(GateRef x)
367 {
368     return NotEqual(x, HoleConstant());
369 }
370 
TaggedIsUndefined(GateRef x)371 GateRef CircuitBuilder::TaggedIsUndefined(GateRef x)
372 {
373     return Equal(x, UndefineConstant());
374 }
375 
TaggedIsException(GateRef x)376 GateRef CircuitBuilder::TaggedIsException(GateRef x)
377 {
378     return Equal(x, ExceptionConstant());
379 }
380 
TaggedIsSpecial(GateRef x)381 GateRef CircuitBuilder::TaggedIsSpecial(GateRef x)
382 {
383     return LogicOrBuilder(env_)
384         .Or(TaggedIsHole(x))
385         .Or(Equal(Int64And(ChangeTaggedPointerToInt64(x), Int64(JSTaggedValue::TAG_SPECIAL_MASK)),
386                   Int64(JSTaggedValue::TAG_SPECIAL)))
387         .Done();
388 }
389 
TaggedIsHeapObject(GateRef x)390 GateRef CircuitBuilder::TaggedIsHeapObject(GateRef x)
391 {
392     x = ChangeTaggedPointerToInt64(x);
393     auto t = Int64And(x, Int64(JSTaggedValue::TAG_HEAPOBJECT_MASK), GateType::Empty(), "checkHeapObject");
394     return Equal(t, Int64(0), "checkHeapObject");
395 }
396 
TaggedIsAsyncGeneratorObject(GateRef x)397 GateRef CircuitBuilder::TaggedIsAsyncGeneratorObject(GateRef x)
398 {
399     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::JS_ASYNC_GENERATOR_OBJECT)).Done();
400 }
401 
TaggedIsJSGlobalObject(GateRef x)402 GateRef CircuitBuilder::TaggedIsJSGlobalObject(GateRef x)
403 {
404     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::JS_GLOBAL_OBJECT)).Done();
405 }
406 
TaggedIsGeneratorObject(GateRef x)407 GateRef CircuitBuilder::TaggedIsGeneratorObject(GateRef x)
408 {
409     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::JS_GENERATOR_OBJECT)).Done();
410 }
411 
TaggedIsJSArray(GateRef x)412 GateRef CircuitBuilder::TaggedIsJSArray(GateRef x)
413 {
414     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::JS_ARRAY)).Done();
415 }
416 
TaggedIsPropertyBox(GateRef x)417 GateRef CircuitBuilder::TaggedIsPropertyBox(GateRef x)
418 {
419     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::PROPERTY_BOX)).Done();
420 }
421 
TaggedIsWeak(GateRef x)422 GateRef CircuitBuilder::TaggedIsWeak(GateRef x)
423 {
424     return LogicAndBuilder(env_)
425         .And(TaggedIsHeapObject(x))
426         .And(Equal(Int64And(ChangeTaggedPointerToInt64(x), Int64(JSTaggedValue::TAG_WEAK)), Int64(1)))
427         .Done();
428 }
429 
TaggedIsPrototypeHandler(GateRef x)430 GateRef CircuitBuilder::TaggedIsPrototypeHandler(GateRef x)
431 {
432     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::PROTOTYPE_HANDLER)).Done();
433 }
434 
TaggedIsTransitionHandler(GateRef x)435 GateRef CircuitBuilder::TaggedIsTransitionHandler(GateRef x)
436 {
437     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::TRANSITION_HANDLER)).Done();
438 }
439 
TaggedIsStoreTSHandler(GateRef x)440 GateRef CircuitBuilder::TaggedIsStoreTSHandler(GateRef x)
441 {
442     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::STORE_TS_HANDLER)).Done();
443 }
444 
TaggedIsTransWithProtoHandler(GateRef x)445 GateRef CircuitBuilder::TaggedIsTransWithProtoHandler(GateRef x)
446 {
447     return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::TRANS_WITH_PROTO_HANDLER)).Done();
448 }
449 
TaggedIsUndefinedOrNull(GateRef x)450 GateRef CircuitBuilder::TaggedIsUndefinedOrNull(GateRef x)
451 {
452     x = ChangeTaggedPointerToInt64(x);
453     GateRef heapObjMask = Int64(JSTaggedValue::TAG_HEAPOBJECT_MASK);
454     GateRef tagSpecial = Int64(JSTaggedValue::TAG_SPECIAL);
455     GateRef andGate = Int64And(x, heapObjMask);
456     GateRef result = Equal(andGate, tagSpecial);
457     return result;
458 }
459 
TaggedIsUndefinedOrNullOrHole(GateRef x)460 GateRef CircuitBuilder::TaggedIsUndefinedOrNullOrHole(GateRef x)
461 {
462     return BitOr(TaggedIsHole(x), TaggedIsUndefinedOrNull(x));
463 }
464 
TaggedIsNotUndefinedAndNull(GateRef x)465 GateRef CircuitBuilder::TaggedIsNotUndefinedAndNull(GateRef x)
466 {
467     x = ChangeTaggedPointerToInt64(x);
468     GateRef heapObjMask = Int64(JSTaggedValue::TAG_HEAPOBJECT_MASK);
469     GateRef tagSpecial = Int64(JSTaggedValue::TAG_SPECIAL);
470     GateRef andGate = Int64And(x, heapObjMask);
471     GateRef result = NotEqual(andGate, tagSpecial);
472     return result;
473 }
474 
TaggedIsNotUndefinedAndNullAndHole(GateRef x)475 GateRef CircuitBuilder::TaggedIsNotUndefinedAndNullAndHole(GateRef x)
476 {
477     return BitAnd(TaggedIsNotHole(x), TaggedIsNotUndefinedAndNull(x));
478 }
479 
TaggedIsUndefinedOrHole(GateRef x)480 GateRef CircuitBuilder::TaggedIsUndefinedOrHole(GateRef x)
481 {
482     GateRef isUndefined = TaggedIsUndefined(x);
483     GateRef isHole = TaggedIsHole(x);
484     GateRef result = BitOr(isHole, isUndefined);
485     return result;
486 }
487 
TaggedTrue()488 GateRef CircuitBuilder::TaggedTrue()
489 {
490     return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_TRUE, GateType::TaggedValue());
491 }
492 
TaggedFalse()493 GateRef CircuitBuilder::TaggedFalse()
494 {
495     return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_FALSE, GateType::TaggedValue());
496 }
497 
TaggedIsTrue(GateRef x)498 GateRef CircuitBuilder::TaggedIsTrue(GateRef x)
499 {
500     return Equal(x, TaggedTrue());
501 }
502 
TaggedIsFalse(GateRef x)503 GateRef CircuitBuilder::TaggedIsFalse(GateRef x)
504 {
505     return Equal(x, TaggedFalse());
506 }
507 
TaggedIsNull(GateRef x)508 GateRef CircuitBuilder::TaggedIsNull(GateRef x)
509 {
510     return Equal(x, NullConstant());
511 }
512 
TaggedIsNotNull(GateRef x)513 GateRef CircuitBuilder::TaggedIsNotNull(GateRef x)
514 {
515     return NotEqual(x, NullConstant());
516 }
517 
TaggedIsBoolean(GateRef x)518 GateRef CircuitBuilder::TaggedIsBoolean(GateRef x)
519 {
520     return BitOr(TaggedIsFalse(x), TaggedIsTrue(x));
521 }
522 
TaggedGetInt(GateRef x)523 GateRef CircuitBuilder::TaggedGetInt(GateRef x)
524 {
525     x = ChangeTaggedPointerToInt64(x);
526     return TruncInt64ToInt32(Int64And(x, Int64(~JSTaggedValue::TAG_MARK)));
527 }
528 
TypedCallBuiltin(GateRef hirGate,const std::vector<GateRef> & args,BuiltinsStubCSigns::ID id,bool isSideEffect)529 inline GateRef CircuitBuilder::TypedCallBuiltin(GateRef hirGate, const std::vector<GateRef> &args,
530                                                 BuiltinsStubCSigns::ID id, bool isSideEffect)
531 {
532     auto currentLabel = env_->GetCurrentLabel();
533     auto currentControl = currentLabel->GetControl();
534     auto currentDepend = currentLabel->GetDepend();
535 
536     std::vector<GateRef> inList { currentControl, currentDepend };
537     inList.insert(inList.end(), args.begin(), args.end());
538     inList.push_back(Int16(static_cast<int16_t>(id)));
539     AppendFrameArgs(inList, hirGate);
540 
541     auto builtinOp = TypedCallOperator(hirGate, MachineType::I64, inList, isSideEffect);
542     currentLabel->SetControl(builtinOp);
543     currentLabel->SetDepend(builtinOp);
544     return builtinOp;
545 }
546 
547 template<TypedBinOp Op>
TypedBinaryOp(GateRef x,GateRef y,ParamType paramType)548 GateRef CircuitBuilder::TypedBinaryOp(GateRef x, GateRef y, ParamType paramType)
549 {
550     auto currentLabel = env_->GetCurrentLabel();
551     auto currentControl = currentLabel->GetControl();
552     auto currentDepend = currentLabel->GetDepend();
553     uint64_t value = TypedBinaryAccessor::ToValue(paramType, Op);
554     auto numberBinaryOp = GetCircuit()->NewGate(circuit_->TypedBinaryOp(value),
555         MachineType::I64, {currentControl, currentDepend, x, y}, GateType::AnyType());
556     currentLabel->SetControl(numberBinaryOp);
557     currentLabel->SetDepend(numberBinaryOp);
558     return numberBinaryOp;
559 }
560 
561 template<TypedCallTargetCheckOp Op>
JSNoGCCallThisTargetTypeCheck(GateRef func,GateRef methodId,GateRef gate)562 GateRef CircuitBuilder::JSNoGCCallThisTargetTypeCheck(GateRef func, GateRef methodId, GateRef gate)
563 {
564     auto currentLabel = env_->GetCurrentLabel();
565     auto currentControl = currentLabel->GetControl();
566     auto currentDepend = currentLabel->GetDepend();
567     auto frameState = acc_.GetFrameState(gate);
568     uint64_t value = TypedCallTargetCheckAccessor::ToValue(Op);
569     GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(value), MachineType::I1,
570         {currentControl, currentDepend, func, methodId, frameState}, GateType::NJSValue());
571     currentLabel->SetControl(ret);
572     currentLabel->SetDepend(ret);
573     return ret;
574 }
575 
576 template<TypedCallTargetCheckOp Op>
JSCallTargetTypeCheck(GateRef func,GateRef methodIndex,GateRef gate)577 GateRef CircuitBuilder::JSCallTargetTypeCheck(GateRef func, GateRef methodIndex, GateRef gate)
578 {
579     auto currentLabel = env_->GetCurrentLabel();
580     auto currentControl = currentLabel->GetControl();
581     auto currentDepend = currentLabel->GetDepend();
582     auto frameState = acc_.GetFrameState(gate);
583     uint64_t value = TypedCallTargetCheckAccessor::ToValue(Op);
584     GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(value), MachineType::I1,
585         {currentControl, currentDepend, func, methodIndex, frameState}, GateType::NJSValue());
586     currentLabel->SetControl(ret);
587     currentLabel->SetDepend(ret);
588     return ret;
589 }
590 
591 template<TypedUnOp Op>
TypedUnaryOp(GateRef x,ParamType paramType)592 GateRef CircuitBuilder::TypedUnaryOp(GateRef x, ParamType paramType)
593 {
594     auto currentLabel = env_->GetCurrentLabel();
595     auto currentControl = currentLabel->GetControl();
596     auto currentDepend = currentLabel->GetDepend();
597     uint64_t value = TypedUnaryAccessor::ToValue(paramType, Op);
598     auto numberUnaryOp = GetCircuit()->NewGate(circuit_->TypedUnaryOp(value),
599         MachineType::I64, {currentControl, currentDepend, x}, GateType::AnyType());
600     currentLabel->SetControl(numberUnaryOp);
601     currentLabel->SetDepend(numberUnaryOp);
602     return numberUnaryOp;
603 }
604 
605 template<TypedJumpOp Op>
TypedConditionJump(GateRef x,ParamType paramType,uint32_t weight)606 GateRef CircuitBuilder::TypedConditionJump(GateRef x, ParamType paramType, uint32_t weight)
607 {
608     auto currentLabel = env_->GetCurrentLabel();
609     auto currentControl = currentLabel->GetControl();
610     auto currentDepend = currentLabel->GetDepend();
611     auto machineType = MachineType::NOVALUE;
612     auto jumpOp = TypedConditionJump(machineType, Op, weight, paramType, {currentControl, currentDepend, x});
613     currentLabel->SetControl(jumpOp);
614     currentLabel->SetDepend(jumpOp);
615     return jumpOp;
616 }
617 
618 template <TypedLoadOp Op>
LoadElement(GateRef receiver,GateRef index,OnHeapMode onHeap)619 GateRef CircuitBuilder::LoadElement(GateRef receiver, GateRef index, OnHeapMode onHeap)
620 {
621     auto currentLabel = env_->GetCurrentLabel();
622     auto currentControl = currentLabel->GetControl();
623     auto currentDepend = currentLabel->GetDepend();
624     LoadElementAccessor accessor(Op, onHeap);
625     auto ret = GetCircuit()->NewGate(GetCircuit()->LoadElement(accessor.ToValue()), MachineType::I64,
626                                      {currentControl, currentDepend, receiver, index}, GateType::AnyType());
627     currentLabel->SetControl(ret);
628     currentLabel->SetDepend(ret);
629     return ret;
630 }
631 
632 template <TypedStoreOp Op>
StoreElement(GateRef receiver,GateRef index,GateRef value,OnHeapMode onHeap)633 GateRef CircuitBuilder::StoreElement(GateRef receiver, GateRef index, GateRef value, OnHeapMode onHeap)
634 {
635     auto currentLabel = env_->GetCurrentLabel();
636     auto currentControl = currentLabel->GetControl();
637     auto currentDepend = currentLabel->GetDepend();
638     StoreElementAccessor accessor(Op, onHeap);
639     auto ret = GetCircuit()->NewGate(GetCircuit()->StoreElement(accessor.ToValue()), MachineType::NOVALUE,
640                                      {currentControl, currentDepend, receiver, index, value}, GateType::AnyType());
641     currentLabel->SetControl(ret);
642     currentLabel->SetDepend(ret);
643     return ret;
644 }
645 
PrimitiveToNumber(GateRef x,ParamType paramType)646 GateRef CircuitBuilder::PrimitiveToNumber(GateRef x, ParamType paramType)
647 {
648     auto currentLabel = env_->GetCurrentLabel();
649     auto currentControl = currentLabel->GetControl();
650     auto currentDepend = currentLabel->GetDepend();
651 
652     auto numberconvert = TypeConvert(MachineType::I64, paramType, GateType::NumberType(),
653                                      {currentControl, currentDepend, x});
654     currentLabel->SetControl(numberconvert);
655     currentLabel->SetDepend(numberconvert);
656     return numberconvert;
657 }
658 
LoadFromTaggedArray(GateRef array,size_t index)659 GateRef CircuitBuilder::LoadFromTaggedArray(GateRef array, size_t index)
660 {
661     auto dataOffset = TaggedArray::DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize();
662     return LoadConstOffset(VariableType::JS_ANY(), array, dataOffset);
663 }
664 
StoreToTaggedArray(GateRef array,size_t index,GateRef value)665 GateRef CircuitBuilder::StoreToTaggedArray(GateRef array, size_t index, GateRef value)
666 {
667     auto dataOffset = TaggedArray::DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize();
668     return StoreConstOffset(VariableType::JS_ANY(), array, dataOffset, value);
669 }
670 
TreeStringIsFlat(GateRef string)671 GateRef CircuitBuilder::TreeStringIsFlat(GateRef string)
672 {
673     GateRef second = GetSecondFromTreeString(string);
674     GateRef len = GetLengthFromString(second);
675     return Int32Equal(len, Int32(0));
676 }
677 
GetFirstFromTreeString(GateRef string)678 GateRef CircuitBuilder::GetFirstFromTreeString(GateRef string)
679 {
680     GateRef offset = IntPtr(TreeEcmaString::FIRST_OFFSET);
681     return Load(VariableType::JS_POINTER(), string, offset);
682 }
683 
GetSecondFromTreeString(GateRef string)684 GateRef CircuitBuilder::GetSecondFromTreeString(GateRef string)
685 {
686     GateRef offset = IntPtr(TreeEcmaString::SECOND_OFFSET);
687     return Load(VariableType::JS_POINTER(), string, offset);
688 }
689 
GetValueFromTaggedArray(GateRef array,GateRef index)690 GateRef CircuitBuilder::GetValueFromTaggedArray(GateRef array, GateRef index)
691 {
692     GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
693     GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
694     return Load(VariableType::JS_ANY(), array, dataOffset);
695 }
696 
GetValueFromTaggedArray(VariableType valType,GateRef array,GateRef index)697 GateRef CircuitBuilder::GetValueFromTaggedArray(VariableType valType, GateRef array, GateRef index)
698 {
699     GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
700     GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
701     return Load(valType, array, dataOffset);
702 }
703 
GetValueFromJSArrayWithElementsKind(VariableType type,GateRef array,GateRef index)704 GateRef CircuitBuilder::GetValueFromJSArrayWithElementsKind(VariableType type, GateRef array, GateRef index)
705 {
706     GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
707     GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
708     return Load(type, array, dataOffset);
709 }
710 
SetValueToTaggedArray(VariableType valType,GateRef glue,GateRef array,GateRef index,GateRef val)711 void CircuitBuilder::SetValueToTaggedArray(VariableType valType, GateRef glue,
712                                            GateRef array, GateRef index, GateRef val)
713 {
714     GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
715     GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
716     Store(valType, glue, array, dataOffset, val);
717 }
718 }
719 
720 #endif  // ECMASCRIPT_COMPILER_MCR_CIRCUIT_BUILDER_H
721