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, ¬X);
753 Bind(&isX);
754 {
755 result = y;
756 Jump(&exit);
757 }
758 Bind(¬X);
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, ¬X);
777 Bind(&isX);
778 {
779 Jump(&exit);
780 }
781 Bind(¬X);
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