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, ¬X);
1030 Bind(&isX);
1031 {
1032 result = y;
1033 Jump(&exit);
1034 }
1035 Bind(¬X);
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, ¬X);
1054 Bind(&isX);
1055 {
1056 Jump(&exit);
1057 }
1058 Bind(¬X);
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