• 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 
Equal(GateRef x,GateRef y)39 GateRef CircuitBuilder::Equal(GateRef x, GateRef y)
40 {
41     auto xType = acc_.GetMachineType(x);
42     switch (xType) {
43         case ARCH:
44         case FLEX:
45         case I1:
46         case I8:
47         case I16:
48         case I32:
49         case I64:
50             return BinaryCmp(circuit_->Icmp(static_cast<uint64_t>(ICmpCondition::EQ)), x, y);
51         case F32:
52         case F64:
53             return BinaryCmp(circuit_->Fcmp(static_cast<uint64_t>(FCmpCondition::OEQ)), x, y);
54         default:
55             UNREACHABLE();
56     }
57 }
58 
NotEqual(GateRef x,GateRef y)59 GateRef CircuitBuilder::NotEqual(GateRef x, GateRef y)
60 {
61     auto xType = acc_.GetMachineType(x);
62     switch (xType) {
63         case ARCH:
64         case FLEX:
65         case I1:
66         case I8:
67         case I16:
68         case I32:
69         case I64:
70             return BinaryCmp(circuit_->Icmp(static_cast<uint64_t>(ICmpCondition::NE)), x, y);
71         case F32:
72         case F64:
73             return BinaryCmp(circuit_->Fcmp(static_cast<uint64_t>(FCmpCondition::ONE)), x, y);
74         default:
75             UNREACHABLE();
76     }
77 }
78 
79 // memory
Load(VariableType type,GateRef base,GateRef offset)80 GateRef CircuitBuilder::Load(VariableType type, GateRef base, GateRef offset)
81 {
82     auto label = GetCurrentLabel();
83     auto depend = label->GetDepend();
84     GateRef val = PtrAdd(base, offset);
85     GateRef result = GetCircuit()->NewGate(GetCircuit()->Load(), type.GetMachineType(),
86                                            { depend, val }, type.GetGateType());
87     label->SetDepend(result);
88     return result;
89 }
90 
91 // Js World
92 // cast operation
GetInt64OfTInt(GateRef x)93 GateRef CircuitBuilder::GetInt64OfTInt(GateRef x)
94 {
95     GateRef tagged = ChangeTaggedPointerToInt64(x);
96     return Int64And(tagged, Int64(~JSTaggedValue::TAG_MARK));
97 }
98 
GetInt32OfTInt(GateRef x)99 GateRef CircuitBuilder::GetInt32OfTInt(GateRef x)
100 {
101     return TruncInt64ToInt32(GetInt64OfTInt(x));
102 }
103 
TaggedCastToIntPtr(GateRef x)104 GateRef CircuitBuilder::TaggedCastToIntPtr(GateRef x)
105 {
106     ASSERT(cmpCfg_ != nullptr);
107     return cmpCfg_->Is32Bit() ? GetInt32OfTInt(x) : GetInt64OfTInt(x);
108 }
109 
GetDoubleOfTDouble(GateRef x)110 GateRef CircuitBuilder::GetDoubleOfTDouble(GateRef x)
111 {
112     GateRef tagged = ChangeTaggedPointerToInt64(x);
113     GateRef val = Int64Sub(tagged, Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET));
114     return CastInt64ToFloat64(val);
115 }
116 
GetDoubleOfTNumber(GateRef x)117 GateRef CircuitBuilder::GetDoubleOfTNumber(GateRef x)
118 {
119     Label subentry(env_);
120     SubCfgEntry(&subentry);
121     Label isInt(env_);
122     Label isDouble(env_);
123     Label exit(env_);
124     DEFVAlUE(result, env_, VariableType::FLOAT64(), Double(0));
125     Branch(TaggedIsInt(x), &isInt, &isDouble);
126     Bind(&isInt);
127     {
128         result = ChangeInt32ToFloat64(GetInt32OfTInt(x));
129         Jump(&exit);
130     }
131     Bind(&isDouble);
132     {
133         result = GetDoubleOfTDouble(x);
134         Jump(&exit);
135     }
136     Bind(&exit);
137     GateRef ret = *result;
138     SubCfgExit();
139     return ret;
140 }
141 
Int8Equal(GateRef x,GateRef y)142 GateRef CircuitBuilder::Int8Equal(GateRef x, GateRef y)
143 {
144     return Equal(x, y);
145 }
146 
Int32NotEqual(GateRef x,GateRef y)147 GateRef CircuitBuilder::Int32NotEqual(GateRef x, GateRef y)
148 {
149     return NotEqual(x, y);
150 }
151 
Int64NotEqual(GateRef x,GateRef y)152 GateRef CircuitBuilder::Int64NotEqual(GateRef x, GateRef y)
153 {
154     return NotEqual(x, y);
155 }
156 
DoubleEqual(GateRef x,GateRef y)157 GateRef CircuitBuilder::DoubleEqual(GateRef x, GateRef y)
158 {
159     return Equal(x, y);
160 }
161 
DoubleNotEqual(GateRef x,GateRef y)162 GateRef CircuitBuilder::DoubleNotEqual(GateRef x, GateRef y)
163 {
164     return NotEqual(x, y);
165 }
166 
Int64Equal(GateRef x,GateRef y)167 GateRef CircuitBuilder::Int64Equal(GateRef x, GateRef y)
168 {
169     return Equal(x, y);
170 }
171 
Int32Equal(GateRef x,GateRef y)172 GateRef CircuitBuilder::Int32Equal(GateRef x, GateRef y)
173 {
174     return Equal(x, y);
175 }
176 
IntPtrGreaterThan(GateRef x,GateRef y)177 GateRef CircuitBuilder::IntPtrGreaterThan(GateRef x, GateRef y)
178 {
179     return env_->Is32Bit() ? Int32GreaterThan(x, y) : Int64GreaterThan(x, y);
180 }
181 
182 template<OpCode Op, MachineType Type>
BinaryOp(GateRef x,GateRef y)183 GateRef CircuitBuilder::BinaryOp(GateRef x, GateRef y)
184 {
185     if (Op == OpCode::ADD) {
186         return BinaryArithmetic(circuit_->Add(), Type, x, y);
187     } else if (Op == OpCode::SUB) {
188         return BinaryArithmetic(circuit_->Sub(), Type, x, y);
189     } else if (Op == OpCode::MUL) {
190         return BinaryArithmetic(circuit_->Mul(), Type, x, y);
191     }
192     UNREACHABLE();
193     return Circuit::NullGate();
194 }
195 
IntPtrLSR(GateRef x,GateRef y)196 GateRef CircuitBuilder::IntPtrLSR(GateRef x, GateRef y)
197 {
198     auto ptrSize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64;
199     return BinaryArithmetic(circuit_->Lsr(), ptrSize, x, y);
200 }
201 
IntPtrLSL(GateRef x,GateRef y)202 GateRef CircuitBuilder::IntPtrLSL(GateRef x, GateRef y)
203 {
204     auto ptrSize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64;
205     return BinaryArithmetic(circuit_->Lsl(), ptrSize, x, y);
206 }
207 
IntPtrOr(GateRef x,GateRef y)208 GateRef CircuitBuilder::IntPtrOr(GateRef x, GateRef y)
209 {
210     auto ptrsize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64;
211     return BinaryArithmetic(circuit_->Or(), ptrsize, x, y);
212 }
213 
IntPtrDiv(GateRef x,GateRef y)214 GateRef CircuitBuilder::IntPtrDiv(GateRef x, GateRef y)
215 {
216     return env_->Is32Bit() ? Int32Div(x, y) : Int64Div(x, y);
217 }
218 
Int64ToTaggedPtr(GateRef x)219 GateRef CircuitBuilder::Int64ToTaggedPtr(GateRef x)
220 {
221     return GetCircuit()->NewGate(circuit_->Int64ToTagged(),
222         MachineType::I64, { x }, GateType::TaggedValue());
223 }
224 
Int32ToTaggedPtr(GateRef x)225 GateRef CircuitBuilder::Int32ToTaggedPtr(GateRef x)
226 {
227     GateRef val = SExtInt32ToInt64(x);
228     return Int64ToTaggedPtr(Int64Or(val, Int64(JSTaggedValue::TAG_INT)));
229 }
230 
Int32ToTaggedInt(GateRef x)231 GateRef CircuitBuilder::Int32ToTaggedInt(GateRef x)
232 {
233     GateRef val = SExtInt32ToInt64(x);
234     return Int64Or(val, Int64(JSTaggedValue::TAG_INT));
235 }
236 
237 // bit operation
IsSpecial(GateRef x,JSTaggedType type)238 GateRef CircuitBuilder::IsSpecial(GateRef x, JSTaggedType type)
239 {
240     auto specialValue = circuit_->GetConstantGate(
241         MachineType::I64, type, GateType::TaggedValue());
242 
243     return Equal(x, specialValue);
244 }
245 
TaggedIsInt(GateRef x)246 GateRef CircuitBuilder::TaggedIsInt(GateRef x)
247 {
248     x = ChangeTaggedPointerToInt64(x);
249     return Equal(Int64And(x, Int64(JSTaggedValue::TAG_MARK)),
250                  Int64(JSTaggedValue::TAG_INT));
251 }
252 
TaggedIsDouble(GateRef x)253 GateRef CircuitBuilder::TaggedIsDouble(GateRef x)
254 {
255     return BoolAnd(TaggedIsNumber(x), BoolNot(TaggedIsInt(x)));
256 }
257 
TaggedIsObject(GateRef x)258 GateRef CircuitBuilder::TaggedIsObject(GateRef x)
259 {
260     x = ChangeTaggedPointerToInt64(x);
261     return Equal(Int64And(x, Int64(JSTaggedValue::TAG_MARK)),
262                  Int64(JSTaggedValue::TAG_OBJECT));
263 }
264 
TaggedIsNumber(GateRef x)265 GateRef CircuitBuilder::TaggedIsNumber(GateRef x)
266 {
267     return BoolNot(TaggedIsObject(x));
268 }
269 
TaggedIsNumeric(GateRef x)270 GateRef CircuitBuilder::TaggedIsNumeric(GateRef x)
271 {
272     return BoolOr(TaggedIsNumber(x), TaggedIsBigInt(x));
273 }
274 
DoubleIsINF(GateRef x)275 GateRef CircuitBuilder::DoubleIsINF(GateRef x)
276 {
277     GateRef infinity = Double(base::POSITIVE_INFINITY);
278     GateRef negativeInfinity = Double(-base::POSITIVE_INFINITY);
279     GateRef diff1 = DoubleEqual(x, infinity);
280     GateRef diff2 = DoubleEqual(x, negativeInfinity);
281     return BoolOr(diff1, diff2);
282 }
283 
TaggedIsHole(GateRef x)284 GateRef CircuitBuilder::TaggedIsHole(GateRef x)
285 {
286     return Equal(x, HoleConstant());
287 }
288 
TaggedIsNotHole(GateRef x)289 GateRef CircuitBuilder::TaggedIsNotHole(GateRef x)
290 {
291     return NotEqual(x, HoleConstant());
292 }
293 
TaggedIsUndefined(GateRef x)294 GateRef CircuitBuilder::TaggedIsUndefined(GateRef x)
295 {
296     return Equal(x, UndefineConstant());
297 }
298 
TaggedIsException(GateRef x)299 GateRef CircuitBuilder::TaggedIsException(GateRef x)
300 {
301     return Equal(x, ExceptionConstant());
302 }
303 
TaggedIsSpecial(GateRef x)304 GateRef CircuitBuilder::TaggedIsSpecial(GateRef x)
305 {
306     return BoolOr(
307         Equal(Int64And(ChangeTaggedPointerToInt64(x), Int64(JSTaggedValue::TAG_SPECIAL_MASK)),
308             Int64(JSTaggedValue::TAG_SPECIAL)),
309         TaggedIsHole(x));
310 }
311 
IsJSHClass(GateRef obj)312 inline GateRef CircuitBuilder::IsJSHClass(GateRef obj)
313 {
314     return Int32Equal(GetObjectType(LoadHClass(obj)), Int32(static_cast<int32_t>(JSType::HCLASS)));
315 }
316 
TaggedIsHeapObject(GateRef x)317 GateRef CircuitBuilder::TaggedIsHeapObject(GateRef x)
318 {
319     x = ChangeTaggedPointerToInt64(x);
320     return Equal(Int64And(x, Int64(JSTaggedValue::TAG_HEAPOBJECT_MASK)), Int64(0));
321 }
322 
TaggedIsAsyncGeneratorObject(GateRef x)323 GateRef CircuitBuilder::TaggedIsAsyncGeneratorObject(GateRef x)
324 {
325     GateRef isHeapObj = TaggedIsHeapObject(x);
326     GateRef objType = GetObjectType(LoadHClass(x));
327     GateRef isAsyncGeneratorObj = Equal(objType,
328         Int32(static_cast<int32_t>(JSType::JS_ASYNC_GENERATOR_OBJECT)));
329     return LogicAnd(isHeapObj, isAsyncGeneratorObj);
330 }
331 
TaggedIsGeneratorObject(GateRef x)332 GateRef CircuitBuilder::TaggedIsGeneratorObject(GateRef x)
333 {
334     GateRef isHeapObj = TaggedIsHeapObject(x);
335     GateRef objType = GetObjectType(LoadHClass(x));
336     GateRef isAsyncGeneratorObj = Equal(objType,
337         Int32(static_cast<int32_t>(JSType::JS_GENERATOR_OBJECT)));
338     return LogicAnd(isHeapObj, isAsyncGeneratorObj);
339 }
340 
TaggedIsPropertyBox(GateRef x)341 GateRef CircuitBuilder::TaggedIsPropertyBox(GateRef x)
342 {
343     return LogicAnd(TaggedIsHeapObject(x),
344         IsJsType(x, JSType::PROPERTY_BOX));
345 }
346 
TaggedIsWeak(GateRef x)347 GateRef CircuitBuilder::TaggedIsWeak(GateRef x)
348 {
349     return LogicAnd(TaggedIsHeapObject(x),
350         Equal(Int64And(ChangeTaggedPointerToInt64(x), Int64(JSTaggedValue::TAG_WEAK)), Int64(1)));
351 }
352 
TaggedIsPrototypeHandler(GateRef x)353 GateRef CircuitBuilder::TaggedIsPrototypeHandler(GateRef x)
354 {
355     return LogicAnd(TaggedIsHeapObject(x),
356         IsJsType(x, JSType::PROTOTYPE_HANDLER));
357 }
358 
TaggedIsTransitionHandler(GateRef x)359 GateRef CircuitBuilder::TaggedIsTransitionHandler(GateRef x)
360 {
361     return LogicAnd(TaggedIsHeapObject(x),
362         IsJsType(x, JSType::TRANSITION_HANDLER));
363 }
364 
TaggedIsStoreTSHandler(GateRef x)365 GateRef CircuitBuilder::TaggedIsStoreTSHandler(GateRef x)
366 {
367     return LogicAnd(TaggedIsHeapObject(x),
368         IsJsType(x, JSType::STORE_TS_HANDLER));
369 }
370 
TaggedIsTransWithProtoHandler(GateRef x)371 GateRef CircuitBuilder::TaggedIsTransWithProtoHandler(GateRef x)
372 {
373     return LogicAnd(TaggedIsHeapObject(x),
374         IsJsType(x, JSType::TRANS_WITH_PROTO_HANDLER));
375 }
376 
TaggedIsUndefinedOrNull(GateRef x)377 GateRef CircuitBuilder::TaggedIsUndefinedOrNull(GateRef x)
378 {
379     return BoolOr(TaggedIsUndefined(x), TaggedIsNull(x));
380 }
381 
TaggedIsTrue(GateRef x)382 GateRef CircuitBuilder::TaggedIsTrue(GateRef x)
383 {
384     return Equal(x, TaggedTrue());
385 }
386 
TaggedIsFalse(GateRef x)387 GateRef CircuitBuilder::TaggedIsFalse(GateRef x)
388 {
389     return Equal(x, TaggedFalse());
390 }
391 
TaggedIsNull(GateRef x)392 GateRef CircuitBuilder::TaggedIsNull(GateRef x)
393 {
394     return Equal(x, NullConstant());
395 }
396 
TaggedIsBoolean(GateRef x)397 GateRef CircuitBuilder::TaggedIsBoolean(GateRef x)
398 {
399     return BoolOr(TaggedIsFalse(x), TaggedIsTrue(x));
400 }
401 
IsAOTLiteralInfo(GateRef x)402 GateRef CircuitBuilder::IsAOTLiteralInfo(GateRef x)
403 {
404     GateRef isHeapObj = TaggedIsHeapObject(x);
405     GateRef objType = GetObjectType(LoadHClass(x));
406     GateRef isAOTLiteralInfoObj = Equal(objType,
407         Int32(static_cast<int32_t>(JSType::AOT_LITERAL_INFO)));
408     return LogicAnd(isHeapObj, isAOTLiteralInfoObj);
409 }
410 
TaggedGetInt(GateRef x)411 GateRef CircuitBuilder::TaggedGetInt(GateRef x)
412 {
413     x = ChangeTaggedPointerToInt64(x);
414     return TruncInt64ToInt32(Int64And(x, Int64(~JSTaggedValue::TAG_MARK)));
415 }
416 
ToTaggedInt(GateRef x)417 GateRef CircuitBuilder::ToTaggedInt(GateRef x)
418 {
419     return Int64Or(x, Int64(JSTaggedValue::TAG_INT));
420 }
421 
ToTaggedIntPtr(GateRef x)422 GateRef CircuitBuilder::ToTaggedIntPtr(GateRef x)
423 {
424     return Int64ToTaggedPtr(Int64Or(x, Int64(JSTaggedValue::TAG_INT)));
425 }
426 
DoubleToTaggedDoublePtr(GateRef x)427 GateRef CircuitBuilder::DoubleToTaggedDoublePtr(GateRef x)
428 {
429     GateRef val = CastDoubleToInt64(x);
430     return Int64ToTaggedPtr(Int64Add(val, Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET)));
431 }
432 
BooleanToTaggedBooleanPtr(GateRef x)433 GateRef CircuitBuilder::BooleanToTaggedBooleanPtr(GateRef x)
434 {
435     auto val = ZExtInt1ToInt64(x);
436     return Int64ToTaggedPtr(Int64Or(val, Int64(JSTaggedValue::TAG_BOOLEAN_MASK)));
437 }
438 
Float32ToTaggedDoublePtr(GateRef x)439 GateRef CircuitBuilder::Float32ToTaggedDoublePtr(GateRef x)
440 {
441     GateRef val = ExtFloat32ToDouble(x);
442     return DoubleToTaggedDoublePtr(val);
443 }
444 
TaggedDoublePtrToFloat32(GateRef x)445 GateRef CircuitBuilder::TaggedDoublePtrToFloat32(GateRef x)
446 {
447     GateRef val = GetDoubleOfTDouble(x);
448     return TruncDoubleToFloat32(val);
449 }
450 
TaggedIntPtrToFloat32(GateRef x)451 GateRef CircuitBuilder::TaggedIntPtrToFloat32(GateRef x)
452 {
453     GateRef val = GetInt32OfTInt(x);
454     return ChangeInt32ToFloat32(val);
455 }
456 
DoubleToTaggedDouble(GateRef x)457 GateRef CircuitBuilder::DoubleToTaggedDouble(GateRef x)
458 {
459     GateRef val = CastDoubleToInt64(x);
460     return Int64Add(val, Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET));
461 }
462 
DoubleIsNAN(GateRef x)463 GateRef CircuitBuilder::DoubleIsNAN(GateRef x)
464 {
465     GateRef diff = Equal(x, x);
466     return Equal(SExtInt1ToInt32(diff), Int32(0));
467 }
468 
DoubleToTagged(GateRef x)469 GateRef CircuitBuilder::DoubleToTagged(GateRef x)
470 {
471     GateRef val = CastDoubleToInt64(x);
472     acc_.SetGateType(val, GateType::TaggedValue());
473     return Int64Add(val, Int64(JSTaggedValue::DOUBLE_ENCODE_OFFSET));
474 }
475 
TaggedTrue()476 GateRef CircuitBuilder::TaggedTrue()
477 {
478     return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_TRUE, GateType::TaggedValue());
479 }
480 
TaggedFalse()481 GateRef CircuitBuilder::TaggedFalse()
482 {
483     return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_FALSE, GateType::TaggedValue());
484 }
485 
GetValueFromTaggedArray(GateRef array,GateRef index)486 GateRef CircuitBuilder::GetValueFromTaggedArray(GateRef array, GateRef index)
487 {
488     GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
489     GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
490     return Load(VariableType::JS_ANY(), array, dataOffset);
491 }
492 
SetValueToTaggedArray(VariableType valType,GateRef glue,GateRef array,GateRef index,GateRef val)493 void CircuitBuilder::SetValueToTaggedArray(VariableType valType, GateRef glue,
494                                            GateRef array, GateRef index, GateRef val)
495 {
496     GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
497     GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
498     Store(valType, glue, array, dataOffset, val);
499 }
500 
GetGlobalConstantString(ConstantIndex index)501 GateRef CircuitBuilder::GetGlobalConstantString(ConstantIndex index)
502 {
503     return PtrMul(IntPtr(sizeof(JSTaggedValue)), IntPtr(static_cast<int>(index)));
504 }
505 
506 // object operation
LoadHClass(GateRef object)507 GateRef CircuitBuilder::LoadHClass(GateRef object)
508 {
509     GateRef offset = IntPtr(TaggedObject::HCLASS_OFFSET);
510     return Load(VariableType::JS_POINTER(), object, offset);
511 }
512 
StoreHClass(GateRef glue,GateRef object,GateRef hClass)513 void CircuitBuilder::StoreHClass(GateRef glue, GateRef object, GateRef hClass)
514 {
515     Store(VariableType::JS_POINTER(), glue, object, IntPtr(TaggedObject::HCLASS_OFFSET), hClass);
516 }
517 
IsJsType(GateRef obj,JSType type)518 GateRef CircuitBuilder::IsJsType(GateRef obj, JSType type)
519 {
520     GateRef objectType = GetObjectType(LoadHClass(obj));
521     return Equal(objectType, Int32(static_cast<int32_t>(type)));
522 }
523 
IsDictionaryMode(GateRef object)524 inline GateRef CircuitBuilder::IsDictionaryMode(GateRef object)
525 {
526     GateRef type = GetObjectType(LoadHClass(object));
527     return Int32Equal(type, Int32(static_cast<int32_t>(JSType::TAGGED_DICTIONARY)));
528 }
529 
GetObjectType(GateRef hClass)530 GateRef CircuitBuilder::GetObjectType(GateRef hClass)
531 {
532     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
533     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
534     return Int32And(bitfield, Int32((1LU << JSHClass::ObjectTypeBits::SIZE) - 1));
535 }
536 
IsDictionaryModeByHClass(GateRef hClass)537 GateRef CircuitBuilder::IsDictionaryModeByHClass(GateRef hClass)
538 {
539     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
540     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
541     return NotEqual(Int32And(Int32LSR(bitfield,
542         Int32(JSHClass::IsDictionaryBit::START_BIT)),
543         Int32((1LU << JSHClass::IsDictionaryBit::SIZE) - 1)),
544         Int32(0));
545 }
546 
IsDictionaryElement(GateRef hClass)547 GateRef CircuitBuilder::IsDictionaryElement(GateRef hClass)
548 {
549     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
550     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
551     return NotEqual(Int32And(Int32LSR(bitfield,
552         Int32(JSHClass::DictionaryElementBits::START_BIT)),
553         Int32((1LU << JSHClass::DictionaryElementBits::SIZE) - 1)),
554         Int32(0));
555 }
556 
IsClassConstructor(GateRef object)557 GateRef CircuitBuilder::IsClassConstructor(GateRef object)
558 {
559     GateRef hClass = LoadHClass(object);
560     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
561     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
562     return NotEqual(Int32And(Int32LSR(bitfield,
563         Int32(JSHClass::ClassConstructorBit::START_BIT)),
564         Int32((1LU << JSHClass::ClassConstructorBit::SIZE) - 1)),
565         Int32(0));
566 }
567 
IsClassPrototype(GateRef object)568 GateRef CircuitBuilder::IsClassPrototype(GateRef object)
569 {
570     GateRef hClass = LoadHClass(object);
571     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
572     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
573     // decode
574     return NotEqual(
575         Int32And(Int32LSR(bitfield, Int32(JSHClass::ClassPrototypeBit::START_BIT)),
576         Int32((1LU << JSHClass::ClassPrototypeBit::SIZE) - 1)),
577         Int32(0));
578 }
579 
IsExtensible(GateRef object)580 GateRef CircuitBuilder::IsExtensible(GateRef object)
581 {
582     GateRef hClass = LoadHClass(object);
583     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
584     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
585     return NotEqual(Int32And(Int32LSR(bitfield,
586         Int32(JSHClass::ExtensibleBit::START_BIT)),
587         Int32((1LU << JSHClass::ExtensibleBit::SIZE) - 1)),
588         Int32(0));
589 }
590 
TaggedObjectIsEcmaObject(GateRef obj)591 GateRef CircuitBuilder::TaggedObjectIsEcmaObject(GateRef obj)
592 {
593     GateRef objectType = GetObjectType(LoadHClass(obj));
594     return BoolAnd(
595         Int32LessThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::ECMA_OBJECT_LAST))),
596         Int32GreaterThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::ECMA_OBJECT_FIRST))));
597 }
598 
IsJSObject(GateRef obj)599 GateRef CircuitBuilder::IsJSObject(GateRef obj)
600 {
601     GateRef objectType = GetObjectType(LoadHClass(obj));
602     auto ret = BoolAnd(
603         Int32LessThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT_LAST))),
604         Int32GreaterThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT_FIRST))));
605     return LogicAnd(TaggedIsHeapObject(obj), ret);
606 }
607 
TaggedObjectBothAreString(GateRef x,GateRef y)608 GateRef CircuitBuilder::TaggedObjectBothAreString(GateRef x, GateRef y)
609 {
610     return BoolAnd(IsJsType(x, JSType::STRING), IsJsType(y, JSType::STRING));
611 }
612 
IsCallableFromBitField(GateRef bitfield)613 GateRef CircuitBuilder::IsCallableFromBitField(GateRef bitfield)
614 {
615     return NotEqual(
616         Int32And(Int32LSR(bitfield, Int32(JSHClass::CallableBit::START_BIT)),
617             Int32((1LU << JSHClass::CallableBit::SIZE) - 1)),
618         Int32(0));
619 }
620 
IsCallable(GateRef obj)621 GateRef CircuitBuilder::IsCallable(GateRef obj)
622 {
623     GateRef hClass = LoadHClass(obj);
624     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
625     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
626     return IsCallableFromBitField(bitfield);
627 }
628 
BothAreString(GateRef x,GateRef y)629 GateRef CircuitBuilder::BothAreString(GateRef x, GateRef y)
630 {
631     Label subentry(env_);
632     SubCfgEntry(&subentry);
633     Label bothAreHeapObjet(env_);
634     Label bothAreStringType(env_);
635     Label exit(env_);
636     DEFVAlUE(result, env_, VariableType::BOOL(), False());
637     Branch(BoolAnd(TaggedIsHeapObject(x), TaggedIsHeapObject(y)), &bothAreHeapObjet, &exit);
638     Bind(&bothAreHeapObjet);
639     {
640         Branch(TaggedObjectBothAreString(x, y), &bothAreStringType, &exit);
641         Bind(&bothAreStringType);
642         {
643             result = True();
644             Jump(&exit);
645         }
646     }
647     Bind(&exit);
648     auto ret = *result;
649     SubCfgExit();
650     return ret;
651 }
652 
GetObjectSizeFromHClass(GateRef hClass)653 GateRef CircuitBuilder::GetObjectSizeFromHClass(GateRef hClass)
654 {
655     // NOTE: check for special case of string and TAGGED_ARRAY
656     GateRef bitfield = Load(VariableType::INT32(), hClass, IntPtr(JSHClass::BIT_FIELD1_OFFSET));
657     GateRef objectSizeInWords = Int32And(Int32LSR(bitfield,
658         Int32(JSHClass::ObjectSizeInWordsBits::START_BIT)),
659         Int32((1LU << JSHClass::ObjectSizeInWordsBits::SIZE) - 1));
660     return PtrMul(ZExtInt32ToPtr(objectSizeInWords), IntPtr(JSTaggedValue::TaggedTypeSize()));
661 }
662 
663 template<TypedBinOp Op>
TypedBinaryOp(GateRef x,GateRef y,GateType xType,GateType yType,GateType gateType)664 GateRef CircuitBuilder::TypedBinaryOp(GateRef x, GateRef y, GateType xType, GateType yType, GateType gateType)
665 {
666     auto currentLabel = env_->GetCurrentLabel();
667     auto currentControl = currentLabel->GetControl();
668     auto currentDepend = currentLabel->GetDepend();
669     auto numberBinaryOp = TypedBinaryOperator(MachineType::I64, Op, xType, yType,
670                                               {currentControl, currentDepend, x, y}, gateType);
671     currentLabel->SetControl(numberBinaryOp);
672     currentLabel->SetDepend(numberBinaryOp);
673     return numberBinaryOp;
674 }
675 
676 template<TypedUnOp Op>
TypedUnaryOp(GateRef x,GateType xType,GateType gateType)677 GateRef CircuitBuilder::TypedUnaryOp(GateRef x, GateType xType, GateType gateType)
678 {
679     auto currentLabel = env_->GetCurrentLabel();
680     auto currentControl = currentLabel->GetControl();
681     auto currentDepend = currentLabel->GetDepend();
682     auto machineType = (Op == TypedUnOp::TYPED_TOBOOL) ? MachineType::I1 : MachineType::I64;
683     auto numberUnaryOp = TypedUnaryOperator(machineType, Op, xType, {currentControl, currentDepend, x}, gateType);
684     currentLabel->SetControl(numberUnaryOp);
685     currentLabel->SetDepend(numberUnaryOp);
686     return numberUnaryOp;
687 }
688 
689 template<TypedLoadOp Op>
LoadElement(GateRef receiver,GateRef index)690 GateRef CircuitBuilder::LoadElement(GateRef receiver, GateRef index)
691 {
692     auto opIdx = static_cast<uint64_t>(Op);
693     auto currentLabel = env_->GetCurrentLabel();
694     auto currentControl = currentLabel->GetControl();
695     auto currentDepend = currentLabel->GetDepend();
696     auto ret = GetCircuit()->NewGate(GetCircuit()->LoadElement(opIdx), MachineType::ANYVALUE,
697                                      { currentControl, currentDepend, receiver, index }, GateType::AnyType());
698     currentLabel->SetControl(ret);
699     currentLabel->SetDepend(ret);
700     return ret;
701 }
702 
703 template<TypedStoreOp Op>
StoreElement(GateRef receiver,GateRef index,GateRef value)704 GateRef CircuitBuilder::StoreElement(GateRef receiver, GateRef index, GateRef value)
705 {
706     auto opIdx = static_cast<uint64_t>(Op);
707     auto currentLabel = env_->GetCurrentLabel();
708     auto currentControl = currentLabel->GetControl();
709     auto currentDepend = currentLabel->GetDepend();
710     auto ret = GetCircuit()->NewGate(GetCircuit()->StoreElement(opIdx), MachineType::NOVALUE,
711                                      { currentControl, currentDepend, receiver, index, value }, GateType::AnyType());
712     currentLabel->SetControl(ret);
713     currentLabel->SetDepend(ret);
714     return ret;
715 }
716 
717 // Number operator
718 template<TypedBinOp Op>
NumberBinaryOp(GateRef x,GateRef y)719 GateRef CircuitBuilder::NumberBinaryOp(GateRef x, GateRef y)
720 {
721     auto currentLabel = env_->GetCurrentLabel();
722     auto currentControl = currentLabel->GetControl();
723     auto currentDepend = currentLabel->GetDepend();
724     auto numberBinaryOp = TypedBinaryOperator(MachineType::I64, Op,
725                                               GateType::NumberType(), GateType::NumberType(),
726                                               {currentControl, currentDepend, x, y}, GateType::AnyType());
727     currentLabel->SetControl(numberBinaryOp);
728     currentLabel->SetDepend(numberBinaryOp);
729     return numberBinaryOp;
730 }
731 
PrimitiveToNumber(GateRef x,VariableType type)732 GateRef CircuitBuilder::PrimitiveToNumber(GateRef x, VariableType type)
733 {
734     auto currentLabel = env_->GetCurrentLabel();
735     auto currentControl = currentLabel->GetControl();
736     auto currentDepend = currentLabel->GetDepend();
737     auto numberconvert = TypeConvert(MachineType::I64, type.GetGateType(), GateType::NumberType(),
738                                      {currentControl, currentDepend, x});
739     currentLabel->SetControl(numberconvert);
740     currentLabel->SetDepend(numberconvert);
741     return numberconvert;
742 }
743 
LogicAnd(GateRef x,GateRef y)744 GateRef CircuitBuilder::LogicAnd(GateRef x, GateRef y)
745 {
746     Label subentry(env_);
747     SubCfgEntry(&subentry);
748     Label exit(env_);
749     Label isX(env_);
750     Label notX(env_);
751     DEFVAlUE(result, env_, VariableType::BOOL(), x);
752     Branch(x, &isX, &notX);
753     Bind(&isX);
754     {
755         result = y;
756         Jump(&exit);
757     }
758     Bind(&notX);
759     {
760         Jump(&exit);
761     }
762     Bind(&exit);
763     auto ret = *result;
764     SubCfgExit();
765     return ret;
766 }
767 
LogicOr(GateRef x,GateRef y)768 GateRef CircuitBuilder::LogicOr(GateRef x, GateRef y)
769 {
770     Label subentry(env_);
771     SubCfgEntry(&subentry);
772     Label exit(env_);
773     Label isX(env_);
774     Label notX(env_);
775     DEFVAlUE(result, env_, VariableType::BOOL(), x);
776     Branch(x, &isX, &notX);
777     Bind(&isX);
778     {
779         Jump(&exit);
780     }
781     Bind(&notX);
782     {
783         result = y;
784         Jump(&exit);
785     }
786     Bind(&exit);
787     auto ret = *result;
788     SubCfgExit();
789     return ret;
790 }
791 
NextVariableId()792 int CircuitBuilder::NextVariableId()
793 {
794     return env_->NextVariableId();
795 }
796 
HandleException(GateRef result,Label * success,Label * fail,Label * exit)797 void CircuitBuilder::HandleException(GateRef result, Label *success, Label *fail, Label *exit)
798 {
799     Branch(Equal(result, ExceptionConstant()), fail, success);
800     Bind(fail);
801     {
802         Jump(exit);
803     }
804 }
805 
HandleException(GateRef result,Label * success,Label * fail,Label * exit,GateRef exceptionVal)806 void CircuitBuilder::HandleException(GateRef result, Label *success, Label *fail, Label *exit, GateRef exceptionVal)
807 {
808     Branch(Equal(result, exceptionVal), fail, success);
809     Bind(fail);
810     {
811         Jump(exit);
812     }
813 }
814 
SubCfgEntry(Label * entry)815 void CircuitBuilder::SubCfgEntry(Label *entry)
816 {
817     ASSERT(env_ != nullptr);
818     env_->SubCfgEntry(entry);
819 }
820 
SubCfgExit()821 void CircuitBuilder::SubCfgExit()
822 {
823     ASSERT(env_ != nullptr);
824     env_->SubCfgExit();
825 }
826 
Return(GateRef value)827 GateRef CircuitBuilder::Return(GateRef value)
828 {
829     auto control = GetCurrentLabel()->GetControl();
830     auto depend = GetCurrentLabel()->GetDepend();
831     return Return(control, depend, value);
832 }
833 
Return()834 GateRef CircuitBuilder::Return()
835 {
836     auto control = GetCurrentLabel()->GetControl();
837     auto depend = GetCurrentLabel()->GetDepend();
838     return ReturnVoid(control, depend);
839 }
840 
Bind(Label * label)841 void CircuitBuilder::Bind(Label *label)
842 {
843     label->Bind();
844     env_->SetCurrentLabel(label);
845 }
846 
Bind(Label * label,bool justSlowPath)847 void CircuitBuilder::Bind(Label *label, bool justSlowPath)
848 {
849     if (!justSlowPath) {
850         label->Bind();
851         env_->SetCurrentLabel(label);
852     }
853 }
854 
GetCurrentLabel()855 Label *CircuitBuilder::GetCurrentLabel() const
856 {
857     return GetCurrentEnvironment()->GetCurrentLabel();
858 }
859 
GetState()860 GateRef CircuitBuilder::GetState() const
861 {
862     return GetCurrentLabel()->GetControl();
863 }
864 
GetDepend()865 GateRef CircuitBuilder::GetDepend() const
866 {
867     return GetCurrentLabel()->GetDepend();
868 }
869 
SetDepend(GateRef depend)870 void CircuitBuilder::SetDepend(GateRef depend)
871 {
872     GetCurrentLabel()->SetDepend(depend);
873 }
874 
SetState(GateRef state)875 void CircuitBuilder::SetState(GateRef state)
876 {
877     GetCurrentLabel()->SetControl(state);
878 }
879 
880 // ctor is base but not builtin
IsBase(GateRef ctor)881 inline GateRef CircuitBuilder::IsBase(GateRef ctor)
882 {
883     GateRef method = GetMethodFromFunction(ctor);
884     GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
885     GateRef bitfield = Load(VariableType::INT32(), method, extraLiteralInfoOffset);
886 
887     GateRef kind = Int32And(Int32LSR(bitfield, Int32(MethodLiteral::FunctionKindBits::START_BIT)),
888                             Int32((1LU << MethodLiteral::FunctionKindBits::SIZE) - 1));
889     return Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(FunctionKind::CLASS_CONSTRUCTOR)));
890 }
891 
TypedCallBuiltin(GateRef x,BuiltinsStubCSigns::ID id)892 inline GateRef CircuitBuilder::TypedCallBuiltin(GateRef x, BuiltinsStubCSigns::ID id)
893 {
894     auto currentLabel = env_->GetCurrentLabel();
895     auto currentControl = currentLabel->GetControl();
896     auto currentDepend = currentLabel->GetDepend();
897     GateRef idGate = Int8(static_cast<int8_t>(id));
898     auto numberMathOp = TypedCallOperator(MachineType::I64, {currentControl, currentDepend, x, idGate});
899     currentLabel->SetControl(numberMathOp);
900     currentLabel->SetDepend(numberMathOp);
901     return numberMathOp;
902 }
903 
Seal()904 void Label::Seal()
905 {
906     return impl_->Seal();
907 }
908 
Bind()909 void Label::Bind()
910 {
911     impl_->Bind();
912 }
913 
MergeAllControl()914 void Label::MergeAllControl()
915 {
916     impl_->MergeAllControl();
917 }
918 
MergeAllDepend()919 void Label::MergeAllDepend()
920 {
921     impl_->MergeAllDepend();
922 }
923 
AppendPredecessor(const Label * predecessor)924 void Label::AppendPredecessor(const Label *predecessor)
925 {
926     impl_->AppendPredecessor(predecessor->GetRawLabel());
927 }
928 
GetPredecessors()929 std::vector<Label> Label::GetPredecessors() const
930 {
931     std::vector<Label> labels;
932     for (auto rawlabel : impl_->GetPredecessors()) {
933         labels.emplace_back(Label(rawlabel));
934     }
935     return labels;
936 }
937 
SetControl(GateRef control)938 void Label::SetControl(GateRef control)
939 {
940     impl_->SetControl(control);
941 }
942 
SetPreControl(GateRef control)943 void Label::SetPreControl(GateRef control)
944 {
945     impl_->SetPreControl(control);
946 }
947 
MergeControl(GateRef control)948 void Label::MergeControl(GateRef control)
949 {
950     impl_->MergeControl(control);
951 }
952 
GetControl()953 GateRef Label::GetControl() const
954 {
955     return impl_->GetControl();
956 }
957 
GetDepend()958 GateRef Label::GetDepend() const
959 {
960     return impl_->GetDepend();
961 }
962 
SetDepend(GateRef depend)963 void Label::SetDepend(GateRef depend)
964 {
965     return impl_->SetDepend(depend);
966 }
967 
GetLabelFromSelector(GateRef sel)968 Label Environment::GetLabelFromSelector(GateRef sel)
969 {
970     Label::LabelImpl *rawlabel = phiToLabels_[sel];
971     return Label(rawlabel);
972 }
973 
AddSelectorToLabel(GateRef sel,Label label)974 void Environment::AddSelectorToLabel(GateRef sel, Label label)
975 {
976     phiToLabels_[sel] = label.GetRawLabel();
977 }
978 
NewLabel(Environment * env,GateRef control)979 Label::LabelImpl *Environment::NewLabel(Environment *env, GateRef control)
980 {
981     auto impl = new Label::LabelImpl(env, control);
982     rawLabels_.emplace_back(impl);
983     return impl;
984 }
985 
SubCfgEntry(Label * entry)986 void Environment::SubCfgEntry(Label *entry)
987 {
988     if (currentLabel_ != nullptr) {
989         GateRef control = currentLabel_->GetControl();
990         GateRef depend = currentLabel_->GetDepend();
991         stack_.push(currentLabel_);
992         currentLabel_ = entry;
993         currentLabel_->SetControl(control);
994         currentLabel_->SetDepend(depend);
995     }
996 }
997 
SubCfgExit()998 void Environment::SubCfgExit()
999 {
1000     if (currentLabel_ != nullptr) {
1001         GateRef control = currentLabel_->GetControl();
1002         GateRef depend = currentLabel_->GetDepend();
1003         if (!stack_.empty()) {
1004             currentLabel_ = stack_.top();
1005             currentLabel_->SetControl(control);
1006             currentLabel_->SetDepend(depend);
1007             stack_.pop();
1008         }
1009     }
1010 }
1011 
GetInput(size_t index)1012 GateRef Environment::GetInput(size_t index) const
1013 {
1014     return inputList_.at(index);
1015 }
1016 
1017 // only for int32
1018 template<TypedUnOp Op>
Int32OverflowCheck(GateRef gate)1019 GateRef CircuitBuilder::Int32OverflowCheck(GateRef gate)
1020 {
1021     auto currentLabel = env_->GetCurrentLabel();
1022     auto currentControl = currentLabel->GetControl();
1023     auto currentDepend = currentLabel->GetDepend();
1024     ASSERT(acc_.HasFrameState(currentDepend));
1025     auto frameState = acc_.GetFrameState(currentDepend);
1026 
1027     uint64_t value = TypedUnaryAccessor::ToValue(GateType::Empty(), Op);
1028     GateRef ret = GetCircuit()->NewGate(circuit_->Int32OverflowCheck(value),
1029         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
1030     currentLabel->SetControl(ret);
1031     currentLabel->SetDepend(ret);
1032     return ret;
1033 }
1034 } // namespace panda::ecmascript::kungfu
1035 
1036 #endif