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