• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #ifndef ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_INL_H
16 #define ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_INL_H
17 
18 #include "ecmascript/compiler/circuit_builder.h"
19 #include "ecmascript/mem/region.h"
20 #include "ecmascript/method.h"
21 
22 namespace panda::ecmascript::kungfu {
23 // constant
True()24 GateRef CircuitBuilder::True()
25 {
26     return TruncInt32ToInt1(Int32(1));
27 }
28 
False()29 GateRef CircuitBuilder::False()
30 {
31     return TruncInt32ToInt1(Int32(0));
32 }
33 
Undefined()34 GateRef CircuitBuilder::Undefined()
35 {
36     return UndefineConstant();
37 }
38 
Hole()39 GateRef CircuitBuilder::Hole()
40 {
41     return HoleConstant();
42 }
43 
Equal(GateRef x,GateRef y)44 GateRef CircuitBuilder::Equal(GateRef x, GateRef y)
45 {
46     auto xType = acc_.GetMachineType(x);
47     switch (xType) {
48         case ARCH:
49         case FLEX:
50         case I1:
51         case I8:
52         case I16:
53         case I32:
54         case I64:
55             return BinaryCmp(circuit_->Icmp(static_cast<uint64_t>(ICmpCondition::EQ)), x, y);
56         case F32:
57         case F64:
58             return BinaryCmp(circuit_->Fcmp(static_cast<uint64_t>(FCmpCondition::OEQ)), x, y);
59         default:
60             LOG_ECMA(FATAL) << "this branch is unreachable";
61             UNREACHABLE();
62     }
63 }
64 
NotEqual(GateRef x,GateRef y)65 GateRef CircuitBuilder::NotEqual(GateRef x, GateRef y)
66 {
67     auto xType = acc_.GetMachineType(x);
68     switch (xType) {
69         case ARCH:
70         case FLEX:
71         case I1:
72         case I8:
73         case I16:
74         case I32:
75         case I64:
76             return BinaryCmp(circuit_->Icmp(static_cast<uint64_t>(ICmpCondition::NE)), x, y);
77         case F32:
78         case F64:
79             return BinaryCmp(circuit_->Fcmp(static_cast<uint64_t>(FCmpCondition::ONE)), x, y);
80         default:
81             LOG_ECMA(FATAL) << "this branch is unreachable";
82             UNREACHABLE();
83     }
84 }
85 
86 // memory
Load(VariableType type,GateRef base,GateRef offset)87 GateRef CircuitBuilder::Load(VariableType type, GateRef base, GateRef offset)
88 {
89     auto label = GetCurrentLabel();
90     auto depend = label->GetDepend();
91     GateRef val = PtrAdd(base, offset);
92     GateRef result = GetCircuit()->NewGate(GetCircuit()->Load(), type.GetMachineType(),
93                                            { depend, val }, type.GetGateType());
94     label->SetDepend(result);
95     return result;
96 }
97 
Load(VariableType type,GateRef base,GateRef offset,GateRef depend)98 GateRef CircuitBuilder::Load(VariableType type, GateRef base, GateRef offset, GateRef depend)
99 {
100     GateRef val = PtrAdd(base, offset);
101     GateRef result = GetCircuit()->NewGate(GetCircuit()->Load(), type.GetMachineType(),
102                                            { depend, val }, type.GetGateType());
103     return result;
104 }
105 
106 // Js World
107 // cast operation
GetInt64OfTInt(GateRef x)108 GateRef CircuitBuilder::GetInt64OfTInt(GateRef x)
109 {
110     GateRef tagged = ChangeTaggedPointerToInt64(x);
111     return Int64And(tagged, Int64(~JSTaggedValue::TAG_MARK));
112 }
113 
GetInt32OfTInt(GateRef x)114 GateRef CircuitBuilder::GetInt32OfTInt(GateRef x)
115 {
116     GateRef tagged = ChangeTaggedPointerToInt64(x);
117     return TruncInt64ToInt32(tagged);
118 }
119 
TaggedCastToIntPtr(GateRef x)120 GateRef CircuitBuilder::TaggedCastToIntPtr(GateRef x)
121 {
122     ASSERT(cmpCfg_ != nullptr);
123     return cmpCfg_->Is32Bit() ? GetInt32OfTInt(x) : GetInt64OfTInt(x);
124 }
125 
GetDoubleOfTDouble(GateRef x)126 GateRef CircuitBuilder::GetDoubleOfTDouble(GateRef x)
127 {
128     GateRef tagged = ChangeTaggedPointerToInt64(x);
129     GateRef val = Int64Sub(tagged, Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET));
130     return CastInt64ToFloat64(val);
131 }
132 
GetBooleanOfTBoolean(GateRef x)133 GateRef CircuitBuilder::GetBooleanOfTBoolean(GateRef x)
134 {
135     GateRef tagged = ChangeTaggedPointerToInt64(x);
136     return TruncInt64ToInt1(tagged);
137 }
138 
GetDoubleOfTNumber(GateRef x)139 GateRef CircuitBuilder::GetDoubleOfTNumber(GateRef x)
140 {
141     Label subentry(env_);
142     SubCfgEntry(&subentry);
143     Label isInt(env_);
144     Label isDouble(env_);
145     Label exit(env_);
146     DEFVAlUE(result, env_, VariableType::FLOAT64(), Double(0));
147     Branch(TaggedIsInt(x), &isInt, &isDouble);
148     Bind(&isInt);
149     {
150         result = ChangeInt32ToFloat64(GetInt32OfTInt(x));
151         Jump(&exit);
152     }
153     Bind(&isDouble);
154     {
155         result = GetDoubleOfTDouble(x);
156         Jump(&exit);
157     }
158     Bind(&exit);
159     GateRef ret = *result;
160     SubCfgExit();
161     return ret;
162 }
163 
DoubleToInt(GateRef x,Label * exit)164 GateRef CircuitBuilder::DoubleToInt(GateRef x, Label *exit)
165 {
166     Label overflow(env_);
167 
168     GateRef xInt = ChangeFloat64ToInt32(x);
169     DEFVAlUE(result, env_, VariableType::INT32(), xInt);
170 
171     GateRef xInt64 = CastDoubleToInt64(x);
172     // exp = (u64 & DOUBLE_EXPONENT_MASK) >> DOUBLE_SIGNIFICAND_SIZE - DOUBLE_EXPONENT_BIAS
173     GateRef exp = Int64And(xInt64, Int64(base::DOUBLE_EXPONENT_MASK));
174     exp = TruncInt64ToInt32(Int64LSR(exp, Int64(base::DOUBLE_SIGNIFICAND_SIZE)));
175     exp = Int32Sub(exp, Int32(base::DOUBLE_EXPONENT_BIAS));
176     GateRef bits = Int32(base::INT32_BITS - 1);
177     // exp < 32 - 1
178     Branch(Int32LessThan(exp, bits), exit, &overflow);
179 
180     Bind(&overflow);
181     {
182         result = CallNGCRuntime(acc_.GetGlueFromArgList(), RTSTUB_ID(DoubleToInt),
183                                 Circuit::NullGate(), { x }, Circuit::NullGate());
184         Jump(exit);
185     }
186     Bind(exit);
187     auto ret = *result;
188     return ret;
189 }
190 
Int8Equal(GateRef x,GateRef y)191 GateRef CircuitBuilder::Int8Equal(GateRef x, GateRef y)
192 {
193     return Equal(x, y);
194 }
195 
Int32NotEqual(GateRef x,GateRef y)196 GateRef CircuitBuilder::Int32NotEqual(GateRef x, GateRef y)
197 {
198     return NotEqual(x, y);
199 }
200 
Int64NotEqual(GateRef x,GateRef y)201 GateRef CircuitBuilder::Int64NotEqual(GateRef x, GateRef y)
202 {
203     return NotEqual(x, y);
204 }
205 
Int64Equal(GateRef x,GateRef y)206 GateRef CircuitBuilder::Int64Equal(GateRef x, GateRef y)
207 {
208     return Equal(x, y);
209 }
210 
Int32Equal(GateRef x,GateRef y)211 GateRef CircuitBuilder::Int32Equal(GateRef x, GateRef y)
212 {
213     return Equal(x, y);
214 }
215 
IntPtrGreaterThan(GateRef x,GateRef y)216 GateRef CircuitBuilder::IntPtrGreaterThan(GateRef x, GateRef y)
217 {
218     return env_->Is32Bit() ? Int32GreaterThan(x, y) : Int64GreaterThan(x, y);
219 }
220 
221 template<OpCode Op, MachineType Type>
BinaryOp(GateRef x,GateRef y)222 GateRef CircuitBuilder::BinaryOp(GateRef x, GateRef y)
223 {
224     if (Op == OpCode::ADD) {
225         return BinaryArithmetic(circuit_->Add(), Type, x, y);
226     } else if (Op == OpCode::SUB) {
227         return BinaryArithmetic(circuit_->Sub(), Type, x, y);
228     } else if (Op == OpCode::MUL) {
229         return BinaryArithmetic(circuit_->Mul(), Type, x, y);
230     }
231     UNREACHABLE();
232     return Circuit::NullGate();
233 }
234 
235 template<OpCode Op, MachineType Type>
BinaryOpWithOverflow(GateRef x,GateRef y)236 GateRef CircuitBuilder::BinaryOpWithOverflow(GateRef x, GateRef y)
237 {
238     if (Op == OpCode::ADD) {
239         return BinaryArithmetic(circuit_->AddWithOverflow(), Type, x, y);
240     } else if (Op == OpCode::SUB) {
241         return BinaryArithmetic(circuit_->SubWithOverflow(), Type, x, y);
242     } else if (Op == OpCode::MUL) {
243         return BinaryArithmetic(circuit_->MulWithOverflow(), Type, x, y);
244     }
245     UNREACHABLE();
246     return Circuit::NullGate();
247 }
248 
IntPtrLSR(GateRef x,GateRef y)249 GateRef CircuitBuilder::IntPtrLSR(GateRef x, GateRef y)
250 {
251     auto ptrSize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64;
252     return BinaryArithmetic(circuit_->Lsr(), ptrSize, x, y);
253 }
254 
IntPtrLSL(GateRef x,GateRef y)255 GateRef CircuitBuilder::IntPtrLSL(GateRef x, GateRef y)
256 {
257     auto ptrSize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64;
258     return BinaryArithmetic(circuit_->Lsl(), ptrSize, x, y);
259 }
260 
IntPtrOr(GateRef x,GateRef y)261 GateRef CircuitBuilder::IntPtrOr(GateRef x, GateRef y)
262 {
263     auto ptrsize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64;
264     return BinaryArithmetic(circuit_->Or(), ptrsize, x, y);
265 }
266 
IntPtrDiv(GateRef x,GateRef y)267 GateRef CircuitBuilder::IntPtrDiv(GateRef x, GateRef y)
268 {
269     return env_->Is32Bit() ? Int32Div(x, y) : Int64Div(x, y);
270 }
271 
Int64ToTaggedPtr(GateRef x)272 GateRef CircuitBuilder::Int64ToTaggedPtr(GateRef x)
273 {
274     return GetCircuit()->NewGate(circuit_->Int64ToTagged(),
275         MachineType::I64, { x }, GateType::TaggedValue());
276 }
277 
Int32ToTaggedPtr(GateRef x)278 GateRef CircuitBuilder::Int32ToTaggedPtr(GateRef x)
279 {
280     GateRef val = SExtInt32ToInt64(x);
281     return Int64ToTaggedPtr(Int64Or(val, Int64(JSTaggedValue::TAG_INT)));
282 }
283 
Int32ToTaggedInt(GateRef x)284 GateRef CircuitBuilder::Int32ToTaggedInt(GateRef x)
285 {
286     GateRef val = SExtInt32ToInt64(x);
287     return Int64Or(val, Int64(JSTaggedValue::TAG_INT));
288 }
289 
290 // bit operation
IsSpecial(GateRef x,JSTaggedType type)291 GateRef CircuitBuilder::IsSpecial(GateRef x, JSTaggedType type)
292 {
293     auto specialValue = circuit_->GetConstantGate(
294         MachineType::I64, type, GateType::TaggedValue());
295 
296     return Equal(x, specialValue);
297 }
298 
TaggedIsInt(GateRef x)299 GateRef CircuitBuilder::TaggedIsInt(GateRef x)
300 {
301     x = ChangeTaggedPointerToInt64(x);
302     return Equal(Int64And(x, Int64(JSTaggedValue::TAG_MARK)),
303                  Int64(JSTaggedValue::TAG_INT));
304 }
305 
TaggedIsDouble(GateRef x)306 GateRef CircuitBuilder::TaggedIsDouble(GateRef x)
307 {
308     x = ChangeTaggedPointerToInt64(x);
309     x = Int64And(x, Int64(JSTaggedValue::TAG_MARK));
310     auto left = NotEqual(x, Int64(JSTaggedValue::TAG_INT));
311     auto right = NotEqual(x, Int64(JSTaggedValue::TAG_OBJECT));
312     return BoolAnd(left, right);
313 }
314 
TaggedIsObject(GateRef x)315 GateRef CircuitBuilder::TaggedIsObject(GateRef x)
316 {
317     x = ChangeTaggedPointerToInt64(x);
318     return Equal(Int64And(x, Int64(JSTaggedValue::TAG_MARK)),
319                  Int64(JSTaggedValue::TAG_OBJECT));
320 }
321 
TaggedIsNumber(GateRef x)322 GateRef CircuitBuilder::TaggedIsNumber(GateRef x)
323 {
324     return BoolNot(TaggedIsObject(x));
325 }
326 
TaggedIsNumeric(GateRef x)327 GateRef CircuitBuilder::TaggedIsNumeric(GateRef x)
328 {
329     return BoolOr(TaggedIsNumber(x), TaggedIsBigInt(x));
330 }
331 
DoubleIsINF(GateRef x)332 GateRef CircuitBuilder::DoubleIsINF(GateRef x)
333 {
334     GateRef infinity = Double(base::POSITIVE_INFINITY);
335     GateRef negativeInfinity = Double(-base::POSITIVE_INFINITY);
336     GateRef diff1 = DoubleEqual(x, infinity);
337     GateRef diff2 = DoubleEqual(x, negativeInfinity);
338     return BoolOr(diff1, diff2);
339 }
340 
TaggedIsHole(GateRef x)341 GateRef CircuitBuilder::TaggedIsHole(GateRef x)
342 {
343     return Equal(x, HoleConstant());
344 }
345 
TaggedIsNullPtr(GateRef x)346 GateRef CircuitBuilder::TaggedIsNullPtr(GateRef x)
347 {
348     return Equal(x, NullPtrConstant());
349 }
350 
TaggedIsNotHole(GateRef x)351 GateRef CircuitBuilder::TaggedIsNotHole(GateRef x)
352 {
353     return NotEqual(x, HoleConstant());
354 }
355 
TaggedIsUndefined(GateRef x)356 GateRef CircuitBuilder::TaggedIsUndefined(GateRef x)
357 {
358     return Equal(x, UndefineConstant());
359 }
360 
TaggedIsException(GateRef x)361 GateRef CircuitBuilder::TaggedIsException(GateRef x)
362 {
363     return Equal(x, ExceptionConstant());
364 }
365 
TaggedIsSpecial(GateRef x)366 GateRef CircuitBuilder::TaggedIsSpecial(GateRef x)
367 {
368     return BoolOr(
369         Equal(Int64And(ChangeTaggedPointerToInt64(x), Int64(JSTaggedValue::TAG_SPECIAL_MASK)),
370             Int64(JSTaggedValue::TAG_SPECIAL)),
371         TaggedIsHole(x));
372 }
373 
IsJSHClass(GateRef obj)374 inline GateRef CircuitBuilder::IsJSHClass(GateRef obj)
375 {
376     return Int32Equal(GetObjectType(LoadHClass(obj)), Int32(static_cast<int32_t>(JSType::HCLASS)));
377 }
378 
TaggedIsHeapObject(GateRef x)379 GateRef CircuitBuilder::TaggedIsHeapObject(GateRef x)
380 {
381     x = ChangeTaggedPointerToInt64(x);
382     return Equal(Int64And(x, Int64(JSTaggedValue::TAG_HEAPOBJECT_MASK)), Int64(0));
383 }
384 
TaggedIsAsyncGeneratorObject(GateRef x)385 GateRef CircuitBuilder::TaggedIsAsyncGeneratorObject(GateRef x)
386 {
387     GateRef isHeapObj = TaggedIsHeapObject(x);
388     GateRef objType = GetObjectType(LoadHClass(x));
389     GateRef isAsyncGeneratorObj = Equal(objType,
390         Int32(static_cast<int32_t>(JSType::JS_ASYNC_GENERATOR_OBJECT)));
391     return LogicAnd(isHeapObj, isAsyncGeneratorObj);
392 }
393 
TaggedIsJSGlobalObject(GateRef x)394 GateRef CircuitBuilder::TaggedIsJSGlobalObject(GateRef x)
395 {
396     GateRef isHeapObj = TaggedIsHeapObject(x);
397     GateRef objType = GetObjectType(LoadHClass(x));
398     GateRef isGlobal = Equal(objType,
399         Int32(static_cast<int32_t>(JSType::JS_GLOBAL_OBJECT)));
400     return LogicAnd(isHeapObj, isGlobal);
401 }
402 
TaggedIsGeneratorObject(GateRef x)403 GateRef CircuitBuilder::TaggedIsGeneratorObject(GateRef x)
404 {
405     GateRef isHeapObj = TaggedIsHeapObject(x);
406     GateRef objType = GetObjectType(LoadHClass(x));
407     GateRef isAsyncGeneratorObj = Equal(objType,
408         Int32(static_cast<int32_t>(JSType::JS_GENERATOR_OBJECT)));
409     return LogicAnd(isHeapObj, isAsyncGeneratorObj);
410 }
411 
TaggedIsJSArray(GateRef x)412 GateRef CircuitBuilder::TaggedIsJSArray(GateRef x)
413 {
414     GateRef objType = GetObjectType(LoadHClass(x));
415     GateRef isJSArray = Equal(objType, Int32(static_cast<int32_t>(JSType::JS_ARRAY)));
416     return isJSArray;
417 }
418 
TaggedIsPropertyBox(GateRef x)419 GateRef CircuitBuilder::TaggedIsPropertyBox(GateRef x)
420 {
421     return LogicAnd(TaggedIsHeapObject(x),
422         IsJsType(x, JSType::PROPERTY_BOX));
423 }
424 
TaggedIsWeak(GateRef x)425 GateRef CircuitBuilder::TaggedIsWeak(GateRef x)
426 {
427     return LogicAnd(TaggedIsHeapObject(x),
428         Equal(Int64And(ChangeTaggedPointerToInt64(x), Int64(JSTaggedValue::TAG_WEAK)), Int64(1)));
429 }
430 
TaggedIsPrototypeHandler(GateRef x)431 GateRef CircuitBuilder::TaggedIsPrototypeHandler(GateRef x)
432 {
433     return LogicAnd(TaggedIsHeapObject(x),
434         IsJsType(x, JSType::PROTOTYPE_HANDLER));
435 }
436 
TaggedIsTransitionHandler(GateRef x)437 GateRef CircuitBuilder::TaggedIsTransitionHandler(GateRef x)
438 {
439     return LogicAnd(TaggedIsHeapObject(x),
440         IsJsType(x, JSType::TRANSITION_HANDLER));
441 }
442 
TaggedIsStoreTSHandler(GateRef x)443 GateRef CircuitBuilder::TaggedIsStoreTSHandler(GateRef x)
444 {
445     return LogicAnd(TaggedIsHeapObject(x),
446         IsJsType(x, JSType::STORE_TS_HANDLER));
447 }
448 
TaggedIsTransWithProtoHandler(GateRef x)449 GateRef CircuitBuilder::TaggedIsTransWithProtoHandler(GateRef x)
450 {
451     return LogicAnd(TaggedIsHeapObject(x),
452         IsJsType(x, JSType::TRANS_WITH_PROTO_HANDLER));
453 }
454 
TaggedIsUndefinedOrNull(GateRef x)455 GateRef CircuitBuilder::TaggedIsUndefinedOrNull(GateRef x)
456 {
457     return BoolOr(TaggedIsUndefined(x), TaggedIsNull(x));
458 }
459 
TaggedIsTrue(GateRef x)460 GateRef CircuitBuilder::TaggedIsTrue(GateRef x)
461 {
462     return Equal(x, TaggedTrue());
463 }
464 
TaggedIsFalse(GateRef x)465 GateRef CircuitBuilder::TaggedIsFalse(GateRef x)
466 {
467     return Equal(x, TaggedFalse());
468 }
469 
TaggedIsNull(GateRef x)470 GateRef CircuitBuilder::TaggedIsNull(GateRef x)
471 {
472     return Equal(x, NullConstant());
473 }
474 
TaggedIsBoolean(GateRef x)475 GateRef CircuitBuilder::TaggedIsBoolean(GateRef x)
476 {
477     return BoolOr(TaggedIsFalse(x), TaggedIsTrue(x));
478 }
479 
IsAOTLiteralInfo(GateRef x)480 GateRef CircuitBuilder::IsAOTLiteralInfo(GateRef x)
481 {
482     GateRef isHeapObj = TaggedIsHeapObject(x);
483     GateRef objType = GetObjectType(LoadHClass(x));
484     GateRef isAOTLiteralInfoObj = Equal(objType,
485         Int32(static_cast<int32_t>(JSType::AOT_LITERAL_INFO)));
486     return LogicAnd(isHeapObj, isAOTLiteralInfoObj);
487 }
488 
TaggedGetInt(GateRef x)489 GateRef CircuitBuilder::TaggedGetInt(GateRef x)
490 {
491     x = ChangeTaggedPointerToInt64(x);
492     return TruncInt64ToInt32(Int64And(x, Int64(~JSTaggedValue::TAG_MARK)));
493 }
494 
ToTaggedInt(GateRef x)495 GateRef CircuitBuilder::ToTaggedInt(GateRef x)
496 {
497     return Int64Or(x, Int64(JSTaggedValue::TAG_INT));
498 }
499 
ToTaggedIntPtr(GateRef x)500 GateRef CircuitBuilder::ToTaggedIntPtr(GateRef x)
501 {
502     return Int64ToTaggedPtr(Int64Or(x, Int64(JSTaggedValue::TAG_INT)));
503 }
504 
DoubleToTaggedDoublePtr(GateRef x)505 GateRef CircuitBuilder::DoubleToTaggedDoublePtr(GateRef x)
506 {
507     GateRef val = CastDoubleToInt64(x);
508     return Int64ToTaggedPtr(Int64Add(val, Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET)));
509 }
510 
BooleanToTaggedBooleanPtr(GateRef x)511 GateRef CircuitBuilder::BooleanToTaggedBooleanPtr(GateRef x)
512 {
513     auto val = ZExtInt1ToInt64(x);
514     return Int64ToTaggedPtr(Int64Or(val, Int64(JSTaggedValue::TAG_BOOLEAN_MASK)));
515 }
516 
BooleanToInt32(GateRef x)517 GateRef CircuitBuilder::BooleanToInt32(GateRef x)
518 {
519     return ZExtInt1ToInt32(x);
520 }
521 
BooleanToFloat64(GateRef x)522 GateRef CircuitBuilder::BooleanToFloat64(GateRef x)
523 {
524     return ChangeInt32ToFloat64(ZExtInt1ToInt32(x));
525 }
526 
Float32ToTaggedDoublePtr(GateRef x)527 GateRef CircuitBuilder::Float32ToTaggedDoublePtr(GateRef x)
528 {
529     GateRef val = ExtFloat32ToDouble(x);
530     return DoubleToTaggedDoublePtr(val);
531 }
532 
TaggedDoublePtrToFloat32(GateRef x)533 GateRef CircuitBuilder::TaggedDoublePtrToFloat32(GateRef x)
534 {
535     GateRef val = GetDoubleOfTDouble(x);
536     return TruncDoubleToFloat32(val);
537 }
538 
TaggedIntPtrToFloat32(GateRef x)539 GateRef CircuitBuilder::TaggedIntPtrToFloat32(GateRef x)
540 {
541     GateRef val = GetInt32OfTInt(x);
542     return ChangeInt32ToFloat32(val);
543 }
544 
DoubleToTaggedDouble(GateRef x)545 GateRef CircuitBuilder::DoubleToTaggedDouble(GateRef x)
546 {
547     GateRef val = CastDoubleToInt64(x);
548     return Int64Add(val, Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET));
549 }
550 
DoubleIsNAN(GateRef x)551 GateRef CircuitBuilder::DoubleIsNAN(GateRef x)
552 {
553     GateRef diff = DoubleEqual(x, x);
554     return Equal(SExtInt1ToInt32(diff), Int32(0));
555 }
556 
DoubleToTagged(GateRef x)557 GateRef CircuitBuilder::DoubleToTagged(GateRef x)
558 {
559     GateRef val = CastDoubleToInt64(x);
560     acc_.SetGateType(val, GateType::TaggedValue());
561     return Int64Add(val, Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET));
562 }
563 
TaggedTrue()564 GateRef CircuitBuilder::TaggedTrue()
565 {
566     return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_TRUE, GateType::TaggedValue());
567 }
568 
TaggedFalse()569 GateRef CircuitBuilder::TaggedFalse()
570 {
571     return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_FALSE, GateType::TaggedValue());
572 }
573 
GetLengthFromTaggedArray(GateRef array)574 GateRef CircuitBuilder::GetLengthFromTaggedArray(GateRef array)
575 {
576     GateRef offset = IntPtr(TaggedArray::LENGTH_OFFSET);
577     return Load(VariableType::INT32(), array, offset);
578 }
579 
GetValueFromTaggedArray(GateRef array,GateRef index)580 GateRef CircuitBuilder::GetValueFromTaggedArray(GateRef array, GateRef index)
581 {
582     GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
583     GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
584     return Load(VariableType::JS_ANY(), array, dataOffset);
585 }
586 
SetValueToTaggedArray(VariableType valType,GateRef glue,GateRef array,GateRef index,GateRef val)587 void CircuitBuilder::SetValueToTaggedArray(VariableType valType, GateRef glue,
588                                            GateRef array, GateRef index, GateRef val)
589 {
590     GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
591     GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
592     Store(valType, glue, array, dataOffset, val);
593 }
594 
GetGlobalConstantString(ConstantIndex index)595 GateRef CircuitBuilder::GetGlobalConstantString(ConstantIndex index)
596 {
597     return PtrMul(IntPtr(sizeof(JSTaggedValue)), IntPtr(static_cast<int>(index)));
598 }
599 
LoadObjectFromWeakRef(GateRef x)600 GateRef CircuitBuilder::LoadObjectFromWeakRef(GateRef x)
601 {
602     return PtrAdd(x, IntPtr(-JSTaggedValue::TAG_WEAK));
603 }
604 
605 // object operation
LoadHClass(GateRef object)606 GateRef CircuitBuilder::LoadHClass(GateRef object)
607 {
608     GateRef offset = IntPtr(TaggedObject::HCLASS_OFFSET);
609     return Load(VariableType::JS_POINTER(), object, offset);
610 }
611 
StoreHClass(GateRef glue,GateRef object,GateRef hClass)612 void CircuitBuilder::StoreHClass(GateRef glue, GateRef object, GateRef hClass)
613 {
614     Store(VariableType::JS_POINTER(), glue, object, IntPtr(TaggedObject::HCLASS_OFFSET), hClass);
615 }
616 
IsJSFunction(GateRef obj)617 inline GateRef CircuitBuilder::IsJSFunction(GateRef obj)
618 {
619     GateRef objectType = GetObjectType(LoadHClass(obj));
620     GateRef greater = Int32GreaterThanOrEqual(objectType,
621         Int32(static_cast<int32_t>(JSType::JS_FUNCTION_FIRST)));
622     GateRef less = Int32LessThanOrEqual(objectType,
623         Int32(static_cast<int32_t>(JSType::JS_FUNCTION_LAST)));
624     return BoolAnd(greater, less);
625 }
626 
IsJSFunctionWithBit(GateRef obj)627 inline GateRef CircuitBuilder::IsJSFunctionWithBit(GateRef obj)
628 {
629     GateRef hClass = LoadHClass(obj);
630     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
631     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
632     return NotEqual(Int32And(bitfield, Int32(1LU << JSHClass::IsJSFunctionBit::START_BIT)), Int32(0));
633 }
634 
IsOptimizedAndNotFastCall(GateRef obj)635 inline GateRef CircuitBuilder::IsOptimizedAndNotFastCall(GateRef obj)
636 {
637     GateRef hClass = LoadHClass(obj);
638     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
639     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
640     GateRef optimizedFastCallBitsInBitfield = Int32And(bitfield, Int32(JSHClass::OPTIMIZED_FASTCALL_BITS));
641     return Equal(optimizedFastCallBitsInBitfield, Int32(JSHClass::OPTIMIZED_BIT));
642 }
643 
IsOptimized(GateRef obj)644 inline GateRef CircuitBuilder::IsOptimized(GateRef obj)
645 {
646     GateRef hClass = LoadHClass(obj);
647     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
648     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
649     return NotEqual(Int32And(bitfield, Int32(1LU << JSHClass::IsOptimizedBit::START_BIT)), Int32(0));
650 }
651 
IsOptimizedWithBitField(GateRef bitfield)652 inline GateRef CircuitBuilder::IsOptimizedWithBitField(GateRef bitfield)
653 {
654     return NotEqual(Int32And(bitfield, Int32(1LU << JSHClass::IsOptimizedBit::START_BIT)), Int32(0));
655 }
656 
CanFastCall(GateRef obj)657 inline GateRef CircuitBuilder::CanFastCall(GateRef obj)
658 {
659     GateRef hClass = LoadHClass(obj);
660     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
661     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
662     return NotEqual(Int32And(bitfield, Int32(1LU << JSHClass::CanFastCallBit::START_BIT)), Int32(0));
663 }
664 
CanFastCallWithBitField(GateRef bitfield)665 inline GateRef CircuitBuilder::CanFastCallWithBitField(GateRef bitfield)
666 {
667     return NotEqual(Int32And(bitfield, Int32(1LU << JSHClass::CanFastCallBit::START_BIT)), Int32(0));
668 }
669 
IsJsType(GateRef obj,JSType type)670 GateRef CircuitBuilder::IsJsType(GateRef obj, JSType type)
671 {
672     GateRef objectType = GetObjectType(LoadHClass(obj));
673     return Equal(objectType, Int32(static_cast<int32_t>(type)));
674 }
675 
IsDictionaryMode(GateRef object)676 inline GateRef CircuitBuilder::IsDictionaryMode(GateRef object)
677 {
678     GateRef type = GetObjectType(LoadHClass(object));
679     return Int32Equal(type, Int32(static_cast<int32_t>(JSType::TAGGED_DICTIONARY)));
680 }
681 
GetObjectType(GateRef hClass)682 GateRef CircuitBuilder::GetObjectType(GateRef hClass)
683 {
684     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
685     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
686     return Int32And(bitfield, Int32((1LU << JSHClass::ObjectTypeBits::SIZE) - 1));
687 }
688 
IsDictionaryModeByHClass(GateRef hClass)689 GateRef CircuitBuilder::IsDictionaryModeByHClass(GateRef hClass)
690 {
691     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
692     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
693     return NotEqual(Int32And(Int32LSR(bitfield,
694         Int32(JSHClass::IsDictionaryBit::START_BIT)),
695         Int32((1LU << JSHClass::IsDictionaryBit::SIZE) - 1)),
696         Int32(0));
697 }
698 
IsIsStableElementsByHClass(GateRef hClass)699 GateRef CircuitBuilder::IsIsStableElementsByHClass(GateRef hClass)
700 {
701     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
702     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
703     return NotEqual(Int32And(Int32LSR(bitfield,
704         Int32(JSHClass::IsStableElementsBit::START_BIT)),
705         Int32((1LU << JSHClass::IsStableElementsBit::SIZE) - 1)),
706         Int32(0));
707 }
708 
GetElementsKindByHClass(GateRef hClass)709 GateRef CircuitBuilder::GetElementsKindByHClass(GateRef hClass)
710 {
711     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
712     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
713     return Int32And(Int32LSR(bitfield,
714         Int32(JSHClass::ElementsKindBits::START_BIT)),
715         Int32((1LLU << JSHClass::ElementsKindBits::SIZE) - 1));
716 }
717 
IsDictionaryElement(GateRef hClass)718 GateRef CircuitBuilder::IsDictionaryElement(GateRef hClass)
719 {
720     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
721     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
722     return NotEqual(Int32And(Int32LSR(bitfield,
723         Int32(JSHClass::DictionaryElementBits::START_BIT)),
724         Int32((1LU << JSHClass::DictionaryElementBits::SIZE) - 1)),
725         Int32(0));
726 }
727 
IsStableElements(GateRef hClass)728 GateRef CircuitBuilder::IsStableElements(GateRef hClass)
729 {
730     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
731     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
732     return NotEqual(Int32And(Int32LSR(bitfield,
733         Int32(JSHClass::IsStableElementsBit::START_BIT)),
734         Int32((1LU << JSHClass::IsStableElementsBit::SIZE) - 1)),
735         Int32(0));
736 }
737 
IsStableArguments(GateRef hClass)738 GateRef CircuitBuilder::IsStableArguments(GateRef hClass)
739 {
740     GateRef objectType = GetObjectType(hClass);
741     GateRef isJsArguments = Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_ARGUMENTS)));
742     GateRef isStableElements = IsStableElements(hClass);
743     return BoolAnd(isStableElements, isJsArguments);
744 }
745 
IsStableArray(GateRef hClass)746 GateRef CircuitBuilder::IsStableArray(GateRef hClass)
747 {
748     GateRef objectType = GetObjectType(hClass);
749     GateRef isJsArray = Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_ARRAY)));
750     GateRef isStableElements = IsStableElements(hClass);
751     return BoolAnd(isStableElements, isJsArray);
752 }
753 
IsClassConstructor(GateRef object)754 GateRef CircuitBuilder::IsClassConstructor(GateRef object)
755 {
756     GateRef hClass = LoadHClass(object);
757     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
758     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
759     return NotEqual(Int32And(Int32LSR(bitfield,
760         Int32(JSHClass::ClassConstructorBit::START_BIT)),
761         Int32((1LU << JSHClass::ClassConstructorBit::SIZE) - 1)),
762         Int32(0));
763 }
764 
IsClassConstructorWithBitField(GateRef bitfield)765 GateRef CircuitBuilder::IsClassConstructorWithBitField(GateRef bitfield)
766 {
767     return NotEqual(Int32And(bitfield, Int32(1LU << JSHClass::ClassConstructorBit::START_BIT)), Int32(0));
768 }
769 
IsConstructor(GateRef object)770 GateRef CircuitBuilder::IsConstructor(GateRef object)
771 {
772     GateRef hClass = LoadHClass(object);
773     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
774     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
775     // decode
776     return Int32NotEqual(
777         Int32And(Int32LSR(bitfield, Int32(JSHClass::ConstructorBit::START_BIT)),
778                  Int32((1LU << JSHClass::ConstructorBit::SIZE) - 1)),
779         Int32(0));
780 }
781 
IsClassPrototype(GateRef object)782 GateRef CircuitBuilder::IsClassPrototype(GateRef object)
783 {
784     GateRef hClass = LoadHClass(object);
785     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
786     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
787     // decode
788     return NotEqual(
789         Int32And(Int32LSR(bitfield, Int32(JSHClass::ClassPrototypeBit::START_BIT)),
790         Int32((1LU << JSHClass::ClassPrototypeBit::SIZE) - 1)),
791         Int32(0));
792 }
793 
IsExtensible(GateRef object)794 GateRef CircuitBuilder::IsExtensible(GateRef object)
795 {
796     GateRef hClass = LoadHClass(object);
797     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
798     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
799     return NotEqual(Int32And(Int32LSR(bitfield,
800         Int32(JSHClass::ExtensibleBit::START_BIT)),
801         Int32((1LU << JSHClass::ExtensibleBit::SIZE) - 1)),
802         Int32(0));
803 }
804 
GetExpectedNumOfArgs(GateRef method)805 GateRef CircuitBuilder::GetExpectedNumOfArgs(GateRef method)
806 {
807     GateRef callFieldOffset = IntPtr(Method::CALL_FIELD_OFFSET);
808     GateRef callfield = Load(VariableType::INT64(), method, callFieldOffset);
809     return Int64And(
810         Int64LSR(callfield, Int64(MethodLiteral::NumArgsBits::START_BIT)),
811         Int64((1LU << MethodLiteral::NumArgsBits::SIZE) - 1));
812 }
813 
TaggedObjectIsEcmaObject(GateRef obj)814 GateRef CircuitBuilder::TaggedObjectIsEcmaObject(GateRef obj)
815 {
816     GateRef objectType = GetObjectType(LoadHClass(obj));
817     return BoolAnd(
818         Int32LessThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::ECMA_OBJECT_LAST))),
819         Int32GreaterThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::ECMA_OBJECT_FIRST))));
820 }
821 
IsJSObject(GateRef obj)822 GateRef CircuitBuilder::IsJSObject(GateRef obj)
823 {
824     GateRef objectType = GetObjectType(LoadHClass(obj));
825     auto ret = BoolAnd(
826         Int32LessThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT_LAST))),
827         Int32GreaterThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT_FIRST))));
828     return LogicAnd(TaggedIsHeapObject(obj), ret);
829 }
830 
TaggedObjectIsString(GateRef obj)831 GateRef CircuitBuilder::TaggedObjectIsString(GateRef obj)
832 {
833     GateRef objectType = GetObjectType(LoadHClass(obj));
834     return BoolAnd(
835         Int32LessThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::STRING_LAST))),
836         Int32GreaterThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::STRING_FIRST))));
837 }
838 
TaggedObjectBothAreString(GateRef x,GateRef y)839 GateRef CircuitBuilder::TaggedObjectBothAreString(GateRef x, GateRef y)
840 {
841     return BoolAnd(TaggedObjectIsString(x), TaggedObjectIsString(y));
842 }
843 
IsCallableFromBitField(GateRef bitfield)844 GateRef CircuitBuilder::IsCallableFromBitField(GateRef bitfield)
845 {
846     return NotEqual(
847         Int32And(Int32LSR(bitfield, Int32(JSHClass::CallableBit::START_BIT)),
848             Int32((1LU << JSHClass::CallableBit::SIZE) - 1)),
849         Int32(0));
850 }
851 
IsCallable(GateRef obj)852 GateRef CircuitBuilder::IsCallable(GateRef obj)
853 {
854     GateRef hClass = LoadHClass(obj);
855     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
856     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
857     return IsCallableFromBitField(bitfield);
858 }
859 
BothAreString(GateRef x,GateRef y)860 GateRef CircuitBuilder::BothAreString(GateRef x, GateRef y)
861 {
862     Label subentry(env_);
863     SubCfgEntry(&subentry);
864     Label bothAreHeapObjet(env_);
865     Label bothAreStringType(env_);
866     Label exit(env_);
867     DEFVAlUE(result, env_, VariableType::BOOL(), False());
868     Branch(BoolAnd(TaggedIsHeapObject(x), TaggedIsHeapObject(y)), &bothAreHeapObjet, &exit);
869     Bind(&bothAreHeapObjet);
870     {
871         Branch(TaggedObjectBothAreString(x, y), &bothAreStringType, &exit);
872         Bind(&bothAreStringType);
873         {
874             result = True();
875             Jump(&exit);
876         }
877     }
878     Bind(&exit);
879     auto ret = *result;
880     SubCfgExit();
881     return ret;
882 }
883 
GetObjectSizeFromHClass(GateRef hClass)884 GateRef CircuitBuilder::GetObjectSizeFromHClass(GateRef hClass)
885 {
886     // NOTE: check for special case of string and TAGGED_ARRAY
887     GateRef bitfield = Load(VariableType::INT32(), hClass, IntPtr(JSHClass::BIT_FIELD1_OFFSET));
888     GateRef objectSizeInWords = Int32And(Int32LSR(bitfield,
889         Int32(JSHClass::ObjectSizeInWordsBits::START_BIT)),
890         Int32((1LU << JSHClass::ObjectSizeInWordsBits::SIZE) - 1));
891     return PtrMul(ZExtInt32ToPtr(objectSizeInWords), IntPtr(JSTaggedValue::TaggedTypeSize()));
892 }
893 
894 template<TypedBinOp Op>
TypedBinaryOp(GateRef x,GateRef y,GateType xType,GateType yType,GateType gateType,PGOSampleType sampleType)895 GateRef CircuitBuilder::TypedBinaryOp(GateRef x, GateRef y, GateType xType, GateType yType, GateType gateType,
896     PGOSampleType sampleType)
897 {
898     auto currentLabel = env_->GetCurrentLabel();
899     auto currentControl = currentLabel->GetControl();
900     auto currentDepend = currentLabel->GetDepend();
901     uint64_t operandTypes = GatePairTypeAccessor::ToValue(xType, yType);
902     auto numberBinaryOp = GetCircuit()->NewGate(circuit_->TypedBinaryOp(operandTypes, Op, sampleType),
903         MachineType::I64, {currentControl, currentDepend, x, y}, gateType);
904     currentLabel->SetControl(numberBinaryOp);
905     currentLabel->SetDepend(numberBinaryOp);
906     return numberBinaryOp;
907 }
908 
909 template<TypedCallTargetCheckOp Op>
JSNoGCCallThisTargetTypeCheck(GateType type,GateRef func,GateRef methodId,GateRef gate)910 GateRef CircuitBuilder::JSNoGCCallThisTargetTypeCheck(GateType type, GateRef func, GateRef methodId, GateRef gate)
911 {
912     auto currentLabel = env_->GetCurrentLabel();
913     auto currentControl = currentLabel->GetControl();
914     auto currentDepend = currentLabel->GetDepend();
915     auto frameState = acc_.GetFrameState(gate);
916     GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(CircuitBuilder::GATE_TWO_VALUESIN,
917         static_cast<size_t>(type.Value()), Op), MachineType::I1,
918         {currentControl, currentDepend, func, methodId, frameState}, GateType::NJSValue());
919     currentLabel->SetControl(ret);
920     currentLabel->SetDepend(ret);
921     return ret;
922 }
923 
924 template<TypedCallTargetCheckOp Op>
JSCallTargetTypeCheck(GateType type,GateRef func,GateRef methodIndex,GateRef gate)925 GateRef CircuitBuilder::JSCallTargetTypeCheck(GateType type, GateRef func, GateRef methodIndex, GateRef gate)
926 {
927     auto currentLabel = env_->GetCurrentLabel();
928     auto currentControl = currentLabel->GetControl();
929     auto currentDepend = currentLabel->GetDepend();
930     auto frameState = acc_.GetFrameState(gate);
931     GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(CircuitBuilder::GATE_TWO_VALUESIN,
932         static_cast<size_t>(type.Value()), Op), MachineType::I1,
933         {currentControl, currentDepend, func, methodIndex, frameState}, GateType::NJSValue());
934     currentLabel->SetControl(ret);
935     currentLabel->SetDepend(ret);
936     return ret;
937 }
938 
939 template<TypedCallTargetCheckOp Op>
JSCallThisTargetTypeCheck(GateType type,GateRef func,GateRef gate)940 GateRef CircuitBuilder::JSCallThisTargetTypeCheck(GateType type, GateRef func, GateRef gate)
941 {
942     auto currentLabel = env_->GetCurrentLabel();
943     auto currentControl = currentLabel->GetControl();
944     auto currentDepend = currentLabel->GetDepend();
945     auto frameState = acc_.GetFrameState(gate);
946     GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(1, static_cast<size_t>(type.Value()), Op),
947         MachineType::I1, {currentControl, currentDepend, func, frameState}, GateType::NJSValue());
948     currentLabel->SetControl(ret);
949     currentLabel->SetDepend(ret);
950     return ret;
951 }
952 
953 template<TypedUnOp Op>
TypedUnaryOp(GateRef x,GateType xType,GateType gateType)954 GateRef CircuitBuilder::TypedUnaryOp(GateRef x, GateType xType, GateType gateType)
955 {
956     auto currentLabel = env_->GetCurrentLabel();
957     auto currentControl = currentLabel->GetControl();
958     auto currentDepend = currentLabel->GetDepend();
959     uint64_t value = TypedUnaryAccessor::ToValue(xType, Op);
960     auto numberUnaryOp = GetCircuit()->NewGate(circuit_->TypedUnaryOp(value),
961         MachineType::I64, {currentControl, currentDepend, x}, gateType);
962     currentLabel->SetControl(numberUnaryOp);
963     currentLabel->SetDepend(numberUnaryOp);
964     return numberUnaryOp;
965 }
966 
967 template<TypedJumpOp Op>
TypedConditionJump(GateRef x,GateType xType)968 GateRef CircuitBuilder::TypedConditionJump(GateRef x, GateType xType)
969 {
970     auto currentLabel = env_->GetCurrentLabel();
971     auto currentControl = currentLabel->GetControl();
972     auto currentDepend = currentLabel->GetDepend();
973     auto machineType = MachineType::NOVALUE;
974     auto jumpOp = TypedConditionJump(machineType, Op, xType, {currentControl, currentDepend, x});
975     currentLabel->SetControl(jumpOp);
976     currentLabel->SetDepend(jumpOp);
977     return jumpOp;
978 }
979 
980 template <TypedLoadOp Op>
LoadElement(GateRef receiver,GateRef index)981 GateRef CircuitBuilder::LoadElement(GateRef receiver, GateRef index)
982 {
983     auto opIdx = static_cast<uint64_t>(Op);
984     auto currentLabel = env_->GetCurrentLabel();
985     auto currentControl = currentLabel->GetControl();
986     auto currentDepend = currentLabel->GetDepend();
987     auto ret = GetCircuit()->NewGate(GetCircuit()->LoadElement(opIdx), MachineType::I64,
988                                      {currentControl, currentDepend, receiver, index}, GateType::AnyType());
989     currentLabel->SetControl(ret);
990     currentLabel->SetDepend(ret);
991     return ret;
992 }
993 
994 template <TypedStoreOp Op>
StoreElement(GateRef receiver,GateRef index,GateRef value)995 GateRef CircuitBuilder::StoreElement(GateRef receiver, GateRef index, GateRef value)
996 {
997     auto opIdx = static_cast<uint64_t>(Op);
998     auto currentLabel = env_->GetCurrentLabel();
999     auto currentControl = currentLabel->GetControl();
1000     auto currentDepend = currentLabel->GetDepend();
1001     auto ret =
1002         GetCircuit()->NewGate(GetCircuit()->StoreElement(opIdx), MachineType::NOVALUE,
1003                               {currentControl, currentDepend, receiver, index, value}, GateType::AnyType());
1004     currentLabel->SetControl(ret);
1005     currentLabel->SetDepend(ret);
1006     return ret;
1007 }
1008 
PrimitiveToNumber(GateRef x,VariableType type)1009 GateRef CircuitBuilder::PrimitiveToNumber(GateRef x, VariableType type)
1010 {
1011     auto currentLabel = env_->GetCurrentLabel();
1012     auto currentControl = currentLabel->GetControl();
1013     auto currentDepend = currentLabel->GetDepend();
1014     auto numberconvert = TypeConvert(MachineType::I64, type.GetGateType(), GateType::NumberType(),
1015                                      {currentControl, currentDepend, x});
1016     currentLabel->SetControl(numberconvert);
1017     currentLabel->SetDepend(numberconvert);
1018     return numberconvert;
1019 }
1020 
LogicAnd(GateRef x,GateRef y)1021 GateRef CircuitBuilder::LogicAnd(GateRef x, GateRef y)
1022 {
1023     Label subentry(env_);
1024     SubCfgEntry(&subentry);
1025     Label exit(env_);
1026     Label isX(env_);
1027     Label notX(env_);
1028     DEFVAlUE(result, env_, VariableType::BOOL(), x);
1029     Branch(x, &isX, &notX);
1030     Bind(&isX);
1031     {
1032         result = y;
1033         Jump(&exit);
1034     }
1035     Bind(&notX);
1036     {
1037         Jump(&exit);
1038     }
1039     Bind(&exit);
1040     auto ret = *result;
1041     SubCfgExit();
1042     return ret;
1043 }
1044 
LogicOr(GateRef x,GateRef y)1045 GateRef CircuitBuilder::LogicOr(GateRef x, GateRef y)
1046 {
1047     Label subentry(env_);
1048     SubCfgEntry(&subentry);
1049     Label exit(env_);
1050     Label isX(env_);
1051     Label notX(env_);
1052     DEFVAlUE(result, env_, VariableType::BOOL(), x);
1053     Branch(x, &isX, &notX);
1054     Bind(&isX);
1055     {
1056         Jump(&exit);
1057     }
1058     Bind(&notX);
1059     {
1060         result = y;
1061         Jump(&exit);
1062     }
1063     Bind(&exit);
1064     auto ret = *result;
1065     SubCfgExit();
1066     return ret;
1067 }
1068 
LoadFromTaggedArray(GateRef array,size_t index)1069 GateRef CircuitBuilder::LoadFromTaggedArray(GateRef array, size_t index)
1070 {
1071     auto dataOffset = TaggedArray::DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize();
1072     return LoadConstOffset(VariableType::JS_ANY(), array, dataOffset);
1073 }
1074 
StoreToTaggedArray(GateRef array,size_t index,GateRef value)1075 GateRef CircuitBuilder::StoreToTaggedArray(GateRef array, size_t index, GateRef value)
1076 {
1077     auto dataOffset = TaggedArray::DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize();
1078     return StoreConstOffset(VariableType::JS_ANY(), array, dataOffset, value);
1079 }
1080 
NextVariableId()1081 int CircuitBuilder::NextVariableId()
1082 {
1083     return env_->NextVariableId();
1084 }
1085 
HandleException(GateRef result,Label * success,Label * fail,Label * exit)1086 void CircuitBuilder::HandleException(GateRef result, Label *success, Label *fail, Label *exit)
1087 {
1088     Branch(Equal(result, ExceptionConstant()), fail, success);
1089     Bind(fail);
1090     {
1091         Jump(exit);
1092     }
1093 }
1094 
HandleException(GateRef result,Label * success,Label * fail,Label * exit,GateRef exceptionVal)1095 void CircuitBuilder::HandleException(GateRef result, Label *success, Label *fail, Label *exit, GateRef exceptionVal)
1096 {
1097     Branch(Equal(result, exceptionVal), fail, success);
1098     Bind(fail);
1099     {
1100         Jump(exit);
1101     }
1102 }
1103 
SubCfgEntry(Label * entry)1104 void CircuitBuilder::SubCfgEntry(Label *entry)
1105 {
1106     ASSERT(env_ != nullptr);
1107     env_->SubCfgEntry(entry);
1108 }
1109 
SubCfgExit()1110 void CircuitBuilder::SubCfgExit()
1111 {
1112     ASSERT(env_ != nullptr);
1113     env_->SubCfgExit();
1114 }
1115 
Return(GateRef value)1116 GateRef CircuitBuilder::Return(GateRef value)
1117 {
1118     auto control = GetCurrentLabel()->GetControl();
1119     auto depend = GetCurrentLabel()->GetDepend();
1120     return Return(control, depend, value);
1121 }
1122 
Return()1123 GateRef CircuitBuilder::Return()
1124 {
1125     auto control = GetCurrentLabel()->GetControl();
1126     auto depend = GetCurrentLabel()->GetDepend();
1127     return ReturnVoid(control, depend);
1128 }
1129 
Bind(Label * label)1130 void CircuitBuilder::Bind(Label *label)
1131 {
1132     label->Bind();
1133     env_->SetCurrentLabel(label);
1134 }
1135 
Bind(Label * label,bool justSlowPath)1136 void CircuitBuilder::Bind(Label *label, bool justSlowPath)
1137 {
1138     if (!justSlowPath) {
1139         label->Bind();
1140         env_->SetCurrentLabel(label);
1141     }
1142 }
1143 
GetCurrentLabel()1144 Label *CircuitBuilder::GetCurrentLabel() const
1145 {
1146     return GetCurrentEnvironment()->GetCurrentLabel();
1147 }
1148 
GetState()1149 GateRef CircuitBuilder::GetState() const
1150 {
1151     return GetCurrentLabel()->GetControl();
1152 }
1153 
GetDepend()1154 GateRef CircuitBuilder::GetDepend() const
1155 {
1156     return GetCurrentLabel()->GetDepend();
1157 }
1158 
GetStateDepend()1159 StateDepend CircuitBuilder::GetStateDepend() const
1160 {
1161     return StateDepend(GetState(), GetDepend());
1162 }
1163 
SetDepend(GateRef depend)1164 void CircuitBuilder::SetDepend(GateRef depend)
1165 {
1166     GetCurrentLabel()->SetDepend(depend);
1167 }
1168 
SetState(GateRef state)1169 void CircuitBuilder::SetState(GateRef state)
1170 {
1171     GetCurrentLabel()->SetControl(state);
1172 }
1173 
1174 // ctor is base but not builtin
IsBase(GateRef ctor)1175 inline GateRef CircuitBuilder::IsBase(GateRef ctor)
1176 {
1177     GateRef method = GetMethodFromFunction(ctor);
1178     GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
1179     GateRef bitfield = Load(VariableType::INT32(), method, extraLiteralInfoOffset);
1180 
1181     GateRef kind = Int32And(Int32LSR(bitfield, Int32(MethodLiteral::FunctionKindBits::START_BIT)),
1182                             Int32((1LU << MethodLiteral::FunctionKindBits::SIZE) - 1));
1183     return Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(FunctionKind::CLASS_CONSTRUCTOR)));
1184 }
1185 
TypedCallBuiltin(GateRef hirGate,GateRef x,BuiltinsStubCSigns::ID id)1186 inline GateRef CircuitBuilder::TypedCallBuiltin(GateRef hirGate, GateRef x, BuiltinsStubCSigns::ID id)
1187 {
1188     auto currentLabel = env_->GetCurrentLabel();
1189     auto currentControl = currentLabel->GetControl();
1190     auto currentDepend = currentLabel->GetDepend();
1191     GateRef idGate = Int8(static_cast<int8_t>(id));
1192     auto numberMathOp = TypedCallOperator(hirGate, MachineType::I64, {currentControl, currentDepend, x, idGate});
1193     currentLabel->SetControl(numberMathOp);
1194     currentLabel->SetDepend(numberMathOp);
1195     return numberMathOp;
1196 }
1197 
TypedCallThis3Builtin(GateRef hirGate,GateRef thisObj,GateRef a0,GateRef a1,GateRef a2,BuiltinsStubCSigns::ID id)1198 inline GateRef CircuitBuilder::TypedCallThis3Builtin(GateRef hirGate, GateRef thisObj, GateRef a0, GateRef a1,
1199                                                      GateRef a2, BuiltinsStubCSigns::ID id)
1200 {
1201     auto currentLabel = env_->GetCurrentLabel();
1202     auto currentControl = currentLabel->GetControl();
1203     auto currentDepend = currentLabel->GetDepend();
1204     GateRef idGate = Int8(static_cast<int8_t>(id));
1205     auto numberMathOp = TypedCallOperator(hirGate, MachineType::I64,
1206         {currentControl, currentDepend, thisObj, a0, a1, a2, idGate});
1207     currentLabel->SetControl(numberMathOp);
1208     currentLabel->SetDepend(numberMathOp);
1209     return numberMathOp;
1210 }
1211 
GetMethodId(GateRef func)1212 inline GateRef CircuitBuilder::GetMethodId(GateRef func)
1213 {
1214     GateRef method = GetMethodFromFunction(func);
1215     GateRef literalInfoOffset = IntPtr(Method::LITERAL_INFO_OFFSET);
1216     GateRef LiteralInfo = Load(VariableType::INT64(), method, literalInfoOffset);
1217     GateRef methodId = Int64And(Int64LSR(LiteralInfo, Int64(MethodLiteral::MethodIdBits::START_BIT)),
1218         Int64((1LLU << MethodLiteral::MethodIdBits::SIZE) - 1));
1219     return methodId;
1220 }
1221 
Seal()1222 void Label::Seal()
1223 {
1224     return impl_->Seal();
1225 }
1226 
Bind()1227 void Label::Bind()
1228 {
1229     impl_->Bind();
1230 }
1231 
MergeAllControl()1232 void Label::MergeAllControl()
1233 {
1234     impl_->MergeAllControl();
1235 }
1236 
MergeAllDepend()1237 void Label::MergeAllDepend()
1238 {
1239     impl_->MergeAllDepend();
1240 }
1241 
AppendPredecessor(const Label * predecessor)1242 void Label::AppendPredecessor(const Label *predecessor)
1243 {
1244     impl_->AppendPredecessor(predecessor->GetRawLabel());
1245 }
1246 
GetPredecessors()1247 std::vector<Label> Label::GetPredecessors() const
1248 {
1249     std::vector<Label> labels;
1250     for (auto rawlabel : impl_->GetPredecessors()) {
1251         labels.emplace_back(Label(rawlabel));
1252     }
1253     return labels;
1254 }
1255 
SetControl(GateRef control)1256 void Label::SetControl(GateRef control)
1257 {
1258     impl_->SetControl(control);
1259 }
1260 
SetPreControl(GateRef control)1261 void Label::SetPreControl(GateRef control)
1262 {
1263     impl_->SetPreControl(control);
1264 }
1265 
MergeControl(GateRef control)1266 void Label::MergeControl(GateRef control)
1267 {
1268     impl_->MergeControl(control);
1269 }
1270 
GetControl()1271 GateRef Label::GetControl() const
1272 {
1273     return impl_->GetControl();
1274 }
1275 
GetDepend()1276 GateRef Label::GetDepend() const
1277 {
1278     return impl_->GetDepend();
1279 }
1280 
SetDepend(GateRef depend)1281 void Label::SetDepend(GateRef depend)
1282 {
1283     return impl_->SetDepend(depend);
1284 }
1285 
GetLabelFromSelector(GateRef sel)1286 Label Environment::GetLabelFromSelector(GateRef sel)
1287 {
1288     Label::LabelImpl *rawlabel = phiToLabels_[sel];
1289     return Label(rawlabel);
1290 }
1291 
AddSelectorToLabel(GateRef sel,Label label)1292 void Environment::AddSelectorToLabel(GateRef sel, Label label)
1293 {
1294     phiToLabels_[sel] = label.GetRawLabel();
1295 }
1296 
NewLabel(Environment * env,GateRef control)1297 Label::LabelImpl *Environment::NewLabel(Environment *env, GateRef control)
1298 {
1299     auto impl = new Label::LabelImpl(env, control);
1300     rawLabels_.emplace_back(impl);
1301     return impl;
1302 }
1303 
SubCfgEntry(Label * entry)1304 void Environment::SubCfgEntry(Label *entry)
1305 {
1306     if (currentLabel_ != nullptr) {
1307         GateRef control = currentLabel_->GetControl();
1308         GateRef depend = currentLabel_->GetDepend();
1309         stack_.push(currentLabel_);
1310         currentLabel_ = entry;
1311         currentLabel_->SetControl(control);
1312         currentLabel_->SetDepend(depend);
1313     }
1314 }
1315 
SubCfgExit()1316 void Environment::SubCfgExit()
1317 {
1318     if (currentLabel_ != nullptr) {
1319         GateRef control = currentLabel_->GetControl();
1320         GateRef depend = currentLabel_->GetDepend();
1321         if (!stack_.empty()) {
1322             currentLabel_ = stack_.top();
1323             currentLabel_->SetControl(control);
1324             currentLabel_->SetDepend(depend);
1325             stack_.pop();
1326         }
1327     }
1328 }
1329 
GetInput(size_t index)1330 GateRef Environment::GetInput(size_t index) const
1331 {
1332     return inputList_.at(index);
1333 }
1334 } // namespace panda::ecmascript::kungfu
1335 
1336 #endif
1337