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