• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &notString);
287         Bind(&notString);
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