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