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(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
TaggedIsArrayIterator(GateRef obj)127 GateRef CircuitBuilder::TaggedIsArrayIterator(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(TaggedIsHeapObject(obj), &isHeapObject, &exit);
135 Bind(&isHeapObject);
136 {
137 result = Int32Equal(GetObjectType(LoadHClass(obj)),
138 Int32(static_cast<int32_t>(JSType::JS_ARRAY_ITERATOR)));
139 Jump(&exit);
140 }
141 Bind(&exit);
142 auto ret = *result;
143 SubCfgExit();
144 return ret;
145 }
146
TaggedIsBigInt(GateRef obj)147 GateRef CircuitBuilder::TaggedIsBigInt(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(TaggedIsHeapObject(obj), &isHeapObject, &exit);
155 Bind(&isHeapObject);
156 {
157 result = Int32Equal(GetObjectType(LoadHClass(obj)),
158 Int32(static_cast<int32_t>(JSType::BIGINT)));
159 Jump(&exit);
160 }
161 Bind(&exit);
162 auto ret = *result;
163 SubCfgExit();
164 return ret;
165 }
166
TaggedIsString(GateRef obj)167 GateRef CircuitBuilder::TaggedIsString(GateRef obj)
168 {
169 Label entry(env_);
170 SubCfgEntry(&entry);
171 Label exit(env_);
172 DEFVALUE(result, env_, VariableType::BOOL(), False());
173 Label isHeapObject(env_);
174 BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
175 Bind(&isHeapObject);
176 {
177 result = TaggedObjectIsString(obj);
178 Jump(&exit);
179 }
180 Bind(&exit);
181 auto ret = *result;
182 SubCfgExit();
183 return ret;
184 }
185
TaggedIsStringIterator(GateRef obj)186 GateRef CircuitBuilder::TaggedIsStringIterator(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(TaggedIsHeapObject(obj), &isHeapObject, &exit);
194 Bind(&isHeapObject);
195 {
196 result = Int32Equal(GetObjectType(LoadHClass(obj)),
197 Int32(static_cast<int32_t>(JSType::JS_STRING_ITERATOR)));
198 Jump(&exit);
199 }
200 Bind(&exit);
201 auto ret = *result;
202 SubCfgExit();
203 return ret;
204 }
205
TaggedIsSharedObj(GateRef obj)206 GateRef CircuitBuilder::TaggedIsSharedObj(GateRef obj)
207 {
208 Label entry(env_);
209 SubCfgEntry(&entry);
210 Label exit(env_);
211 DEFVALUE(result, env_, VariableType::BOOL(), False());
212 Label isHeapObject(env_);
213 BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
214 Bind(&isHeapObject);
215 {
216 result = TaggedObjectIsShared(obj);
217 Jump(&exit);
218 }
219 Bind(&exit);
220 auto ret = *result;
221 SubCfgExit();
222 return ret;
223 }
224
TaggedIsStableArray(GateRef glue,GateRef obj)225 GateRef CircuitBuilder::TaggedIsStableArray(GateRef glue, GateRef obj)
226 {
227 Label subentry(env_);
228 env_->SubCfgEntry(&subentry);
229 DEFVALUE(result, env_, VariableType::BOOL(), False());
230 Label exit(env_);
231 Label targetIsHeapObject(env_);
232 Label targetIsStableArray(env_);
233
234 BRANCH(TaggedIsHeapObject(obj), &targetIsHeapObject, &exit);
235 Bind(&targetIsHeapObject);
236 {
237 GateRef jsHclass = LoadHClass(obj);
238 BRANCH(IsStableArray(jsHclass), &targetIsStableArray, &exit);
239 Bind(&targetIsStableArray);
240 {
241 GateRef guardiansOffset =
242 IntPtr(JSThread::GlueData::GetArrayElementsGuardiansOffset(false));
243 result = Load(VariableType::BOOL(), glue, guardiansOffset);
244 Jump(&exit);
245 }
246 }
247 Bind(&exit);
248 auto res = *result;
249 env_->SubCfgExit();
250 return res;
251 }
252
TaggedIsSymbol(GateRef obj)253 GateRef CircuitBuilder::TaggedIsSymbol(GateRef obj)
254 {
255 Label entry(env_);
256 SubCfgEntry(&entry);
257 Label exit(env_);
258 DEFVALUE(result, env_, VariableType::BOOL(), False());
259 Label isHeapObject(env_);
260 BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
261 Bind(&isHeapObject);
262 {
263 GateRef objType = GetObjectType(LoadHClass(obj));
264 result = Equal(objType, Int32(static_cast<int32_t>(JSType::SYMBOL)));
265 Jump(&exit);
266 }
267 Bind(&exit);
268 auto ret = *result;
269 SubCfgExit();
270 return ret;
271 }
272
TaggedIsStringOrSymbol(GateRef obj)273 GateRef CircuitBuilder::TaggedIsStringOrSymbol(GateRef obj)
274 {
275 Label entry(env_);
276 SubCfgEntry(&entry);
277 Label exit(env_);
278 DEFVALUE(result, env_, VariableType::BOOL(), False());
279 Label isHeapObject(env_);
280 BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
281 Bind(&isHeapObject);
282 {
283 result = TaggedObjectIsString(obj);
284 Label isString(env_);
285 Label notString(env_);
286 BRANCH(*result, &exit, ¬String);
287 Bind(¬String);
288 {
289 GateRef objType = GetObjectType(LoadHClass(obj));
290 result = Equal(objType, Int32(static_cast<int32_t>(JSType::SYMBOL)));
291 Jump(&exit);
292 }
293 }
294 Bind(&exit);
295 auto ret = *result;
296 SubCfgExit();
297 return ret;
298 }
299
TaggedIsProtoChangeMarker(GateRef obj)300 GateRef CircuitBuilder::TaggedIsProtoChangeMarker(GateRef obj)
301 {
302 Label entry(env_);
303 SubCfgEntry(&entry);
304 Label exit(env_);
305 DEFVALUE(result, env_, VariableType::BOOL(), False());
306 Label isHeapObject(env_);
307 BRANCH(TaggedIsHeapObject(obj), &isHeapObject, &exit);
308 Bind(&isHeapObject);
309 {
310 GateRef objType = GetObjectType(LoadHClass(obj));
311 result = Equal(objType, Int32(static_cast<int32_t>(JSType::PROTO_CHANGE_MARKER)));
312 Jump(&exit);
313 }
314 Bind(&exit);
315 auto ret = *result;
316 SubCfgExit();
317 return ret;
318 }
319
TaggedObjectIsJSMap(GateRef obj)320 GateRef CircuitBuilder::TaggedObjectIsJSMap(GateRef obj)
321 {
322 GateRef objType = GetObjectType(LoadHClass(obj));
323 return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_MAP)));
324 }
325
TaggedObjectIsJSSet(GateRef obj)326 GateRef CircuitBuilder::TaggedObjectIsJSSet(GateRef obj)
327 {
328 GateRef objType = GetObjectType(LoadHClass(obj));
329 return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_SET)));
330 }
331
TaggedObjectIsJSDate(GateRef obj)332 GateRef CircuitBuilder::TaggedObjectIsJSDate(GateRef obj)
333 {
334 GateRef objType = GetObjectType(LoadHClass(obj));
335 return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_DATE)));
336 }
337
TaggedObjectIsTypedArray(GateRef obj)338 GateRef CircuitBuilder::TaggedObjectIsTypedArray(GateRef obj)
339 {
340 GateRef jsType = GetObjectType(LoadHClass(obj));
341 return BitAnd(Int32GreaterThan(jsType, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY_FIRST))),
342 Int32GreaterThanOrEqual(Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY_LAST)), jsType));
343 }
344
TaggedObjectIsJSArray(GateRef obj)345 GateRef CircuitBuilder::TaggedObjectIsJSArray(GateRef obj)
346 {
347 GateRef objType = GetObjectType(LoadHClass(obj));
348 return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_ARRAY)));
349 }
350
TaggedIsBoundFunction(GateRef obj)351 GateRef CircuitBuilder::TaggedIsBoundFunction(GateRef obj)
352 {
353 GateRef objType = GetObjectType(LoadHClass(obj));
354 return Equal(objType, Int32(static_cast<int32_t>(JSType::JS_BOUND_FUNCTION)));
355 }
356
JudgeAotAndFastCall(GateRef jsFunc,JudgeMethodType type)357 inline GateRef CircuitBuilder::JudgeAotAndFastCall(GateRef jsFunc, JudgeMethodType type)
358 {
359 GateRef bitFieldOffset = IntPtr(JSFunctionBase::BIT_FIELD_OFFSET);
360 GateRef bitField = Load(VariableType::INT32(), jsFunc, bitFieldOffset);
361 switch (type) {
362 case JudgeMethodType::HAS_AOT: {
363 return Int32NotEqual(
364 Int32And(
365 Int32LSR(bitField, Int32(JSFunctionBase::IsCompiledCodeBit::START_BIT)),
366 Int32((1U << JSFunctionBase::IsCompiledCodeBit::SIZE) - 1)),
367 Int32(0));
368 }
369 case JudgeMethodType::HAS_AOT_FASTCALL: {
370 return Int32Equal(
371 Int32And(
372 bitField,
373 Int32(JSFunctionBase::COMPILED_CODE_FASTCALL_BITS << JSFunctionBase::IsCompiledCodeBit::START_BIT)),
374 Int32(JSFunctionBase::COMPILED_CODE_FASTCALL_BITS << JSFunctionBase::IsCompiledCodeBit::START_BIT));
375 }
376 case JudgeMethodType::HAS_AOT_NOTFASTCALL: {
377 GateRef fastCallField =
378 Int32And(bitField,
379 Int32(JSFunctionBase::COMPILED_CODE_FASTCALL_BITS << JSFunctionBase::IsCompiledCodeBit::START_BIT));
380 GateRef hasAot = Int32(1U << JSFunctionBase::IsCompiledCodeBit::START_BIT);
381 return Int32Equal(fastCallField, hasAot);
382 }
383 default:
384 UNREACHABLE();
385 }
386 }
387
BothAreString(GateRef x,GateRef y)388 GateRef CircuitBuilder::BothAreString(GateRef x, GateRef y)
389 {
390 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(TaggedIsHeapObject(y))
391 .And(TaggedObjectIsString(x)).And(TaggedObjectIsString(y)).Done();
392 }
393
TaggedIsHole(GateRef x)394 GateRef CircuitBuilder::TaggedIsHole(GateRef x)
395 {
396 return Equal(x, HoleConstant());
397 }
398
TaggedIsNullPtr(GateRef x)399 GateRef CircuitBuilder::TaggedIsNullPtr(GateRef x)
400 {
401 return Equal(x, NullPtrConstant());
402 }
403
IsSpecialHole(GateRef x)404 GateRef CircuitBuilder::IsSpecialHole(GateRef x)
405 {
406 return Equal(x, SpecialHoleConstant());
407 }
408
IsNotSpecialHole(GateRef x)409 GateRef CircuitBuilder::IsNotSpecialHole(GateRef x)
410 {
411 return NotEqual(x, SpecialHoleConstant());
412 }
413
TaggedIsNotHole(GateRef x)414 GateRef CircuitBuilder::TaggedIsNotHole(GateRef x)
415 {
416 return NotEqual(x, HoleConstant());
417 }
418
TaggedIsUndefined(GateRef x)419 GateRef CircuitBuilder::TaggedIsUndefined(GateRef x)
420 {
421 return Equal(x, UndefineConstant());
422 }
423
TaggedIsException(GateRef x)424 GateRef CircuitBuilder::TaggedIsException(GateRef x)
425 {
426 return Equal(x, ExceptionConstant());
427 }
428
TaggedIsSpecial(GateRef x)429 GateRef CircuitBuilder::TaggedIsSpecial(GateRef x)
430 {
431 return LogicOrBuilder(env_)
432 .Or(TaggedIsHole(x))
433 .Or(Equal(Int64And(ChangeTaggedPointerToInt64(x), Int64(JSTaggedValue::TAG_SPECIAL_MASK)),
434 Int64(JSTaggedValue::TAG_SPECIAL)))
435 .Done();
436 }
437
TaggedIsHeapObject(GateRef x)438 GateRef CircuitBuilder::TaggedIsHeapObject(GateRef x)
439 {
440 x = ChangeTaggedPointerToInt64(x);
441 auto t = Int64And(x, Int64(JSTaggedValue::TAG_HEAPOBJECT_MASK), GateType::Empty(), "checkHeapObject");
442 return Equal(t, Int64(0), "checkHeapObject");
443 }
444
TaggedIsAsyncGeneratorObject(GateRef x)445 GateRef CircuitBuilder::TaggedIsAsyncGeneratorObject(GateRef x)
446 {
447 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::JS_ASYNC_GENERATOR_OBJECT)).Done();
448 }
449
TaggedIsJSGlobalObject(GateRef x)450 GateRef CircuitBuilder::TaggedIsJSGlobalObject(GateRef x)
451 {
452 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::JS_GLOBAL_OBJECT)).Done();
453 }
454
TaggedIsGeneratorObject(GateRef x)455 GateRef CircuitBuilder::TaggedIsGeneratorObject(GateRef x)
456 {
457 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::JS_GENERATOR_OBJECT)).Done();
458 }
459
TaggedIsJSArray(GateRef x)460 GateRef CircuitBuilder::TaggedIsJSArray(GateRef x)
461 {
462 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::JS_ARRAY)).Done();
463 }
464
TaggedIsPropertyBox(GateRef x)465 GateRef CircuitBuilder::TaggedIsPropertyBox(GateRef x)
466 {
467 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::PROPERTY_BOX)).Done();
468 }
469
TaggedIsWeak(GateRef x)470 GateRef CircuitBuilder::TaggedIsWeak(GateRef x)
471 {
472 return LogicAndBuilder(env_)
473 .And(TaggedIsHeapObject(x))
474 .And(Equal(Int64And(ChangeTaggedPointerToInt64(x), Int64(JSTaggedValue::TAG_WEAK)), Int64(1)))
475 .Done();
476 }
477
TaggedIsPrototypeHandler(GateRef x)478 GateRef CircuitBuilder::TaggedIsPrototypeHandler(GateRef x)
479 {
480 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::PROTOTYPE_HANDLER)).Done();
481 }
482
TaggedIsTransitionHandler(GateRef x)483 GateRef CircuitBuilder::TaggedIsTransitionHandler(GateRef x)
484 {
485 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::TRANSITION_HANDLER)).Done();
486 }
487
TaggedIsStoreAOTHandler(GateRef x)488 GateRef CircuitBuilder::TaggedIsStoreAOTHandler(GateRef x)
489 {
490 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::STORE_TS_HANDLER)).Done();
491 }
492
TaggedIsTransWithProtoHandler(GateRef x)493 GateRef CircuitBuilder::TaggedIsTransWithProtoHandler(GateRef x)
494 {
495 return LogicAndBuilder(env_).And(TaggedIsHeapObject(x)).And(IsJsType(x, JSType::TRANS_WITH_PROTO_HANDLER)).Done();
496 }
497
TaggedIsUndefinedOrNull(GateRef x)498 GateRef CircuitBuilder::TaggedIsUndefinedOrNull(GateRef x)
499 {
500 x = ChangeTaggedPointerToInt64(x);
501 GateRef heapObjMask = Int64(JSTaggedValue::TAG_HEAPOBJECT_MASK);
502 GateRef tagSpecial = Int64(JSTaggedValue::TAG_SPECIAL);
503 GateRef andGate = Int64And(x, heapObjMask);
504 GateRef result = Equal(andGate, tagSpecial);
505 return result;
506 }
507
TaggedIsUndefinedOrNullOrHole(GateRef x)508 GateRef CircuitBuilder::TaggedIsUndefinedOrNullOrHole(GateRef x)
509 {
510 return BitOr(TaggedIsHole(x), TaggedIsUndefinedOrNull(x));
511 }
512
TaggedIsNotUndefinedAndNull(GateRef x)513 GateRef CircuitBuilder::TaggedIsNotUndefinedAndNull(GateRef x)
514 {
515 x = ChangeTaggedPointerToInt64(x);
516 GateRef heapObjMask = Int64(JSTaggedValue::TAG_HEAPOBJECT_MASK);
517 GateRef tagSpecial = Int64(JSTaggedValue::TAG_SPECIAL);
518 GateRef andGate = Int64And(x, heapObjMask);
519 GateRef result = NotEqual(andGate, tagSpecial);
520 return result;
521 }
522
TaggedIsNotUndefinedAndNullAndHole(GateRef x)523 GateRef CircuitBuilder::TaggedIsNotUndefinedAndNullAndHole(GateRef x)
524 {
525 return BitAnd(TaggedIsNotHole(x), TaggedIsNotUndefinedAndNull(x));
526 }
527
TaggedIsUndefinedOrHole(GateRef x)528 GateRef CircuitBuilder::TaggedIsUndefinedOrHole(GateRef x)
529 {
530 GateRef isUndefined = TaggedIsUndefined(x);
531 GateRef isHole = TaggedIsHole(x);
532 GateRef result = BitOr(isHole, isUndefined);
533 return result;
534 }
535
TaggedTrue()536 GateRef CircuitBuilder::TaggedTrue()
537 {
538 return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_TRUE, GateType::TaggedValue());
539 }
540
TaggedFalse()541 GateRef CircuitBuilder::TaggedFalse()
542 {
543 return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_FALSE, GateType::TaggedValue());
544 }
545
TaggedIsTrue(GateRef x)546 GateRef CircuitBuilder::TaggedIsTrue(GateRef x)
547 {
548 return Equal(x, TaggedTrue());
549 }
550
TaggedIsFalse(GateRef x)551 GateRef CircuitBuilder::TaggedIsFalse(GateRef x)
552 {
553 return Equal(x, TaggedFalse());
554 }
555
TaggedIsNull(GateRef x)556 GateRef CircuitBuilder::TaggedIsNull(GateRef x)
557 {
558 return Equal(x, NullConstant());
559 }
560
TaggedIsNotNull(GateRef x)561 GateRef CircuitBuilder::TaggedIsNotNull(GateRef x)
562 {
563 return NotEqual(x, NullConstant());
564 }
565
TaggedIsBoolean(GateRef x)566 GateRef CircuitBuilder::TaggedIsBoolean(GateRef x)
567 {
568 return BitOr(TaggedIsFalse(x), TaggedIsTrue(x));
569 }
570
TaggedIsNativePointer(GateRef x)571 GateRef CircuitBuilder::TaggedIsNativePointer(GateRef x)
572 {
573 return LogicAndBuilder(env_)
574 .And(TaggedIsHeapObject(x))
575 .And(IsJsType(x, JSType::JS_NATIVE_POINTER)).Done();
576 }
577
TaggedGetInt(GateRef x)578 GateRef CircuitBuilder::TaggedGetInt(GateRef x)
579 {
580 x = ChangeTaggedPointerToInt64(x);
581 return TruncInt64ToInt32(Int64And(x, Int64(~JSTaggedValue::TAG_MARK)));
582 }
583
TypedCallBuiltin(GateRef hirGate,const std::vector<GateRef> & args,BuiltinsStubCSigns::ID id,bool isSideEffect)584 inline GateRef CircuitBuilder::TypedCallBuiltin(GateRef hirGate, const std::vector<GateRef> &args,
585 BuiltinsStubCSigns::ID id, bool isSideEffect)
586 {
587 auto currentLabel = env_->GetCurrentLabel();
588 auto currentControl = currentLabel->GetControl();
589 auto currentDepend = currentLabel->GetDepend();
590
591 std::vector<GateRef> inList { currentControl, currentDepend };
592 inList.insert(inList.end(), args.begin(), args.end());
593 inList.push_back(Int16(static_cast<int16_t>(id)));
594 AppendFrameArgs(inList, hirGate);
595
596 auto builtinOp = TypedCallOperator(hirGate, MachineType::I64, inList, isSideEffect);
597 currentLabel->SetControl(builtinOp);
598 currentLabel->SetDepend(builtinOp);
599 return builtinOp;
600 }
601
602 template<TypedBinOp Op>
TypedBinaryOp(GateRef x,GateRef y,ParamType paramType)603 GateRef CircuitBuilder::TypedBinaryOp(GateRef x, GateRef y, ParamType paramType)
604 {
605 auto currentLabel = env_->GetCurrentLabel();
606 auto currentControl = currentLabel->GetControl();
607 auto currentDepend = currentLabel->GetDepend();
608 uint64_t value = TypedBinaryAccessor::ToValue(paramType, Op);
609 auto numberBinaryOp = GetCircuit()->NewGate(circuit_->TypedBinaryOp(value),
610 MachineType::I64, {currentControl, currentDepend, x, y}, GateType::AnyType());
611 currentLabel->SetControl(numberBinaryOp);
612 currentLabel->SetDepend(numberBinaryOp);
613 return numberBinaryOp;
614 }
615
616 template<TypedCallTargetCheckOp Op>
JSNoGCCallThisTargetTypeCheck(GateRef func,GateRef methodId,GateRef gate)617 GateRef CircuitBuilder::JSNoGCCallThisTargetTypeCheck(GateRef func, GateRef methodId, GateRef gate)
618 {
619 auto currentLabel = env_->GetCurrentLabel();
620 auto currentControl = currentLabel->GetControl();
621 auto currentDepend = currentLabel->GetDepend();
622 auto frameState = acc_.GetFrameState(gate);
623 uint64_t value = TypedCallTargetCheckAccessor::ToValue(Op);
624 GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(value), MachineType::I1,
625 {currentControl, currentDepend, func, methodId, frameState}, GateType::NJSValue());
626 currentLabel->SetControl(ret);
627 currentLabel->SetDepend(ret);
628 return ret;
629 }
630
631 template<TypedCallTargetCheckOp Op>
JSCallTargetTypeCheck(GateRef func,GateRef methodIndex,GateRef gate)632 GateRef CircuitBuilder::JSCallTargetTypeCheck(GateRef func, GateRef methodIndex, GateRef gate)
633 {
634 auto currentLabel = env_->GetCurrentLabel();
635 auto currentControl = currentLabel->GetControl();
636 auto currentDepend = currentLabel->GetDepend();
637 auto frameState = acc_.GetFrameState(gate);
638 uint64_t value = TypedCallTargetCheckAccessor::ToValue(Op);
639 GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(value), MachineType::I1,
640 {currentControl, currentDepend, func, methodIndex, frameState}, GateType::NJSValue());
641 currentLabel->SetControl(ret);
642 currentLabel->SetDepend(ret);
643 return ret;
644 }
645
646 template<TypedUnOp Op>
TypedUnaryOp(GateRef x,ParamType paramType)647 GateRef CircuitBuilder::TypedUnaryOp(GateRef x, ParamType paramType)
648 {
649 auto currentLabel = env_->GetCurrentLabel();
650 auto currentControl = currentLabel->GetControl();
651 auto currentDepend = currentLabel->GetDepend();
652 uint64_t value = TypedUnaryAccessor::ToValue(paramType, Op);
653 auto numberUnaryOp = GetCircuit()->NewGate(circuit_->TypedUnaryOp(value),
654 MachineType::I64, {currentControl, currentDepend, x}, GateType::AnyType());
655 currentLabel->SetControl(numberUnaryOp);
656 currentLabel->SetDepend(numberUnaryOp);
657 return numberUnaryOp;
658 }
659
660 template<TypedJumpOp Op>
TypedConditionJump(GateRef x,ParamType paramType,uint32_t weight)661 GateRef CircuitBuilder::TypedConditionJump(GateRef x, ParamType paramType, uint32_t weight)
662 {
663 auto currentLabel = env_->GetCurrentLabel();
664 auto currentControl = currentLabel->GetControl();
665 auto currentDepend = currentLabel->GetDepend();
666 auto machineType = MachineType::NOVALUE;
667 auto jumpOp = TypedConditionJump(machineType, Op, weight, paramType, {currentControl, currentDepend, x});
668 currentLabel->SetControl(jumpOp);
669 currentLabel->SetDepend(jumpOp);
670 return jumpOp;
671 }
672
673 template <TypedLoadOp Op>
LoadElement(GateRef receiver,GateRef index,OnHeapMode onHeap)674 GateRef CircuitBuilder::LoadElement(GateRef receiver, GateRef index, OnHeapMode onHeap)
675 {
676 auto currentLabel = env_->GetCurrentLabel();
677 auto currentControl = currentLabel->GetControl();
678 auto currentDepend = currentLabel->GetDepend();
679 LoadElementAccessor accessor(Op, onHeap);
680 auto ret = GetCircuit()->NewGate(GetCircuit()->LoadElement(accessor.ToValue()), MachineType::I64,
681 {currentControl, currentDepend, receiver, index}, GateType::AnyType());
682 currentLabel->SetControl(ret);
683 currentLabel->SetDepend(ret);
684 return ret;
685 }
686
687 template <TypedStoreOp Op>
StoreElement(GateRef receiver,GateRef index,GateRef value,OnHeapMode onHeap)688 GateRef CircuitBuilder::StoreElement(GateRef receiver, GateRef index, GateRef value, OnHeapMode onHeap)
689 {
690 auto currentLabel = env_->GetCurrentLabel();
691 auto currentControl = currentLabel->GetControl();
692 auto currentDepend = currentLabel->GetDepend();
693 StoreElementAccessor accessor(Op, onHeap);
694 auto ret = GetCircuit()->NewGate(GetCircuit()->StoreElement(accessor.ToValue()), MachineType::NOVALUE,
695 {currentControl, currentDepend, receiver, index, value}, GateType::AnyType());
696 currentLabel->SetControl(ret);
697 currentLabel->SetDepend(ret);
698 return ret;
699 }
700
PrimitiveToNumber(GateRef x,ParamType paramType)701 GateRef CircuitBuilder::PrimitiveToNumber(GateRef x, ParamType paramType)
702 {
703 auto currentLabel = env_->GetCurrentLabel();
704 auto currentControl = currentLabel->GetControl();
705 auto currentDepend = currentLabel->GetDepend();
706
707 auto numberconvert = TypeConvert(MachineType::I64, paramType, GateType::NumberType(),
708 {currentControl, currentDepend, x});
709 currentLabel->SetControl(numberconvert);
710 currentLabel->SetDepend(numberconvert);
711 return numberconvert;
712 }
713
LoadFromTaggedArray(GateRef array,size_t index)714 GateRef CircuitBuilder::LoadFromTaggedArray(GateRef array, size_t index)
715 {
716 auto dataOffset = TaggedArray::DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize();
717 return LoadConstOffset(VariableType::JS_ANY(), array, dataOffset);
718 }
719
StoreToTaggedArray(GateRef array,size_t index,GateRef value)720 GateRef CircuitBuilder::StoreToTaggedArray(GateRef array, size_t index, GateRef value)
721 {
722 auto dataOffset = TaggedArray::DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize();
723 return StoreConstOffset(VariableType::JS_ANY(), array, dataOffset, value);
724 }
725
TreeStringIsFlat(GateRef string)726 GateRef CircuitBuilder::TreeStringIsFlat(GateRef string)
727 {
728 GateRef second = GetSecondFromTreeString(string);
729 GateRef len = GetLengthFromString(second);
730 return Int32Equal(len, Int32(0));
731 }
732
GetFirstFromTreeString(GateRef string)733 GateRef CircuitBuilder::GetFirstFromTreeString(GateRef string)
734 {
735 GateRef offset = IntPtr(TreeEcmaString::FIRST_OFFSET);
736 return Load(VariableType::JS_POINTER(), string, offset);
737 }
738
GetSecondFromTreeString(GateRef string)739 GateRef CircuitBuilder::GetSecondFromTreeString(GateRef string)
740 {
741 GateRef offset = IntPtr(TreeEcmaString::SECOND_OFFSET);
742 return Load(VariableType::JS_POINTER(), string, offset);
743 }
744
GetValueFromTaggedArray(GateRef array,GateRef index)745 GateRef CircuitBuilder::GetValueFromTaggedArray(GateRef array, GateRef index)
746 {
747 GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
748 GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
749 return Load(VariableType::JS_ANY(), array, dataOffset);
750 }
751
GetValueFromTaggedArray(VariableType valType,GateRef array,GateRef index)752 GateRef CircuitBuilder::GetValueFromTaggedArray(VariableType valType, GateRef array, GateRef index)
753 {
754 GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
755 GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
756 return Load(valType, array, dataOffset);
757 }
758
GetValueFromJSArrayWithElementsKind(VariableType type,GateRef array,GateRef index)759 GateRef CircuitBuilder::GetValueFromJSArrayWithElementsKind(VariableType type, GateRef array, GateRef index)
760 {
761 GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
762 GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
763 return Load(type, array, dataOffset);
764 }
765
SetValueToTaggedArray(VariableType valType,GateRef glue,GateRef array,GateRef index,GateRef val)766 void CircuitBuilder::SetValueToTaggedArray(VariableType valType, GateRef glue,
767 GateRef array, GateRef index, GateRef val)
768 {
769 GateRef offset = PtrMul(ZExtInt32ToPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize()));
770 GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET));
771 Store(valType, glue, array, dataOffset, val);
772 }
773 }
774
775 #endif // ECMASCRIPT_COMPILER_MCR_CIRCUIT_BUILDER_H
776