• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #include "ecmascript/compiler/typed_hcr_lowering.h"
17 
18 #include "ecmascript/compiler/builtins_lowering.h"
19 #include "ecmascript/compiler/deopt_type.h"
20 #include "ecmascript/compiler/new_object_stub_builder.h"
21 #include "ecmascript/js_map.h"
22 #include "ecmascript/js_primitive_ref.h"
23 #include "ecmascript/linked_hash_table.h"
24 
25 namespace panda::ecmascript::kungfu {
VisitGate(GateRef gate)26 GateRef TypedHCRLowering::VisitGate(GateRef gate)
27 {
28     GateRef glue = glue_;
29     auto op = acc_.GetOpCode(gate);
30     [[maybe_unused]] auto scopedGate = circuit_->VisitGateBegin(gate);
31     switch (op) {
32         case OpCode::PRIMITIVE_TYPE_CHECK:
33             LowerPrimitiveTypeCheck(gate);
34             break;
35         case OpCode::BUILTIN_INSTANCE_HCLASS_CHECK:
36             LowerBuiltinInstanceHClassCheck(gate);
37             break;
38         case OpCode::BUILTIN_PROTOTYPE_HCLASS_CHECK:
39             LowerBuiltinPrototypeHClassCheck(gate);
40             break;
41         case OpCode::STABLE_ARRAY_CHECK:
42             LowerStableArrayCheck(glue, gate);
43             break;
44         case OpCode::TYPED_ARRAY_CHECK:
45             LowerTypedArrayCheck(glue, gate);
46             break;
47         case OpCode::ECMA_STRING_CHECK:
48             LowerEcmaStringCheck(gate, glue);
49             break;
50         case OpCode::INTERN_STRING_CHECK:
51             LowerInternStringCheck(gate, glue);
52             break;
53         case OpCode::STRING_KEY_CHECK:
54             LowerStringKeyCheck(gate, glue);
55             break;
56         case OpCode::INTERN_STRING_KEY_CHECK:
57             LowerInternStringKeyCheck(gate, glue);
58             break;
59         case OpCode::ECMA_MAP_CHECK:
60             LowerEcmaMapCheck(glue, gate);
61             break;
62         case OpCode::FLATTEN_TREE_STRING_CHECK:
63             LowerFlattenTreeStringCheck(gate, glue);
64             break;
65         case OpCode::LOAD_STRING_LENGTH:
66             LowerStringLength(gate);
67             break;
68         case OpCode::LOAD_MAP_SIZE:
69             LowerMapSize(gate);
70             break;
71         case OpCode::LOAD_TYPED_ARRAY_LENGTH:
72             LowerLoadTypedArrayLength(gate);
73             break;
74         case OpCode::OBJECT_TYPE_CHECK:
75             LowerObjectTypeCheck(glue, gate);
76             break;
77         case OpCode::RANGE_CHECK_PREDICATE:
78             LowerRangeCheckPredicate(gate);
79             break;
80         case OpCode::INDEX_CHECK:
81             LowerIndexCheck(gate);
82             break;
83         case OpCode::TYPED_CALLTARGETCHECK_OP:
84             LowerJSCallTargetCheck(gate, glue);
85             break;
86         case OpCode::CALL_TARGET_IS_COMPILED_CHECK:
87             LowerCallTargetIsCompiledCheck(gate);
88             break;
89         case OpCode::TYPED_CALL_CHECK:
90             LowerCallTargetCheck(gate);
91             break;
92         case OpCode::JSINLINETARGET_TYPE_CHECK:
93             LowerJSInlineTargetTypeCheck(gate, glue);
94             break;
95         case OpCode::JSINLINETARGET_HEAPCONSTANT_CHECK:
96             LowerJSInlineTargetHeapConstantCheck(gate);
97             break;
98         case OpCode::TYPE_CONVERT:
99             LowerTypeConvert(gate);
100             break;
101         case OpCode::LOAD_PROPERTY:
102             LowerLoadProperty(gate);
103             break;
104         case OpCode::CALL_PRIVATE_GETTER:
105             LowerCallPrivateGetter(gate, glue);
106             break;
107         case OpCode::CALL_PRIVATE_SETTER:
108             LowerCallPrivateSetter(gate, glue);
109             break;
110         case OpCode::CALL_GETTER:
111             LowerCallGetter(gate, glue);
112             break;
113         case OpCode::STORE_PROPERTY:
114         case OpCode::STORE_PROPERTY_NO_BARRIER:
115             LowerStoreProperty(gate);
116             break;
117         case OpCode::CALL_SETTER:
118             LowerCallSetter(gate, glue);
119             break;
120         case OpCode::LOAD_ARRAY_LENGTH:
121             LowerLoadArrayLength(gate);
122             break;
123         case OpCode::LOAD_ELEMENT:
124             LowerLoadElement(gate, glue);
125             break;
126         case OpCode::STORE_ELEMENT:
127             LowerStoreElement(gate, glue);
128             break;
129         case OpCode::TYPED_CALL_BUILTIN:
130         case OpCode::TYPED_CALL_BUILTIN_SIDE_EFFECT:
131             LowerTypedCallBuitin(gate);
132             break;
133         case OpCode::TYPED_NEW_ALLOCATE_THIS:
134             LowerTypedNewAllocateThis(gate, glue);
135             break;
136         case OpCode::TYPED_SUPER_ALLOCATE_THIS:
137             LowerTypedSuperAllocateThis(gate, glue);
138             break;
139         case OpCode::GET_SUPER_CONSTRUCTOR:
140             LowerGetSuperConstructor(glue, gate);
141             break;
142         case OpCode::COW_ARRAY_CHECK:
143             LowerCowArrayCheck(gate, glue);
144             break;
145         case OpCode::LOOK_UP_HOLDER:
146             LowerLookupHolder(glue, gate);
147             break;
148         case OpCode::LOAD_GETTER:
149             LowerLoadGetter(gate, glue);
150             break;
151         case OpCode::LOAD_SETTER:
152             LowerLoadSetter(gate, glue);
153             break;
154         case OpCode::PROTOTYPE_CHECK:
155             LowerPrototypeCheck(glue, gate);
156             break;
157         case OpCode::STRING_EQUAL:
158             LowerStringEqual(gate, glue);
159             break;
160         case OpCode::TYPE_OF_CHECK:
161             LowerTypeOfCheck(gate);
162             break;
163         case OpCode::TYPE_OF:
164             LowerTypeOf(gate, glue);
165             break;
166         case OpCode::TYPED_CONSTRUCTOR_CHECK:
167             LowerTypedConstructorCheck(gate, glue);
168             break;
169         case OpCode::ARRAY_CONSTRUCTOR_CHECK:
170             LowerArrayConstructorCheck(gate, glue);
171             break;
172         case OpCode::ARRAY_CONSTRUCTOR:
173             LowerArrayConstructor(gate, glue);
174             break;
175         case OpCode::FLOAT32_ARRAY_CONSTRUCTOR_CHECK:
176             LowerFloat32ArrayConstructorCheck(gate, glue);
177             break;
178         case OpCode::FLOAT32_ARRAY_CONSTRUCTOR:
179             LowerFloat32ArrayConstructor(gate, glue);
180             break;
181         case OpCode::LOAD_BUILTIN_OBJECT:
182             LowerLoadBuiltinObject(gate);
183             break;
184         case OpCode::OBJECT_CONSTRUCTOR_CHECK:
185             LowerObjectConstructorCheck(gate, glue);
186             break;
187         case OpCode::OBJECT_CONSTRUCTOR:
188             LowerObjectConstructor(gate, glue);
189             break;
190         case OpCode::BOOLEAN_CONSTRUCTOR_CHECK:
191             LowerBooleanConstructorCheck(gate, glue);
192             break;
193         case OpCode::BOOLEAN_CONSTRUCTOR:
194             LowerBooleanConstructor(gate, glue);
195             break;
196         case OpCode::ORDINARY_HAS_INSTANCE:
197             if (compilationEnv_->IsJitCompiler()) {
198                 LowerOrdinaryHasInstanceForJIT(gate, glue);
199             } else {
200                 LowerOrdinaryHasInstance(gate, glue);
201             }
202             break;
203         case OpCode::PROTO_CHANGE_MARKER_CHECK:
204             LowerProtoChangeMarkerCheck(glue, gate);
205             break;
206         case OpCode::PRIMTYPE_PROTO_CHANGE_MARKER_CHECK:
207             LowerPrimitiveTypeProtoChangeMarkerCheck(glue, gate);
208             break;
209         case OpCode::MONO_CALL_GETTER_ON_PROTO:
210             LowerMonoCallGetterOnProto(gate, glue);
211             break;
212         case OpCode::MONO_LOAD_PROPERTY_ON_PROTO:
213             LowerMonoLoadPropertyOnProto(glue, gate);
214             break;
215         case OpCode::MONO_STORE_PROPERTY_LOOK_UP_PROTO:
216             LowerMonoStorePropertyLookUpProto(gate, glue);
217             break;
218         case OpCode::MONO_STORE_PROPERTY:
219             LowerMonoStoreProperty(gate, glue);
220             break;
221         case OpCode::TYPED_CREATE_OBJ_WITH_BUFFER:
222             LowerTypedCreateObjWithBuffer(gate, glue);
223             break;
224         case OpCode::STRING_FROM_SINGLE_CHAR_CODE:
225             LowerStringFromSingleCharCode(gate, glue);
226             break;
227         case OpCode::MIGRATE_ARRAY_WITH_KIND:
228             LowerMigrateArrayWithKind(gate, glue);
229             break;
230         case OpCode::NUMBER_TO_STRING:
231             LowerNumberToString(gate, glue);
232             break;
233         case OpCode::ECMA_OBJECT_CHECK:
234             LowerEcmaObjectCheck(gate);
235             break;
236         case OpCode::ELEMENTSKIND_CHECK:
237             LowerElementskindCheck(glue, gate);
238             break;
239         case OpCode::INLINE_SUPER_CTOR_CHECK:
240             LowerInlineSuperCtorCheck(glue, gate);
241             break;
242         case OpCode::CHECK_CONSTRUCTOR:
243             LowerCheckConstructor(gate, glue);
244             break;
245         default:
246             break;
247     }
248     return Circuit::NullGate();
249 }
250 
LowerJSCallTargetCheck(GateRef gate,GateRef glue)251 void TypedHCRLowering::LowerJSCallTargetCheck(GateRef gate, GateRef glue)
252 {
253     TypedCallTargetCheckOp Op = acc_.GetTypedCallTargetCheckOp(gate);
254     switch (Op) {
255         case TypedCallTargetCheckOp::JSCALL: {
256             LowerJSCallTargetTypeCheck(gate, glue);
257             break;
258         }
259         case TypedCallTargetCheckOp::JSCALL_FAST: {
260             LowerJSFastCallTargetTypeCheck(gate, glue);
261             break;
262         }
263         case TypedCallTargetCheckOp::JSCALLTHIS: {
264             LowerJSCallThisTargetTypeCheck(gate, glue);
265             break;
266         }
267         case TypedCallTargetCheckOp::JSCALLTHIS_FAST: {
268             LowerJSFastCallThisTargetTypeCheck(gate, glue);
269             break;
270         }
271         case TypedCallTargetCheckOp::JSCALLTHIS_NOGC: {
272             LowerJSNoGCCallThisTargetTypeCheck(gate, glue);
273             break;
274         }
275         case TypedCallTargetCheckOp::JSCALLTHIS_FAST_NOGC: {
276             LowerJSNoGCFastCallThisTargetTypeCheck(gate, glue);
277             break;
278         }
279         case TypedCallTargetCheckOp::JS_NEWOBJRANGE: {
280             LowerJSNewObjRangeCallTargetCheck(gate, glue);
281             break;
282         }
283         default:
284             LOG_ECMA(FATAL) << "this branch is unreachable";
285             UNREACHABLE();
286     }
287 }
288 
LowerPrimitiveTypeCheck(GateRef gate)289 void TypedHCRLowering::LowerPrimitiveTypeCheck(GateRef gate)
290 {
291     Environment env(gate, circuit_, &builder_);
292     auto type = acc_.GetParamGateType(gate);
293     if (type.IsIntType()) {
294         LowerIntCheck(gate);
295     } else if (type.IsDoubleType()) {
296         LowerDoubleCheck(gate);
297     } else if (type.IsNumberType()) {
298         LowerNumberCheck(gate);
299     } else if (type.IsBooleanType()) {
300         LowerBooleanCheck(gate);
301     } else {
302         LOG_ECMA(FATAL) << "this branch is unreachable";
303         UNREACHABLE();
304     }
305 }
306 
LowerIntCheck(GateRef gate)307 void TypedHCRLowering::LowerIntCheck(GateRef gate)
308 {
309     GateRef frameState = GetFrameState(gate);
310 
311     GateRef value = acc_.GetValueIn(gate, 0);
312     GateRef typeCheck = builder_.TaggedIsInt(value);
313     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTINT6);
314 
315     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
316 }
317 
LowerDoubleCheck(GateRef gate)318 void TypedHCRLowering::LowerDoubleCheck(GateRef gate)
319 {
320     GateRef frameState = GetFrameState(gate);
321 
322     GateRef value = acc_.GetValueIn(gate, 0);
323     GateRef typeCheck = builder_.TaggedIsDouble(value);
324     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTDOUBLE3);
325 
326     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
327 }
328 
LowerNumberCheck(GateRef gate)329 void TypedHCRLowering::LowerNumberCheck(GateRef gate)
330 {
331     GateRef frameState = GetFrameState(gate);
332 
333     GateRef value = acc_.GetValueIn(gate, 0);
334     GateRef typeCheck = builder_.TaggedIsNumber(value);
335     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTNUMBER2);
336 
337     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
338 }
339 
LowerBooleanCheck(GateRef gate)340 void TypedHCRLowering::LowerBooleanCheck(GateRef gate)
341 {
342     GateRef frameState = GetFrameState(gate);
343 
344     GateRef value = acc_.GetValueIn(gate, 0);
345     GateRef typeCheck = builder_.TaggedIsBoolean(value);
346     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTBOOL2);
347 
348     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
349 }
350 
LowerStableArrayCheck(GateRef glue,GateRef gate)351 void TypedHCRLowering::LowerStableArrayCheck(GateRef glue, GateRef gate)
352 {
353     Environment env(gate, circuit_, &builder_);
354     GateRef frameState = GetFrameState(gate);
355 
356     GateRef receiver = acc_.GetValueIn(gate, 0);
357     builder_.HeapObjectCheck(receiver, frameState);
358 
359     GateRef receiverHClass = builder_.LoadHClassByConstOffset(glue, receiver);
360     ArrayMetaDataAccessor accessor = acc_.GetArrayMetaDataAccessor(gate);
361     builder_.HClassStableArrayCheck(receiverHClass, frameState, accessor);
362     builder_.ArrayGuardianCheck(frameState);
363 
364     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
365 }
366 
SetDeoptTypeInfo(JSType jstype,DeoptType & type,size_t & typedArrayRootHclassIndex,size_t & typedArrayRootHclassOnHeapIndex)367 void TypedHCRLowering::SetDeoptTypeInfo(JSType jstype, DeoptType &type, size_t &typedArrayRootHclassIndex,
368     size_t &typedArrayRootHclassOnHeapIndex)
369 {
370     type = DeoptType::NOTARRAY1;
371     switch (jstype) {
372         case JSType::JS_INT8_ARRAY:
373             typedArrayRootHclassIndex = GlobalEnv::INT8_ARRAY_ROOT_HCLASS_INDEX;
374             typedArrayRootHclassOnHeapIndex = GlobalEnv::INT8_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
375             break;
376         case JSType::JS_UINT8_ARRAY:
377             typedArrayRootHclassIndex = GlobalEnv::UINT8_ARRAY_ROOT_HCLASS_INDEX;
378             typedArrayRootHclassOnHeapIndex = GlobalEnv::UINT8_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
379             break;
380         case JSType::JS_UINT8_CLAMPED_ARRAY:
381             typedArrayRootHclassIndex = GlobalEnv::UINT8_CLAMPED_ARRAY_ROOT_HCLASS_INDEX;
382             typedArrayRootHclassOnHeapIndex = GlobalEnv::UINT8_CLAMPED_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
383             break;
384         case JSType::JS_INT16_ARRAY:
385             typedArrayRootHclassIndex = GlobalEnv::INT16_ARRAY_ROOT_HCLASS_INDEX;
386             typedArrayRootHclassOnHeapIndex = GlobalEnv::INT16_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
387             break;
388         case JSType::JS_UINT16_ARRAY:
389             typedArrayRootHclassIndex = GlobalEnv::UINT16_ARRAY_ROOT_HCLASS_INDEX;
390             typedArrayRootHclassOnHeapIndex = GlobalEnv::UINT16_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
391             break;
392         case JSType::JS_INT32_ARRAY:
393             typedArrayRootHclassIndex = GlobalEnv::INT32_ARRAY_ROOT_HCLASS_INDEX;
394             typedArrayRootHclassOnHeapIndex = GlobalEnv::INT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
395             break;
396         case JSType::JS_UINT32_ARRAY:
397             typedArrayRootHclassIndex = GlobalEnv::UINT32_ARRAY_ROOT_HCLASS_INDEX;
398             typedArrayRootHclassOnHeapIndex = GlobalEnv::UINT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
399             break;
400         case JSType::JS_FLOAT32_ARRAY:
401             typedArrayRootHclassIndex = GlobalEnv::FLOAT32_ARRAY_ROOT_HCLASS_INDEX;
402             typedArrayRootHclassOnHeapIndex = GlobalEnv::FLOAT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
403             break;
404         case JSType::JS_FLOAT64_ARRAY:
405             typedArrayRootHclassIndex = GlobalEnv::FLOAT64_ARRAY_ROOT_HCLASS_INDEX;
406             typedArrayRootHclassOnHeapIndex = GlobalEnv::FLOAT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
407             break;
408         case JSType::JS_BIGINT64_ARRAY:
409             typedArrayRootHclassIndex = GlobalEnv::BIGINT64_ARRAY_ROOT_HCLASS_INDEX;
410             typedArrayRootHclassOnHeapIndex = GlobalEnv::BIGINT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
411             break;
412         case JSType::JS_BIGUINT64_ARRAY:
413             typedArrayRootHclassIndex = GlobalEnv::BIGUINT64_ARRAY_ROOT_HCLASS_INDEX;
414             typedArrayRootHclassOnHeapIndex = GlobalEnv::BIGUINT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
415             break;
416         default:
417             LOG_ECMA(FATAL) << "this branch is unreachable";
418             UNREACHABLE();
419     }
420 }
421 
LowerTypedArrayCheck(GateRef glue,GateRef gate)422 void TypedHCRLowering::LowerTypedArrayCheck(GateRef glue, GateRef gate)
423 {
424     Environment env(gate, circuit_, &builder_);
425     TypedArrayMetaDataAccessor accessor = acc_.GetTypedArrayMetaDataAccessor(gate);
426     size_t typedArrayRootHclassIndex = GlobalEnv::INT8_ARRAY_ROOT_HCLASS_INDEX;
427     size_t typedArrayRootHclassOnHeapIndex = GlobalEnv::INT8_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
428     auto deoptType = DeoptType::NONE;
429     ParamType paramType = accessor.GetParamType();
430     ASSERT(paramType.IsBuiltinType());
431     auto builtinType = paramType.GetBuiltinType();
432     SetDeoptTypeInfo(static_cast<JSType>(builtinType), deoptType, typedArrayRootHclassIndex,
433                      typedArrayRootHclassOnHeapIndex);
434 
435     GateRef frameState = GetFrameState(gate);
436     GateRef globalEnv = circuit_->GetGlobalEnvCache();
437     GateRef receiver = acc_.GetValueIn(gate, 0);
438     builder_.HeapObjectCheck(receiver, frameState);
439     GateRef receiverHClass = builder_.LoadHClassByConstOffset(glue, receiver);
440 
441     OnHeapMode onHeapMode = accessor.GetOnHeapMode();
442     if (OnHeap::IsOnHeap(onHeapMode)) {
443         GateRef rootOnHeapHclass = builder_.GetGlobalEnvObj(globalEnv, typedArrayRootHclassOnHeapIndex);
444         GateRef check = builder_.Equal(receiverHClass, rootOnHeapHclass);
445         builder_.DeoptCheck(check, frameState, deoptType);
446     } else if (OnHeap::IsNotOnHeap(onHeapMode)) {
447         GateRef rootHclass = builder_.GetGlobalEnvObj(globalEnv, typedArrayRootHclassIndex);
448         GateRef check = builder_.Equal(receiverHClass, rootHclass);
449         builder_.DeoptCheck(check, frameState, deoptType);
450     } else {
451         GateRef rootHclass = builder_.GetGlobalEnvObj(globalEnv, typedArrayRootHclassIndex);
452         GateRef rootOnHeapHclass = builder_.GetGlobalEnvObj(globalEnv, typedArrayRootHclassOnHeapIndex);
453         GateRef check1 = builder_.Equal(receiverHClass, rootHclass);
454         GateRef check2 = builder_.Equal(receiverHClass, rootOnHeapHclass);
455         builder_.DeoptCheck(builder_.BitOr(check1, check2), frameState, deoptType);
456     }
457     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
458 }
459 
LowerInternStringKeyCheck(GateRef gate,GateRef glue)460 void TypedHCRLowering::LowerInternStringKeyCheck(GateRef gate, GateRef glue)
461 {
462     Environment env(gate, circuit_, &builder_);
463     GateRef frameState = GetFrameState(gate);
464     GateRef key = acc_.GetValueIn(gate, 0);
465     GateRef value = acc_.GetValueIn(gate, 1);
466     builder_.HeapObjectCheck(key, frameState);
467     GateRef isString = builder_.TaggedObjectIsString(glue, key, compilationEnv_);
468     builder_.DeoptCheck(isString, frameState, DeoptType::NOTSTRING1);
469     GateRef isInternString = builder_.IsInternString(key);
470     builder_.DeoptCheck(isInternString, frameState, DeoptType::NOTINTERNSTRING1);
471     GateRef isEqual = builder_.Equal(value, key);
472     builder_.DeoptCheck(isEqual, frameState, DeoptType::KEYMISSMATCH);
473     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
474 }
475 
LowerStringKeyCheck(GateRef gate,GateRef glue)476 void TypedHCRLowering::LowerStringKeyCheck(GateRef gate, GateRef glue)
477 {
478     Environment env(gate, circuit_, &builder_);
479     GateRef frameState = GetFrameState(gate);
480     GateRef key = acc_.GetValueIn(gate, 0);
481     GateRef value = acc_.GetValueIn(gate, 1);
482     builder_.DeoptCheck(builder_.TaggedIsString(glue, key), frameState, DeoptType::NOTSTRING1);
483     builder_.DeoptCheck(builder_.StringEqual(key, value),
484                         frameState, DeoptType::KEYMISSMATCH);
485     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
486 }
487 
LowerEcmaStringCheck(GateRef gate,GateRef glue)488 void TypedHCRLowering::LowerEcmaStringCheck(GateRef gate, GateRef glue)
489 {
490     Environment env(gate, circuit_, &builder_);
491     GateRef frameState = GetFrameState(gate);
492     GateRef receiver = acc_.GetValueIn(gate, 0);
493     builder_.HeapObjectCheck(receiver, frameState);
494     GateRef isString = builder_.TaggedObjectIsString(glue, receiver, compilationEnv_);
495     builder_.DeoptCheck(isString, frameState, DeoptType::NOTSTRING1);
496 
497     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
498 }
499 
LowerInternStringCheck(GateRef gate,GateRef glue)500 void TypedHCRLowering::LowerInternStringCheck(GateRef gate, GateRef glue)
501 {
502     Environment env(gate, circuit_, &builder_);
503     GateRef frameState = GetFrameState(gate);
504     GateRef receiver = acc_.GetValueIn(gate, 0);
505     builder_.HeapObjectCheck(receiver, frameState);
506     GateRef isString = builder_.TaggedObjectIsString(glue, receiver, compilationEnv_);
507     builder_.DeoptCheck(isString, frameState, DeoptType::NOTSTRING1);
508     GateRef isInternString = builder_.IsInternString(receiver);
509     builder_.DeoptCheck(isInternString, frameState, DeoptType::NOTINTERNSTRING1);
510     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
511 }
512 
LowerEcmaMapCheck(GateRef glue,GateRef gate)513 void TypedHCRLowering::LowerEcmaMapCheck(GateRef glue, GateRef gate)
514 {
515     Environment env(gate, circuit_, &builder_);
516     GateRef frameState = GetFrameState(gate);
517     GateRef receiver = acc_.GetValueIn(gate, 0);
518     builder_.HeapObjectCheck(receiver, frameState);
519 
520     GateRef hclass = builder_.LoadHClassByConstOffset(glue, receiver);
521 
522     size_t mapHclassIndex = GlobalEnv::MAP_CLASS_INDEX;
523     GateRef globalEnv = circuit_->GetGlobalEnvCache();
524     GateRef mapHclass = builder_.GetGlobalEnvObj(globalEnv, mapHclassIndex);
525     GateRef isMap = builder_.Equal(hclass, mapHclass, "Check HClass");
526 
527     builder_.DeoptCheck(isMap, frameState, DeoptType::ISNOTMAP);
528     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
529 }
530 
LowerFlattenTreeStringCheck(GateRef gate,GateRef glue)531 void TypedHCRLowering::LowerFlattenTreeStringCheck(GateRef gate, GateRef glue)
532 {
533     Environment env(gate, circuit_, &builder_);
534     GateRef str = acc_.GetValueIn(gate, 0);
535     DEFVALUE(result, (&builder_), VariableType::JS_POINTER(), str);
536     Label isTreeString(&builder_);
537     Label exit(&builder_);
538 
539     BRANCH_CIR(builder_.IsTreeString(glue, str), &isTreeString, &exit);
540     builder_.Bind(&isTreeString);
541     {
542         Label isFlat(&builder_);
543         Label needFlat(&builder_);
544         BRANCH_CIR(builder_.TreeStringIsFlat(glue, str), &isFlat, &needFlat);
545         builder_.Bind(&isFlat);
546         {
547             result = builder_.GetFirstFromTreeString(glue, str);
548             builder_.Jump(&exit);
549         }
550         builder_.Bind(&needFlat);
551         {
552             result = LowerCallRuntime(glue, gate, RTSTUB_ID(SlowFlattenString), { str }, true);
553             builder_.Jump(&exit);
554         }
555     }
556 
557     builder_.Bind(&exit);
558     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
559 }
560 
GetLengthFromString(GateRef gate)561 GateRef TypedHCRLowering::GetLengthFromString(GateRef gate)
562 {
563     GateRef shiftCount = builder_.Int32(BaseString::LengthBits::START_BIT);
564     return builder_.Int32LSR(
565         builder_.LoadConstOffset(VariableType::INT32(), gate, BaseString::LENGTH_AND_FLAGS_OFFSET), shiftCount);
566 }
567 
LowerStringLength(GateRef gate)568 void TypedHCRLowering::LowerStringLength(GateRef gate)
569 {
570     Environment env(gate, circuit_, &builder_);
571     GateRef receiver = acc_.GetValueIn(gate, 0);
572     GateRef length = GetLengthFromString(receiver);
573 
574     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), length);
575 }
576 
LowerMapSize(GateRef gate)577 void TypedHCRLowering::LowerMapSize(GateRef gate)
578 {
579     Environment env(gate, circuit_, &builder_);
580     GateRef receiver = acc_.GetValueIn(gate, 0);
581 
582     GateRef linkedMap = builder_.LoadConstOffset(VariableType::JS_ANY(), receiver, JSMap::LINKED_MAP_OFFSET);
583     GateRef mapSizeTagged = builder_.LoadFromTaggedArray(linkedMap, LinkedHashMap::NUMBER_OF_ELEMENTS_INDEX);
584     GateRef mapSize = builder_.TaggedGetInt(mapSizeTagged);
585 
586     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), mapSize);
587 }
588 
LowerLoadTypedArrayLength(GateRef gate)589 void TypedHCRLowering::LowerLoadTypedArrayLength(GateRef gate)
590 {
591     Environment env(gate, circuit_, &builder_);
592     GateRef receiver = acc_.GetValueIn(gate, 0);
593     GateRef length = builder_.LoadConstOffset(VariableType::INT32(), receiver, JSTypedArray::ARRAY_LENGTH_OFFSET);
594     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), length);
595 }
596 
LowerObjectTypeCheck(GateRef glue,GateRef gate)597 void TypedHCRLowering::LowerObjectTypeCheck(GateRef glue, GateRef gate)
598 {
599     Environment env(gate, circuit_, &builder_);
600     size_t typeCount = acc_.GetNumValueIn(gate) - 1;
601     if (typeCount == 1) {
602         GateRef frameState = GetFrameState(gate);
603         GateRef compare = BuildCompareHClass(glue, gate, frameState);
604         builder_.DeoptCheck(compare, frameState, DeoptType::INCONSISTENTHCLASS6);
605         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
606         return;
607     }
608     LowerSimpleHClassCheck(glue, gate);
609 }
610 
BuildCompareHClass(GateRef glue,GateRef gate,GateRef frameState)611 GateRef TypedHCRLowering::BuildCompareHClass(GateRef glue, GateRef gate, GateRef frameState)
612 {
613     GateRef receiver = acc_.GetValueIn(gate, 0);
614     bool isHeapObject = acc_.GetObjectTypeAccessor(gate).IsHeapObject();
615     if (!isHeapObject) {
616         builder_.HeapObjectCheck(receiver, frameState);
617     }
618     GateRef aotHCIndex = acc_.GetValueIn(gate, 1);
619     auto hclassIndex = acc_.GetConstantValue(aotHCIndex);
620     ArgumentAccessor *argAcc = circuit_->GetArgumentAccessor();
621     GateRef unsharedConstPool = argAcc->GetFrameArgsIn(frameState, FrameArgIdx::UNSHARED_CONST_POOL);
622     GateRef aotHCGate = builder_.LoadHClassFromConstpool(unsharedConstPool, hclassIndex);
623     GateRef receiverHClass = builder_.LoadHClassByConstOffset(glue, receiver);
624     return builder_.Equal(aotHCGate, receiverHClass, "checkHClass");
625 }
626 
LowerSimpleHClassCheck(GateRef glue,GateRef gate)627 void TypedHCRLowering::LowerSimpleHClassCheck(GateRef glue, GateRef gate)
628 {
629     GateRef frameState = GetFrameState(gate);
630     GateRef receiver = acc_.GetValueIn(gate, 0);
631     bool isHeapObject = acc_.GetObjectTypeAccessor(gate).IsHeapObject();
632     if (!isHeapObject) {
633         builder_.HeapObjectCheck(receiver, frameState);
634     }
635     DEFVALUE(result, (&builder_), VariableType::BOOL(), builder_.Boolean(false));
636     ArgumentAccessor *argAcc = circuit_->GetArgumentAccessor();
637     GateRef unsharedConstPool = argAcc->GetFrameArgsIn(frameState, FrameArgIdx::UNSHARED_CONST_POOL);
638     GateRef receiverHClass = builder_.LoadHClassByConstOffset(glue, receiver);
639     std::vector<Label> ifFalse;
640     Label resultIsTrue(&builder_);
641     Label resultIsFalse(&builder_);
642     Label exit(&builder_);
643     size_t typeCount = acc_.GetNumValueIn(gate) - 1;
644     ASSERT(typeCount > 0);
645     for (size_t i = 0; i < typeCount - 1; i++) {
646         ifFalse.emplace_back(Label(&builder_));
647     }
648     for (size_t i = 0; i < typeCount; i++) {
649         GateRef aotHCIndex = acc_.GetValueIn(gate, i + 1);
650         auto hclassIndex = acc_.GetConstantValue(aotHCIndex);
651         GateRef aotHCGate = builder_.LoadHClassFromConstpool(unsharedConstPool, hclassIndex);
652 
653         if (i != typeCount - 1) {
654             BRANCH_CIR(builder_.Equal(receiverHClass, aotHCGate), &resultIsTrue, &ifFalse[i]);
655             builder_.Bind(&ifFalse[i]);
656         } else {
657             BRANCH_CIR(builder_.Equal(receiverHClass, aotHCGate), &resultIsTrue, &resultIsFalse);
658         }
659     }
660     builder_.Bind(&resultIsFalse);
661     {
662         result = builder_.Boolean(false);
663         builder_.Jump(&exit);
664     }
665     builder_.Bind(&resultIsTrue);
666     {
667         result = builder_.Boolean(true);
668         builder_.Jump(&exit);
669     }
670     builder_.Bind(&exit);
671     auto finalResult = *result;
672     builder_.DeoptCheck(finalResult, frameState, DeoptType::INCONSISTENTHCLASS6);
673     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
674 }
675 
LowerRangeCheckPredicate(GateRef gate)676 void TypedHCRLowering::LowerRangeCheckPredicate(GateRef gate)
677 {
678     Environment env(gate, circuit_, &builder_);
679     auto deoptType = DeoptType::NOTARRAY1;
680     GateRef frameState = GetFrameState(gate);
681     GateRef x = acc_.GetValueIn(gate, 0);
682     GateRef y = acc_.GetValueIn(gate, 1);
683     TypedBinaryAccessor accessor = acc_.GetTypedBinaryAccessor(gate);
684     TypedBinOp cond = accessor.GetTypedBinOp();
685     GateRef check = Circuit::NullGate();
686     // check the condition
687     switch (cond) {
688         case TypedBinOp::TYPED_GREATER:
689             check = builder_.Int32GreaterThan(x, y);
690             break;
691         case TypedBinOp::TYPED_GREATEREQ:
692             check = builder_.Int32GreaterThanOrEqual(x, y);
693             break;
694         case TypedBinOp::TYPED_LESS:
695             check = builder_.Int32LessThan(x, y);
696             break;
697         case TypedBinOp::TYPED_LESSEQ:
698             check = builder_.Int32LessThanOrEqual(x, y);
699             break;
700         default:
701             UNREACHABLE();
702             break;
703     }
704     builder_.DeoptCheck(check, frameState, deoptType);
705     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
706 }
707 
BuiltinInstanceHClassCheck(Environment * env,GateRef gate)708 void TypedHCRLowering::BuiltinInstanceHClassCheck(Environment *env, GateRef gate)
709 {
710     BuiltinPrototypeHClassAccessor accessor = acc_.GetBuiltinHClassAccessor(gate);
711     BuiltinTypeId type = accessor.GetBuiltinTypeId();
712     ElementsKind kind = accessor.GetElementsKind();
713     GateRef frameState = GetFrameState(gate);
714     GateRef glue = glue_;
715     GateRef receiver = acc_.GetValueIn(gate, 0);
716     GateRef ihcMatches = Circuit::NullGate();
717     if (type == BuiltinTypeId::ARRAY) {
718         if (Elements::IsGeneric(kind)) {
719             auto index = compilationEnv_->GetArrayHClassIndex(kind, false);
720             auto protoIndex = compilationEnv_->GetArrayHClassIndex(kind, true);
721             GateRef receiverHClass = builder_.LoadHClassByConstOffset(glue, receiver);
722             // If the Elements kind is Generic, hclass comparison is required. Other kinds can ensure that hclass has
723             // not been modified.
724             GateRef globalEnv = circuit_->GetGlobalEnvCache();
725             ihcMatches = LogicOrBuilder(env)
726                 .Or(builder_.Equal(receiverHClass,
727                                    builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
728                                                               static_cast<size_t>(index))))
729                 .Or(builder_.Equal(receiverHClass,
730                                    builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
731                                                               static_cast<size_t>(protoIndex))))
732                 .Done();
733             GateRef elementsKind = builder_.GetElementsKindByHClass(receiverHClass);
734             ihcMatches = LogicOrBuilder(env)
735                 .Or(ihcMatches)
736                 .Or(builder_.NotEqual(elementsKind, builder_.Int32(Elements::ToUint(ElementsKind::GENERIC))))
737                 .Done();
738         } else {
739             GateRef receiverHClass = builder_.LoadHClassByConstOffset(glue, receiver);
740             GateRef elementsKind = builder_.GetElementsKindByHClass(receiverHClass);
741             ihcMatches =
742                 builder_.NotEqual(elementsKind, builder_.Int32(Elements::ToUint(ElementsKind::GENERIC)));
743         }
744     } else {
745         size_t ihcOffset = JSThread::GlueData::GetBuiltinInstanceHClassOffset(type, env->IsArch32Bit());
746         GateRef initialIhcAddress = builder_.LoadConstOffset(VariableType::JS_POINTER(), glue, ihcOffset);
747         GateRef receiverHClass = builder_.LoadHClassByConstOffset(glue, receiver);
748         if (IsTypedArrayType(type)) {
749              // check IHC onHeap hclass
750             size_t ihcOnHeapOffset = JSThread::GlueData::GetBuiltinExtraHClassOffset(type, env->IsArch32Bit());
751             ihcMatches = LogicOrBuilder(env)
752                 .Or(builder_.Equal(receiverHClass, initialIhcAddress))
753                 .Or(builder_.Equal(receiverHClass,
754                                    builder_.LoadConstOffset(VariableType::JS_POINTER(), glue, ihcOnHeapOffset)))
755                 .Done();
756         } else {
757             ihcMatches = builder_.Equal(receiverHClass, initialIhcAddress);
758         }
759     }
760     // De-opt if HClass of x changed where X is the current builtin object.
761     builder_.DeoptCheck(ihcMatches, frameState, DeoptType::BUILTININSTANCEHCLASSMISMATCH);
762 }
763 
BuiltinPrototypeHClassCheck(Environment * env,GateRef gate)764 void TypedHCRLowering::BuiltinPrototypeHClassCheck(Environment *env, GateRef gate)
765 {
766     BuiltinPrototypeHClassAccessor accessor = acc_.GetBuiltinHClassAccessor(gate);
767     BuiltinTypeId type = accessor.GetBuiltinTypeId();
768     bool isPrototypeOfPrototype = accessor.IsPrototypeOfPrototype();
769     GateRef frameState = GetFrameState(gate);
770     GateRef glue = glue_;
771     GateRef receiver = acc_.GetValueIn(gate, 0);
772     // Only HClasses recorded in the JSThread during builtin initialization are available
773     [[maybe_unused]] JSHClass *initialPrototypeHClass = compilationEnv_->GetBuiltinPrototypeHClass(type);
774     ASSERT(initialPrototypeHClass != nullptr);
775 
776     // Phc = PrototypeHClass
777     size_t phcOffset = JSThread::GlueData::GetBuiltinPrototypeHClassOffset(type, env->IsArch32Bit());
778     GateRef receiverPhcAddress = builder_.LoadPrototypeHClass(glue, receiver);
779     GateRef initialPhcAddress = builder_.LoadConstOffset(VariableType::JS_POINTER(), glue, phcOffset);
780     GateRef phcMatches = builder_.Equal(receiverPhcAddress, initialPhcAddress);
781     // De-opt if HClass of X.prototype changed where X is the current builtin object.
782     builder_.DeoptCheck(phcMatches, frameState, DeoptType::BUILTINPROTOHCLASSMISMATCH1);
783 
784     // array.Iterator should compare PrototypeOfPrototypeHClass.
785     if (isPrototypeOfPrototype) {
786         size_t pphcOffset = JSThread::GlueData::GetBuiltinPrototypeOfPrototypeHClassOffset(type, env->IsArch32Bit());
787         GateRef receiverPPhcAddress = builder_.LoadPrototypeOfPrototypeHClass(glue, receiver);
788         GateRef initialPPhcAddress = builder_.LoadConstOffset(VariableType::JS_POINTER(), glue, pphcOffset);
789         GateRef pphcMatches = builder_.Equal(receiverPPhcAddress, initialPPhcAddress);
790         // De-opt if HClass of X.prototype.prototype changed where X is the current builtin object.
791         builder_.DeoptCheck(pphcMatches, frameState, DeoptType::BUILTINPROTOHCLASSMISMATCH2);
792     }
793 }
794 
BuiltinInstanceStringTypeCheck(GateRef gate)795 void TypedHCRLowering::BuiltinInstanceStringTypeCheck(GateRef gate)
796 {
797     BuiltinPrototypeHClassAccessor accessor = acc_.GetBuiltinHClassAccessor(gate);
798     [[maybe_unused]] BuiltinTypeId type = accessor.GetBuiltinTypeId();
799     ASSERT(type == BuiltinTypeId::STRING);
800     GateRef frameState = GetFrameState(gate);
801     GateRef receiver = acc_.GetValueIn(gate, 0);
802     GateRef typeCheck = builder_.TaggedObjectIsString(glue_, receiver, compilationEnv_);
803     builder_.DeoptCheck(typeCheck, frameState, DeoptType::BUILTININSTANCEHCLASSMISMATCH2);
804 }
805 
LowerBuiltinInstanceHClassCheck(GateRef gate)806 void TypedHCRLowering::LowerBuiltinInstanceHClassCheck(GateRef gate)
807 {
808     Environment env(gate, circuit_, &builder_);
809     GateRef frameState = GetFrameState(gate);
810     GateRef receiver = acc_.GetValueIn(gate, 0);
811     builder_.HeapObjectCheck(receiver, frameState);
812     BuiltinPrototypeHClassAccessor accessor = acc_.GetBuiltinHClassAccessor(gate);
813     BuiltinTypeId type = accessor.GetBuiltinTypeId();
814     // BuiltinTypeId::STRING represents primitive string, only need to check the type of hclass here.
815     if (type == BuiltinTypeId::STRING) {
816         BuiltinInstanceStringTypeCheck(gate);
817     } else {
818         BuiltinInstanceHClassCheck(&env, gate); // check IHC
819     }
820     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
821 }
822 
LowerBuiltinPrototypeHClassCheck(GateRef gate)823 void TypedHCRLowering::LowerBuiltinPrototypeHClassCheck(GateRef gate)
824 {
825     Environment env(gate, circuit_, &builder_);
826     GateRef frameState = GetFrameState(gate);
827     GateRef receiver = acc_.GetValueIn(gate, 0);
828     builder_.HeapObjectCheck(receiver, frameState);
829     BuiltinPrototypeHClassAccessor accessor = acc_.GetBuiltinHClassAccessor(gate);
830     BuiltinTypeId type = accessor.GetBuiltinTypeId();
831     // BuiltinTypeId::STRING represents primitive string, only need to check the type of hclass here.
832     if (type == BuiltinTypeId::STRING) {
833         BuiltinInstanceStringTypeCheck(gate);
834     } else {
835         BuiltinInstanceHClassCheck(&env, gate); // check IHC
836         BuiltinPrototypeHClassCheck(&env, gate); // check PHC
837     }
838     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
839 }
840 
LowerIndexCheck(GateRef gate)841 void TypedHCRLowering::LowerIndexCheck(GateRef gate)
842 {
843     Environment env(gate, circuit_, &builder_);
844     auto deoptType = DeoptType::NOTLEGALIDX1;
845 
846     GateRef frameState = GetFrameState(gate);
847     GateRef length = acc_.GetValueIn(gate, 0);
848     GateRef index = acc_.GetValueIn(gate, 1);
849     ASSERT(acc_.GetGateType(length).IsNJSValueType());
850     // UnsignedLessThan can check both lower and upper bounds
851     GateRef lengthCheck = builder_.Int32UnsignedLessThan(index, length);
852     builder_.DeoptCheck(lengthCheck, frameState, deoptType);
853     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), index);
854 }
855 
LowerCallRuntime(GateRef glue,GateRef hirGate,int index,const std::vector<GateRef> & args,bool useLabel)856 GateRef TypedHCRLowering::LowerCallRuntime(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args,
857                                            bool useLabel)
858 {
859     const std::string name = RuntimeStubCSigns::GetRTName(index);
860     if (useLabel) {
861         GateRef result = builder_.CallRuntime(glue, index, Gate::InvalidGateRef, args, hirGate, name.c_str());
862         return result;
863     } else {
864         const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
865         GateRef target = builder_.IntPtr(index);
866         GateRef result = builder_.Call(cs, glue, target, dependEntry_, args, hirGate, name.c_str());
867         return result;
868     }
869 }
870 
LowerTypeConvert(GateRef gate)871 void TypedHCRLowering::LowerTypeConvert(GateRef gate)
872 {
873     Environment env(gate, circuit_, &builder_);
874 
875     TypeConvertAccessor accessor(acc_.TryGetValue(gate));
876     ParamType leftType = accessor.GetLeftType();
877     GateType rightType = accessor.GetRightType();
878     if (rightType.IsNumberType()) {
879         GateRef value = acc_.GetValueIn(gate, 0);
880         // NOTICE-PGO: wx support undefined/null/boolean type:
881         if (leftType.HasNumberType()) {
882             LowerPrimitiveToNumber(gate, value, leftType);
883         }
884         return;
885     }
886 }
887 
LowerPrimitiveToNumber(GateRef dst,GateRef src,ParamType srcType)888 void TypedHCRLowering::LowerPrimitiveToNumber(GateRef dst, GateRef src, ParamType srcType)
889 {
890     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
891     if (srcType.IsBooleanType()) {
892         Label exit(&builder_);
893         Label isTrue(&builder_);
894         Label isFalse(&builder_);
895         BRANCH_CIR(builder_.TaggedIsTrue(src), &isTrue, &isFalse);
896         builder_.Bind(&isTrue);
897         {
898             result = IntToTaggedIntPtr(builder_.Int32(1));
899             builder_.Jump(&exit);
900         }
901         builder_.Bind(&isFalse);
902         {
903             result = IntToTaggedIntPtr(builder_.Int32(0));
904             builder_.Jump(&exit);
905         }
906         builder_.Bind(&exit);
907     } else if (srcType.IsUndefinedType()) {
908         result = DoubleToTaggedDoublePtr(builder_.Double(base::NAN_VALUE));
909     } else if (srcType.IsBigIntType() || srcType.HasNumberType()) {
910         ASSERT(!srcType.IsIntOverflowType());
911         result = src;
912     } else if (srcType.IsNullType()) {
913         result = IntToTaggedIntPtr(builder_.Int32(0));
914     } else {
915         LOG_ECMA(FATAL) << "this branch is unreachable";
916         UNREACHABLE();
917     }
918     acc_.ReplaceGate(dst, builder_.GetState(), builder_.GetDepend(), *result);
919 }
920 
LoadFromConstPool(GateRef glue,GateRef unsharedConstPool,size_t index,size_t valVecType)921 GateRef TypedHCRLowering::LoadFromConstPool(GateRef glue, GateRef unsharedConstPool, size_t index, size_t valVecType)
922 {
923     GateRef constPoolSize = builder_.GetLengthOfTaggedArray(unsharedConstPool);
924     GateRef valVecIndex = builder_.Int32Sub(constPoolSize, builder_.Int32(valVecType));
925     GateRef valVec = builder_.GetValueFromTaggedArray(glue, unsharedConstPool, valVecIndex);
926     return builder_.LoadFromTaggedArray(valVec, index);
927 }
928 
LowerLoadProperty(GateRef gate)929 void TypedHCRLowering::LowerLoadProperty(GateRef gate)
930 {
931     Environment env(gate, circuit_, &builder_);
932     ASSERT(acc_.GetNumValueIn(gate) == 2);  // 2: receiver, plr
933     GateRef receiver = acc_.GetValueIn(gate, 0);
934     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
935     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
936     ASSERT(plr.IsLocal() || plr.IsFunction());
937 
938     GateRef result = LoadPropertyFromHolder(receiver, plr);
939 
940     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
941 }
942 
LowerCallPrivateGetter(GateRef gate,GateRef glue)943 void TypedHCRLowering::LowerCallPrivateGetter(GateRef gate, GateRef glue)
944 {
945     Environment env(gate, circuit_, &builder_);
946     ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: receiver, accessor
947     GateRef receiver = acc_.GetValueIn(gate, 0);
948     GateRef accessor = acc_.GetValueIn(gate, 1);
949 
950     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
951     result = CallAccessor(glue, gate, accessor, receiver, AccessorMode::GETTER);
952     ReplaceHirWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), *result);
953 }
954 
LowerCallPrivateSetter(GateRef gate,GateRef glue)955 void TypedHCRLowering::LowerCallPrivateSetter(GateRef gate, GateRef glue)
956 {
957     Environment env(gate, circuit_, &builder_);
958     ASSERT(acc_.GetNumValueIn(gate) == 3); // 3: receiver, accessor, value
959     GateRef receiver = acc_.GetValueIn(gate, 0);
960     GateRef accessor = acc_.GetValueIn(gate, 1);
961     GateRef value = acc_.GetValueIn(gate, 2);
962 
963     CallAccessor(glue, gate, accessor, receiver, AccessorMode::SETTER, value);
964     ReplaceHirWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
965 }
966 
LowerCallGetter(GateRef gate,GateRef glue)967 void TypedHCRLowering::LowerCallGetter(GateRef gate, GateRef glue)
968 {
969     Environment env(gate, circuit_, &builder_);
970     ASSERT(acc_.GetNumValueIn(gate) == 3);  // 3: receiver, holder, plr
971     GateRef receiver = acc_.GetValueIn(gate, 0);
972     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
973     GateRef holder = acc_.GetValueIn(gate, 2);
974     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
975 
976     GateRef accessor = LoadPropertyFromHolder(holder, plr);
977 
978     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
979     Label isInternalAccessor(&builder_);
980     Label notInternalAccessor(&builder_);
981     Label callGetter(&builder_);
982     Label exit(&builder_);
983     BRANCH_CIR(builder_.IsAccessorInternal(glue, accessor), &isInternalAccessor, &notInternalAccessor);
984     {
985         builder_.Bind(&isInternalAccessor);
986         {
987             result = builder_.CallRuntime(glue, RTSTUB_ID(CallInternalGetter),
988                 Gate::InvalidGateRef, { accessor, holder }, gate);
989             builder_.Jump(&exit);
990         }
991         builder_.Bind(&notInternalAccessor);
992         {
993             GateRef getter = builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::GETTER_OFFSET);
994             BRANCH_CIR(builder_.IsSpecial(getter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callGetter);
995             builder_.Bind(&callGetter);
996             {
997                 result = CallAccessor(glue, gate, getter, receiver, AccessorMode::GETTER);
998                 builder_.Jump(&exit);
999             }
1000         }
1001     }
1002     builder_.Bind(&exit);
1003     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
1004 }
1005 
LowerStoreProperty(GateRef gate)1006 void TypedHCRLowering::LowerStoreProperty(GateRef gate)
1007 {
1008     Environment env(gate, circuit_, &builder_);
1009     ASSERT(acc_.GetNumValueIn(gate) == 3);  // 3: receiver, plr, value
1010     GateRef receiver = acc_.GetValueIn(gate, 0);
1011     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1012     GateRef value = acc_.GetValueIn(gate, 2); // 2: value
1013     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1014     ASSERT(plr.IsLocal());
1015     auto op = OpCode(acc_.GetOpCode(gate));
1016     if (op == OpCode::STORE_PROPERTY) {
1017         if (plr.IsInlinedProps()) {
1018             builder_.StoreConstOffset(VariableType::JS_ANY(), receiver, plr.GetOffset(), value);
1019         } else {
1020             auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), receiver, JSObject::PROPERTIES_OFFSET);
1021             builder_.SetValueToTaggedArray(
1022                 VariableType::JS_ANY(), glue_, properties, builder_.Int32(plr.GetOffset()), value);
1023         }
1024     } else if (op == OpCode::STORE_PROPERTY_NO_BARRIER) {
1025         if (plr.IsInlinedProps()) {
1026             builder_.StoreConstOffset(GetVarType(plr), receiver, plr.GetOffset(), value);
1027         } else {
1028             auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), receiver, JSObject::PROPERTIES_OFFSET);
1029             builder_.SetValueToTaggedArray(
1030                 GetVarType(plr), glue_, properties, builder_.Int32(plr.GetOffset()), value);
1031         }
1032     } else {
1033         UNREACHABLE();
1034     }
1035     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1036 }
1037 
LowerCallSetter(GateRef gate,GateRef glue)1038 void TypedHCRLowering::LowerCallSetter(GateRef gate, GateRef glue)
1039 {
1040     Environment env(gate, circuit_, &builder_);
1041     ASSERT(acc_.GetNumValueIn(gate) == 4);  // 4: receiver, holder, plr, value
1042     GateRef receiver = acc_.GetValueIn(gate, 0);
1043     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1044     GateRef holder = acc_.GetValueIn(gate, 2);
1045     GateRef value = acc_.GetValueIn(gate, 3);
1046 
1047     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1048     ASSERT(plr.IsAccessor());
1049     GateRef accessor = Circuit::NullGate();
1050     if (plr.IsNotHole()) {
1051         ASSERT(plr.IsLocal());
1052         if (plr.IsInlinedProps()) {
1053             accessor = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset());
1054         } else {
1055             auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
1056             accessor = builder_.GetValueFromTaggedArray(glue, properties, builder_.Int32(plr.GetOffset()));
1057         }
1058     } else if (plr.IsLocal()) {
1059         if (plr.IsInlinedProps()) {
1060             accessor = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset());
1061         } else {
1062             auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
1063             accessor = builder_.GetValueFromTaggedArray(glue, properties, builder_.Int32(plr.GetOffset()));
1064         }
1065         accessor = builder_.ConvertHoleAsUndefined(accessor);
1066     } else {
1067         UNREACHABLE();
1068     }
1069     Label isInternalAccessor(&builder_);
1070     Label notInternalAccessor(&builder_);
1071     Label callSetter(&builder_);
1072     Label exit(&builder_);
1073     BRANCH_CIR(builder_.IsAccessorInternal(glue, accessor), &isInternalAccessor, &notInternalAccessor);
1074     {
1075         builder_.Bind(&isInternalAccessor);
1076         {
1077             builder_.CallRuntime(glue, RTSTUB_ID(CallInternalSetter),
1078                 Gate::InvalidGateRef, { receiver, accessor, value }, gate);
1079             builder_.Jump(&exit);
1080         }
1081         builder_.Bind(&notInternalAccessor);
1082         {
1083             GateRef setter = builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::SETTER_OFFSET);
1084             BRANCH_CIR(builder_.IsSpecial(setter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callSetter);
1085             builder_.Bind(&callSetter);
1086             {
1087                 CallAccessor(glue, gate, setter, receiver, AccessorMode::SETTER, value);
1088                 builder_.Jump(&exit);
1089             }
1090         }
1091     }
1092     builder_.Bind(&exit);
1093     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1094 }
1095 
LowerLoadArrayLength(GateRef gate)1096 void TypedHCRLowering::LowerLoadArrayLength(GateRef gate)
1097 {
1098     Environment env(gate, circuit_, &builder_);
1099     GateRef array = acc_.GetValueIn(gate, 0);
1100     GateRef result = builder_.LoadConstOffset(VariableType::INT32(), array, JSArray::LENGTH_OFFSET);
1101     acc_.SetGateType(gate, GateType::NJSValue());
1102     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
1103 }
1104 
GetElementSize(BuiltinTypeId id)1105 GateRef TypedHCRLowering::GetElementSize(BuiltinTypeId id)
1106 {
1107     GateRef elementSize = Circuit::NullGate();
1108     switch (id) {
1109         case BuiltinTypeId::INT8_ARRAY:
1110         case BuiltinTypeId::UINT8_ARRAY:
1111         case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
1112             elementSize = builder_.Int32(sizeof(uint8_t));
1113             break;
1114         case BuiltinTypeId::INT16_ARRAY:
1115         case BuiltinTypeId::UINT16_ARRAY:
1116             elementSize = builder_.Int32(sizeof(uint16_t));
1117             break;
1118         case BuiltinTypeId::INT32_ARRAY:
1119         case BuiltinTypeId::UINT32_ARRAY:
1120         case BuiltinTypeId::FLOAT32_ARRAY:
1121             elementSize = builder_.Int32(sizeof(uint32_t));
1122             break;
1123         case BuiltinTypeId::FLOAT64_ARRAY:
1124             elementSize = builder_.Int32(sizeof(double));
1125             break;
1126         default:
1127             LOG_ECMA(FATAL) << "this branch is unreachable";
1128             UNREACHABLE();
1129     }
1130     return elementSize;
1131 }
1132 
GetVariableType(BuiltinTypeId id)1133 VariableType TypedHCRLowering::GetVariableType(BuiltinTypeId id)
1134 {
1135     VariableType type = VariableType::JS_ANY();
1136     switch (id) {
1137         case BuiltinTypeId::INT8_ARRAY:
1138         case BuiltinTypeId::UINT8_ARRAY:
1139         case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
1140             type = VariableType::INT8();
1141             break;
1142         case BuiltinTypeId::INT16_ARRAY:
1143         case BuiltinTypeId::UINT16_ARRAY:
1144             type = VariableType::INT16();
1145             break;
1146         case BuiltinTypeId::INT32_ARRAY:
1147         case BuiltinTypeId::UINT32_ARRAY:
1148             type = VariableType::INT32();
1149             break;
1150         case BuiltinTypeId::FLOAT32_ARRAY:
1151             type = VariableType::FLOAT32();
1152             break;
1153         case BuiltinTypeId::FLOAT64_ARRAY:
1154             type = VariableType::FLOAT64();
1155             break;
1156         default:
1157             LOG_ECMA(FATAL) << "this branch is unreachable";
1158             UNREACHABLE();
1159     }
1160     return type;
1161 }
1162 
LowerLoadElement(GateRef gate,GateRef glue)1163 void TypedHCRLowering::LowerLoadElement(GateRef gate, GateRef glue)
1164 {
1165     Environment env(gate, circuit_, &builder_);
1166     LoadElementAccessor accessor = acc_.GetLoadElementAccessor(gate);
1167     TypedLoadOp op = accessor.GetTypedLoadOp();
1168     switch (op) {
1169         case TypedLoadOp::ARRAY_LOAD_INT_ELEMENT:
1170         case TypedLoadOp::ARRAY_LOAD_DOUBLE_ELEMENT:
1171         case TypedLoadOp::ARRAY_LOAD_OBJECT_ELEMENT:
1172         case TypedLoadOp::ARRAY_LOAD_TAGGED_ELEMENT:
1173             LowerArrayLoadElement(gate, ArrayState::PACKED, op);
1174             break;
1175         case TypedLoadOp::ARRAY_LOAD_HOLE_TAGGED_ELEMENT:
1176         case TypedLoadOp::ARRAY_LOAD_HOLE_INT_ELEMENT:
1177         case TypedLoadOp::ARRAY_LOAD_HOLE_DOUBLE_ELEMENT:
1178             LowerArrayLoadElement(gate, ArrayState::HOLEY, op);
1179             break;
1180         case TypedLoadOp::INT8ARRAY_LOAD_ELEMENT:
1181             LowerTypedArrayLoadElement(gate, BuiltinTypeId::INT8_ARRAY);
1182             break;
1183         case TypedLoadOp::UINT8ARRAY_LOAD_ELEMENT:
1184             LowerTypedArrayLoadElement(gate, BuiltinTypeId::UINT8_ARRAY);
1185             break;
1186         case TypedLoadOp::UINT8CLAMPEDARRAY_LOAD_ELEMENT:
1187             LowerTypedArrayLoadElement(gate, BuiltinTypeId::UINT8_CLAMPED_ARRAY);
1188             break;
1189         case TypedLoadOp::INT16ARRAY_LOAD_ELEMENT:
1190             LowerTypedArrayLoadElement(gate, BuiltinTypeId::INT16_ARRAY);
1191             break;
1192         case TypedLoadOp::UINT16ARRAY_LOAD_ELEMENT:
1193             LowerTypedArrayLoadElement(gate, BuiltinTypeId::UINT16_ARRAY);
1194             break;
1195         case TypedLoadOp::INT32ARRAY_LOAD_ELEMENT:
1196             LowerTypedArrayLoadElement(gate, BuiltinTypeId::INT32_ARRAY);
1197             break;
1198         case TypedLoadOp::UINT32ARRAY_LOAD_ELEMENT:
1199             LowerTypedArrayLoadElement(gate, BuiltinTypeId::UINT32_ARRAY);
1200             break;
1201         case TypedLoadOp::FLOAT32ARRAY_LOAD_ELEMENT:
1202             LowerTypedArrayLoadElement(gate, BuiltinTypeId::FLOAT32_ARRAY);
1203             break;
1204         case TypedLoadOp::FLOAT64ARRAY_LOAD_ELEMENT:
1205             LowerTypedArrayLoadElement(gate, BuiltinTypeId::FLOAT64_ARRAY);
1206             break;
1207         case TypedLoadOp::STRING_LOAD_ELEMENT:
1208             LowerStringLoadElement(gate, glue);
1209             break;
1210         default:
1211             LOG_ECMA(FATAL) << "this branch is unreachable";
1212             UNREACHABLE();
1213     }
1214 }
1215 
LowerCowArrayCheck(GateRef gate,GateRef glue)1216 void TypedHCRLowering::LowerCowArrayCheck(GateRef gate, GateRef glue)
1217 {
1218     Environment env(gate, circuit_, &builder_);
1219     GateRef receiver = acc_.GetValueIn(gate, 0);
1220     Label notCOWArray(&builder_);
1221     Label isCOWArray(&builder_);
1222     GateRef needCOW = builder_.IsJsCOWArray(glue, receiver, compilationEnv_);
1223     BRANCH_CIR(needCOW, &isCOWArray, &notCOWArray);
1224     builder_.Bind(&isCOWArray);
1225     {
1226         LowerCallRuntime(glue, gate, RTSTUB_ID(CheckAndCopyArray), {receiver}, true);
1227         builder_.Jump(&notCOWArray);
1228     }
1229     builder_.Bind(&notCOWArray);
1230 
1231     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1232 }
1233 
1234 // for JSArray
LowerArrayLoadElement(GateRef gate,ArrayState arrayState,TypedLoadOp op)1235 void TypedHCRLowering::LowerArrayLoadElement(GateRef gate, ArrayState arrayState, TypedLoadOp op)
1236 {
1237     Environment env(gate, circuit_, &builder_);
1238     GateRef glue = glue_;
1239     GateRef receiver = acc_.GetValueIn(gate, 0);
1240     GateRef index = acc_.GetValueIn(gate, 1);
1241     GateRef element = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, JSObject::ELEMENTS_OFFSET);
1242     GateRef result = Circuit::NullGate();
1243     if (arrayState == ArrayState::HOLEY) {
1244         if (op == TypedLoadOp::ARRAY_LOAD_HOLE_INT_ELEMENT ||
1245             op == TypedLoadOp::ARRAY_LOAD_HOLE_DOUBLE_ELEMENT) {
1246             result = builder_.GetValueFromJSArrayWithElementsKind(VariableType::INT64(), element, index);
1247         } else {
1248             result = builder_.GetValueFromTaggedArray(glue, element, index);
1249             result = builder_.ConvertHoleAsUndefined(result);
1250         }
1251     } else {
1252         // When elementsKind swith on, we should get corresponding raw value for Int and Double kind.
1253         result = builder_.GetValueFromTaggedArray(glue, element, index);
1254     }
1255     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
1256 }
1257 
LowerTypedArrayLoadElement(GateRef gate,BuiltinTypeId id)1258 void TypedHCRLowering::LowerTypedArrayLoadElement(GateRef gate, BuiltinTypeId id)
1259 {
1260     Environment env(gate, circuit_, &builder_);
1261     GateRef glue = glue_;
1262     GateRef receiver = acc_.GetValueIn(gate, 0);
1263     GateRef index = acc_.GetValueIn(gate, 1);
1264     GateRef elementSize = GetElementSize(id);
1265     GateRef offset = builder_.PtrMul(index, elementSize);
1266     VariableType type = GetVariableType(id);
1267 
1268     GateRef result = Circuit::NullGate();
1269     LoadElementAccessor accessor = acc_.GetLoadElementAccessor(gate);
1270     OnHeapMode onHeapMode = accessor.GetOnHeapMode();
1271 
1272     switch (onHeapMode) {
1273         case OnHeapMode::ON_HEAP: {
1274             result = BuildOnHeapTypedArrayLoadElement(glue, receiver, offset, type);
1275             break;
1276         }
1277         case OnHeapMode::NOT_ON_HEAP: {
1278             result = BuildNotOnHeapTypedArrayLoadElement(glue, receiver, offset, type);
1279             break;
1280         }
1281         default: {
1282             Label isByteArray(&builder_);
1283             Label isArrayBuffer(&builder_);
1284             Label exit(&builder_);
1285             result = BuildTypedArrayLoadElement(glue, receiver, offset, type, &isByteArray, &isArrayBuffer, &exit);
1286             break;
1287         }
1288     }
1289 
1290     switch (id) {
1291         case BuiltinTypeId::INT8_ARRAY:
1292             result = builder_.SExtInt8ToInt32(result);
1293             break;
1294         case BuiltinTypeId::UINT8_ARRAY:
1295         case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
1296             result = builder_.ZExtInt8ToInt32(result);
1297             break;
1298         case BuiltinTypeId::INT16_ARRAY:
1299             result = builder_.SExtInt16ToInt32(result);
1300             break;
1301         case BuiltinTypeId::UINT16_ARRAY:
1302             result = builder_.ZExtInt16ToInt32(result);
1303             break;
1304         case BuiltinTypeId::FLOAT32_ARRAY:
1305             result = builder_.FloatArrayElementConvert(result, true);
1306             break;
1307         case BuiltinTypeId::FLOAT64_ARRAY:
1308             result = builder_.FloatArrayElementConvert(result, false);
1309             break;
1310         default:
1311             break;
1312     }
1313     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
1314 }
1315 
BuildOnHeapTypedArrayLoadElement(GateRef glue,GateRef receiver,GateRef offset,VariableType type)1316 GateRef TypedHCRLowering::BuildOnHeapTypedArrayLoadElement(GateRef glue, GateRef receiver, GateRef offset,
1317     VariableType type)
1318 {
1319     GateRef byteArray =
1320         builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
1321     GateRef data = builder_.PtrAdd(byteArray, builder_.IntPtr(ByteArray::DATA_OFFSET));
1322     GateRef result = builder_.Load(type, glue, data, offset);
1323     return result;
1324 }
1325 
BuildNotOnHeapTypedArrayLoadElement(GateRef glue,GateRef receiver,GateRef offset,VariableType type)1326 GateRef TypedHCRLowering::BuildNotOnHeapTypedArrayLoadElement(GateRef glue, GateRef receiver, GateRef offset,
1327     VariableType type)
1328 {
1329     GateRef arrayBuffer =
1330         builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
1331 
1332     GateRef data =
1333         builder_.Load(VariableType::JS_POINTER(), glue, arrayBuffer, builder_.IntPtr(JSArrayBuffer::DATA_OFFSET));
1334     GateRef block =
1335         builder_.Load(VariableType::JS_ANY(), glue, data, builder_.IntPtr(JSNativePointer::POINTER_OFFSET));
1336     GateRef byteOffset = builder_.LoadWithoutBarrier(VariableType::INT32(), receiver,
1337                                                      builder_.IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET));
1338     GateRef result = builder_.Load(type, glue, block, builder_.PtrAdd(offset, byteOffset));
1339     return result;
1340 }
1341 
BuildTypedArrayLoadElement(GateRef glue,GateRef receiver,GateRef offset,VariableType type,Label * isByteArray,Label * isArrayBuffer,Label * exit)1342 GateRef TypedHCRLowering::BuildTypedArrayLoadElement(GateRef glue, GateRef receiver, GateRef offset, VariableType type,
1343                                                      Label *isByteArray, Label *isArrayBuffer, Label *exit)
1344 {
1345     GateRef byteArrayOrArrayBuffer =
1346         builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
1347     DEFVALUE(data, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1348     DEFVALUE(result, (&builder_), type, builder_.Double(0));
1349 
1350     GateRef isOnHeap = builder_.IsOnHeap(builder_.LoadHClassByConstOffset(glue, receiver));
1351     BRANCH_CIR(isOnHeap, isByteArray, isArrayBuffer);
1352     builder_.Bind(isByteArray);
1353     {
1354         data = builder_.PtrAdd(byteArrayOrArrayBuffer, builder_.IntPtr(ByteArray::DATA_OFFSET));
1355         result = builder_.Load(type, glue, *data, offset);
1356         builder_.Jump(exit);
1357     }
1358     builder_.Bind(isArrayBuffer);
1359     {
1360         data = builder_.Load(VariableType::JS_POINTER(), glue, byteArrayOrArrayBuffer,
1361                              builder_.IntPtr(JSArrayBuffer::DATA_OFFSET));
1362         GateRef block =
1363             builder_.Load(VariableType::JS_ANY(), glue, *data, builder_.IntPtr(JSNativePointer::POINTER_OFFSET));
1364         GateRef byteOffset =
1365             builder_.LoadWithoutBarrier(VariableType::INT32(), receiver,
1366                                         builder_.IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET));
1367         result = builder_.Load(type, glue, block, builder_.PtrAdd(offset, byteOffset));
1368         builder_.Jump(exit);
1369     }
1370     builder_.Bind(exit);
1371 
1372     return *result;
1373 }
1374 
LowerStringLoadElement(GateRef gate,GateRef glue)1375 void TypedHCRLowering::LowerStringLoadElement(GateRef gate, GateRef glue)
1376 {
1377     Environment env(gate, circuit_, &builder_);
1378     GateRef receiver = acc_.GetValueIn(gate, 0);
1379     GateRef index = acc_.GetValueIn(gate, 1);
1380     GateRef result = Circuit::NullGate();
1381     if (compilationEnv_->IsJitCompiler()) {
1382         result = builder_.CallStub(glue, gate, CommonStubCSigns::StringLoadElement,
1383                                    {glue, receiver, index, circuit_->GetGlobalEnvCache()}, "StringLoadElement stub");
1384     } else {
1385         BuiltinsStringStubBuilder builder(&env, circuit_->GetGlobalEnvCache());
1386         result = builder.GetSingleCharCodeByIndex(glue, receiver, index);
1387     }
1388 
1389     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
1390 }
1391 
LowerStoreElement(GateRef gate,GateRef glue)1392 void TypedHCRLowering::LowerStoreElement(GateRef gate, GateRef glue)
1393 {
1394     Environment env(gate, circuit_, &builder_);
1395     StoreElementAccessor accessor = acc_.GetStoreElementAccessor(gate);
1396     TypedStoreOp op = accessor.GetTypedStoreOp();
1397     switch (op) {
1398         case TypedStoreOp::ARRAY_STORE_ELEMENT:
1399         case TypedStoreOp::ARRAY_STORE_INT_ELEMENT:
1400         case TypedStoreOp::ARRAY_STORE_DOUBLE_ELEMENT:
1401             LowerArrayStoreElement(gate, glue, op);
1402             break;
1403         case TypedStoreOp::INT8ARRAY_STORE_ELEMENT:
1404             LowerTypedArrayStoreElement(gate, BuiltinTypeId::INT8_ARRAY);
1405             break;
1406         case TypedStoreOp::UINT8ARRAY_STORE_ELEMENT:
1407             LowerTypedArrayStoreElement(gate, BuiltinTypeId::UINT8_ARRAY);
1408             break;
1409         case TypedStoreOp::UINT8CLAMPEDARRAY_STORE_ELEMENT:
1410             LowerUInt8ClampedArrayStoreElement(gate);
1411             break;
1412         case TypedStoreOp::INT16ARRAY_STORE_ELEMENT:
1413             LowerTypedArrayStoreElement(gate, BuiltinTypeId::INT16_ARRAY);
1414             break;
1415         case TypedStoreOp::UINT16ARRAY_STORE_ELEMENT:
1416             LowerTypedArrayStoreElement(gate, BuiltinTypeId::UINT16_ARRAY);
1417             break;
1418         case TypedStoreOp::INT32ARRAY_STORE_ELEMENT:
1419             LowerTypedArrayStoreElement(gate, BuiltinTypeId::INT32_ARRAY);
1420             break;
1421         case TypedStoreOp::UINT32ARRAY_STORE_ELEMENT:
1422             LowerTypedArrayStoreElement(gate, BuiltinTypeId::UINT32_ARRAY);
1423             break;
1424         case TypedStoreOp::FLOAT32ARRAY_STORE_ELEMENT:
1425             LowerTypedArrayStoreElement(gate, BuiltinTypeId::FLOAT32_ARRAY);
1426             break;
1427         case TypedStoreOp::FLOAT64ARRAY_STORE_ELEMENT:
1428             LowerTypedArrayStoreElement(gate, BuiltinTypeId::FLOAT64_ARRAY);
1429             break;
1430         default:
1431             LOG_ECMA(FATAL) << "this branch is unreachable";
1432             UNREACHABLE();
1433     }
1434 }
1435 
1436 // for JSArray
LowerArrayStoreElement(GateRef gate,GateRef glue,TypedStoreOp op)1437 void TypedHCRLowering::LowerArrayStoreElement(GateRef gate, GateRef glue, TypedStoreOp op)
1438 {
1439     Environment env(gate, circuit_, &builder_);
1440     GateRef receiver = acc_.GetValueIn(gate, 0);  // 0: receiver
1441     GateRef index = acc_.GetValueIn(gate, 1);     // 1: index
1442     GateRef value = acc_.GetValueIn(gate, 2);     // 2: value
1443 
1444     GateRef element = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, JSObject::ELEMENTS_OFFSET);
1445     // Because at retype stage, we have set output according to op
1446     // there is not need to consider about the convertion here.
1447     if (op == TypedStoreOp::ARRAY_STORE_INT_ELEMENT) {
1448         GateRef convertedValue = builder_.ZExtInt32ToInt64(value);
1449         builder_.SetValueToTaggedArray(VariableType::INT64(), glue, element, index, convertedValue);
1450     } else if (op == TypedStoreOp::ARRAY_STORE_DOUBLE_ELEMENT) {
1451         builder_.SetValueToTaggedArray(VariableType::FLOAT64(), glue, element, index, value);
1452     } else {
1453         builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue, element, index, value);
1454     }
1455 
1456     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1457 }
1458 
1459 // for JSTypedArray
LowerTypedArrayStoreElement(GateRef gate,BuiltinTypeId id)1460 void TypedHCRLowering::LowerTypedArrayStoreElement(GateRef gate, BuiltinTypeId id)
1461 {
1462     Environment env(gate, circuit_, &builder_);
1463     GateRef glue = glue_;
1464     GateRef receiver = acc_.GetValueIn(gate, 0);
1465     GateRef index = acc_.GetValueIn(gate, 1);
1466     GateRef value = acc_.GetValueIn(gate, 2);
1467 
1468     GateRef elementSize = GetElementSize(id);
1469     GateRef offset = builder_.PtrMul(index, elementSize);
1470     switch (id) {
1471         case BuiltinTypeId::INT8_ARRAY:
1472         case BuiltinTypeId::UINT8_ARRAY:
1473             value = builder_.TruncInt32ToInt8(value);
1474             break;
1475         case BuiltinTypeId::INT16_ARRAY:
1476         case BuiltinTypeId::UINT16_ARRAY:
1477             value = builder_.TruncInt32ToInt16(value);
1478             break;
1479         case BuiltinTypeId::FLOAT32_ARRAY:
1480             value = builder_.TruncDoubleToFloat32(value);
1481             break;
1482         default:
1483             break;
1484     }
1485 
1486     Label isByteArray(&builder_);
1487     Label isArrayBuffer(&builder_);
1488     Label exit(&builder_);
1489     OptStoreElementByOnHeapMode(gate, glue, receiver, offset, value, &isByteArray, &isArrayBuffer, &exit);
1490     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1491 }
1492 
OptStoreElementByOnHeapMode(GateRef gate,GateRef glue,GateRef receiver,GateRef offset,GateRef value,Label * isByteArray,Label * isArrayBuffer,Label * exit)1493 void TypedHCRLowering::OptStoreElementByOnHeapMode(GateRef gate, GateRef glue, GateRef receiver, GateRef offset,
1494     GateRef value, Label *isByteArray, Label *isArrayBuffer, Label *exit)
1495 {
1496     StoreElementAccessor accessor = acc_.GetStoreElementAccessor(gate);
1497     OnHeapMode onHeapMode = accessor.GetOnHeapMode();
1498     switch (onHeapMode) {
1499         case OnHeapMode::ON_HEAP: {
1500             BuildOnHeapTypedArrayStoreElement(receiver, offset, value);
1501             break;
1502         }
1503         case OnHeapMode::NOT_ON_HEAP: {
1504             BuildNotOnHeapTypedArrayStoreElement(glue, receiver, offset, value);
1505             break;
1506         }
1507         default: {
1508             BuildTypedArrayStoreElement(glue, receiver, offset, value, isByteArray, isArrayBuffer, exit);
1509             break;
1510         }
1511     }
1512 }
1513 
BuildOnHeapTypedArrayStoreElement(GateRef receiver,GateRef offset,GateRef value)1514 void TypedHCRLowering::BuildOnHeapTypedArrayStoreElement(GateRef receiver, GateRef offset, GateRef value)
1515 {
1516     GateRef byteArray = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver,
1517                                                  JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
1518     GateRef data = builder_.PtrAdd(byteArray, builder_.IntPtr(ByteArray::DATA_OFFSET));
1519 
1520     builder_.StoreMemory(MemoryType::ELEMENT_TYPE, VariableType::VOID(), data, offset, value);
1521 }
1522 
BuildNotOnHeapTypedArrayStoreElement(GateRef glue,GateRef receiver,GateRef offset,GateRef value)1523 void TypedHCRLowering::BuildNotOnHeapTypedArrayStoreElement(GateRef glue, GateRef receiver,
1524                                                             GateRef offset, GateRef value)
1525 {
1526     GateRef arrayBuffer = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver,
1527                                                    JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
1528     GateRef data =
1529         builder_.Load(VariableType::JS_POINTER(), glue, arrayBuffer, builder_.IntPtr(JSArrayBuffer::DATA_OFFSET));
1530     GateRef block = builder_.Load(VariableType::JS_ANY(), glue, data,
1531                                   builder_.IntPtr(JSNativePointer::POINTER_OFFSET));
1532     GateRef byteOffset =
1533         builder_.LoadWithoutBarrier(VariableType::INT32(), receiver,
1534                                     builder_.IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET));
1535     builder_.StoreMemory(MemoryType::ELEMENT_TYPE, VariableType::VOID(), block,
1536                          builder_.PtrAdd(offset, byteOffset), value);
1537 }
1538 
BuildTypedArrayStoreElement(GateRef glue,GateRef receiver,GateRef offset,GateRef value,Label * isByteArray,Label * isArrayBuffer,Label * exit)1539 void TypedHCRLowering::BuildTypedArrayStoreElement(GateRef glue, GateRef receiver, GateRef offset, GateRef value,
1540                                                    Label *isByteArray, Label *isArrayBuffer, Label *exit)
1541 {
1542     GateRef byteArrayOrArrayBuffer = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver,
1543                                                               JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
1544     GateRef isOnHeap = builder_.IsOnHeap(builder_.LoadHClassByConstOffset(glue, receiver));
1545     DEFVALUE(data, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1546     BRANCH_CIR(isOnHeap, isByteArray, isArrayBuffer);
1547     builder_.Bind(isByteArray);
1548     {
1549         data = builder_.PtrAdd(byteArrayOrArrayBuffer, builder_.IntPtr(ByteArray::DATA_OFFSET));
1550         builder_.StoreMemory(MemoryType::ELEMENT_TYPE, VariableType::VOID(), *data, offset, value);
1551         builder_.Jump(exit);
1552     }
1553     builder_.Bind(isArrayBuffer);
1554     {
1555         data = builder_.Load(VariableType::JS_POINTER(), glue, byteArrayOrArrayBuffer,
1556                              builder_.IntPtr(JSArrayBuffer::DATA_OFFSET));
1557         GateRef block =
1558             builder_.Load(VariableType::JS_ANY(), glue, *data, builder_.IntPtr(JSNativePointer::POINTER_OFFSET));
1559         GateRef byteOffset =
1560             builder_.LoadWithoutBarrier(VariableType::INT32(), receiver,
1561                                         builder_.IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET));
1562         builder_.StoreMemory(MemoryType::ELEMENT_TYPE, VariableType::VOID(), block,
1563                              builder_.PtrAdd(offset, byteOffset), value);
1564         builder_.Jump(exit);
1565     }
1566     builder_.Bind(exit);
1567 }
1568 
1569 // for UInt8ClampedArray
LowerUInt8ClampedArrayStoreElement(GateRef gate)1570 void TypedHCRLowering::LowerUInt8ClampedArrayStoreElement(GateRef gate)
1571 {
1572     Environment env(gate, circuit_, &builder_);
1573 
1574     GateRef glue = glue_;
1575     GateRef receiver = acc_.GetValueIn(gate, 0);
1576     GateRef index = acc_.GetValueIn(gate, 1);
1577     GateRef elementSize = builder_.Int32(sizeof(uint8_t));
1578     GateRef offset = builder_.PtrMul(index, elementSize);
1579     GateRef value = acc_.GetValueIn(gate, 2);
1580 
1581     DEFVALUE(result, (&builder_), VariableType::INT32(), value);
1582     GateRef topValue = builder_.Int32(static_cast<uint32_t>(UINT8_MAX));
1583     GateRef bottomValue = builder_.Int32(static_cast<uint32_t>(0));
1584     Label isOverFlow(&builder_);
1585     Label notOverFlow(&builder_);
1586     Label exit(&builder_);
1587     Label isByteArray(&builder_);
1588     Label isArrayBuffer(&builder_);
1589     Label quit(&builder_);
1590     BRANCH_CIR(builder_.Int32GreaterThan(value, topValue), &isOverFlow, &notOverFlow);
1591     builder_.Bind(&isOverFlow);
1592     {
1593         result = topValue;
1594         builder_.Jump(&exit);
1595     }
1596     builder_.Bind(&notOverFlow);
1597     {
1598         Label isUnderSpill(&builder_);
1599         BRANCH_CIR(builder_.Int32LessThan(value, bottomValue), &isUnderSpill, &exit);
1600         builder_.Bind(&isUnderSpill);
1601         {
1602             result = bottomValue;
1603             builder_.Jump(&exit);
1604         }
1605     }
1606     builder_.Bind(&exit);
1607     value = builder_.TruncInt32ToInt8(*result);
1608     OptStoreElementByOnHeapMode(gate, glue, receiver, offset, value, &isByteArray, &isArrayBuffer, &quit);
1609     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1610 }
1611 
DoubleToTaggedDoublePtr(GateRef gate)1612 GateRef TypedHCRLowering::DoubleToTaggedDoublePtr(GateRef gate)
1613 {
1614     return builder_.DoubleToTaggedDoublePtr(gate);
1615 }
1616 
ChangeInt32ToFloat64(GateRef gate)1617 GateRef TypedHCRLowering::ChangeInt32ToFloat64(GateRef gate)
1618 {
1619     return builder_.ChangeInt32ToFloat64(gate);
1620 }
1621 
TruncDoubleToInt(GateRef gate)1622 GateRef TypedHCRLowering::TruncDoubleToInt(GateRef gate)
1623 {
1624     return builder_.TruncInt64ToInt32(builder_.TruncFloatToInt64(gate));
1625 }
1626 
IntToTaggedIntPtr(GateRef x)1627 GateRef TypedHCRLowering::IntToTaggedIntPtr(GateRef x)
1628 {
1629     GateRef val = builder_.SExtInt32ToInt64(x);
1630     return builder_.ToTaggedIntPtr(val);
1631 }
1632 
LowerTypedCallBuitin(GateRef gate)1633 void TypedHCRLowering::LowerTypedCallBuitin(GateRef gate)
1634 {
1635     BuiltinLowering lowering(circuit_, builder_.GetCompilationConfig(), traceBuiltins_);
1636     lowering.LowerTypedCallBuitin(gate);
1637 }
1638 
CallTargetIsCompiledCheck(GateRef func,GateRef frameState,Label * checkAlreadyDeopt,Label * exit)1639 void TypedHCRLowering::CallTargetIsCompiledCheck(GateRef func, GateRef frameState,
1640                                                  Label *checkAlreadyDeopt, Label *exit)
1641 {
1642     GateRef isCompiled = builder_.JudgeAotAndFastCall(func, CircuitBuilder::JudgeMethodType::HAS_AOT);
1643     BRANCH_CIR_LIKELY(isCompiled, exit, checkAlreadyDeopt);
1644     builder_.Bind(checkAlreadyDeopt);
1645     {
1646         GateRef glue = glue_;
1647         GateRef method = builder_.GetMethodFromFunction(glue, func);
1648         GateRef hasDeopt = builder_.AlreadyDeopt(method);
1649         builder_.DeoptCheck(hasDeopt, frameState, DeoptType::CALLTARGETNOTCOMPILED);
1650         builder_.Jump(exit);
1651     }
1652     builder_.Bind(exit);
1653 }
1654 
LowerCallTargetIsCompiledCheck(GateRef gate)1655 void TypedHCRLowering::LowerCallTargetIsCompiledCheck(GateRef gate)
1656 {
1657     Environment env(gate, circuit_, &builder_);
1658     Label checkAlreadyDeopt(&builder_);
1659     Label exit(&builder_);
1660     GateRef func = acc_.GetValueIn(gate, 0);
1661     GateRef frameState = acc_.GetFrameState(gate);
1662     builder_.IsCallableCheck(func, frameState);
1663     CallTargetIsCompiledCheck(func, frameState, &checkAlreadyDeopt, &exit);
1664     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1665 }
1666 
LowerJSCallTargetTypeCheck(GateRef gate,GateRef glue)1667 void TypedHCRLowering::LowerJSCallTargetTypeCheck(GateRef gate, GateRef glue)
1668 {
1669     Environment env(gate, circuit_, &builder_);
1670     Label checkAlreadyDeopt(&builder_);
1671     Label exit(&builder_);
1672     ArgumentAccessor *argAcc = circuit_->GetArgumentAccessor();
1673     GateRef frameState = GetFrameState(gate);
1674     GateRef sharedConstPool = argAcc->GetFrameArgsIn(frameState, FrameArgIdx::SHARED_CONST_POOL);
1675     auto func = acc_.GetValueIn(gate, 0);
1676     auto methodIndex = acc_.GetValueIn(gate, 1);
1677     builder_.IsCallableCheck(func, frameState);
1678     CallTargetIsCompiledCheck(func, frameState, &checkAlreadyDeopt, &exit);
1679 
1680     GateRef funcMethodTarget = builder_.GetMethodFromFunction(glue, func);
1681     GateRef methodTarget = builder_.GetValueFromTaggedArray(glue, sharedConstPool, methodIndex);
1682     GateRef check = builder_.Equal(funcMethodTarget, methodTarget);
1683     builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT2);
1684     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1685 }
1686 
LowerJSFastCallTargetTypeCheck(GateRef gate,GateRef glue)1687 void TypedHCRLowering::LowerJSFastCallTargetTypeCheck(GateRef gate, GateRef glue)
1688 {
1689     Environment env(gate, circuit_, &builder_);
1690     Label checkAlreadyDeopt(&builder_);
1691     Label exit(&builder_);
1692     ArgumentAccessor *argAcc = circuit_->GetArgumentAccessor();
1693     GateRef frameState = GetFrameState(gate);
1694     GateRef sharedConstPool = argAcc->GetFrameArgsIn(frameState, FrameArgIdx::SHARED_CONST_POOL);
1695     auto func = acc_.GetValueIn(gate, 0);
1696     auto methodIndex = acc_.GetValueIn(gate, 1);
1697     builder_.IsCallableCheck(func, frameState);
1698     CallTargetIsCompiledCheck(func, frameState, &checkAlreadyDeopt, &exit);
1699 
1700     GateRef funcMethodTarget = builder_.GetMethodFromFunction(glue, func);
1701     GateRef methodTarget = builder_.GetValueFromTaggedArray(glue, sharedConstPool, methodIndex);
1702     GateRef check = builder_.Equal(funcMethodTarget, methodTarget);
1703     builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT1);
1704     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1705 }
1706 
LowerJSCallThisTargetTypeCheck(GateRef gate,GateRef glue)1707 void TypedHCRLowering::LowerJSCallThisTargetTypeCheck(GateRef gate, GateRef glue)
1708 {
1709     Environment env(gate, circuit_, &builder_);
1710     Label checkAlreadyDeopt(&builder_);
1711     Label exit(&builder_);
1712     GateRef frameState = GetFrameState(gate);
1713     auto func = acc_.GetValueIn(gate, 0);
1714     builder_.IsCallableCheck(func, frameState);
1715     CallTargetIsCompiledCheck(func, frameState, &checkAlreadyDeopt, &exit);
1716 
1717     GateRef methodId = builder_.GetMethodId(glue, func);
1718     GateRef check = builder_.Equal(methodId, acc_.GetValueIn(gate, 1));
1719     builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT3);
1720     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1721 }
1722 
LowerJSNoGCCallThisTargetTypeCheck(GateRef gate,GateRef glue)1723 void TypedHCRLowering::LowerJSNoGCCallThisTargetTypeCheck(GateRef gate, GateRef glue)
1724 {
1725     Environment env(gate, circuit_, &builder_);
1726     Label checkAlreadyDeopt(&builder_);
1727     Label exit(&builder_);
1728     GateRef frameState = GetFrameState(gate);
1729     auto func = acc_.GetValueIn(gate, 0);
1730     builder_.IsCallableCheck(func, frameState);
1731     CallTargetIsCompiledCheck(func, frameState, &checkAlreadyDeopt, &exit);
1732 
1733     GateRef methodId = builder_.GetMethodId(glue, func);
1734     GateRef check = builder_.Equal(methodId, acc_.GetValueIn(gate, 1));
1735     builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT4);
1736     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1737 }
1738 
LowerJSFastCallThisTargetTypeCheck(GateRef gate,GateRef glue)1739 void TypedHCRLowering::LowerJSFastCallThisTargetTypeCheck(GateRef gate, GateRef glue)
1740 {
1741     Environment env(gate, circuit_, &builder_);
1742     Label checkAlreadyDeopt(&builder_);
1743     Label exit(&builder_);
1744     GateRef frameState = GetFrameState(gate);
1745     auto func = acc_.GetValueIn(gate, 0);
1746     builder_.IsCallableCheck(func, frameState);
1747     CallTargetIsCompiledCheck(func, frameState, &checkAlreadyDeopt, &exit);
1748 
1749     GateRef methodId = builder_.GetMethodId(glue, func);
1750     GateRef check = builder_.Equal(methodId, acc_.GetValueIn(gate, 1));
1751     builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT2);
1752     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1753 }
1754 
LowerJSNoGCFastCallThisTargetTypeCheck(GateRef gate,GateRef glue)1755 void TypedHCRLowering::LowerJSNoGCFastCallThisTargetTypeCheck(GateRef gate, GateRef glue)
1756 {
1757     Environment env(gate, circuit_, &builder_);
1758     Label checkAlreadyDeopt(&builder_);
1759     Label exit(&builder_);
1760     GateRef frameState = GetFrameState(gate);
1761     auto func = acc_.GetValueIn(gate, 0);
1762     builder_.IsCallableCheck(func, frameState);
1763     CallTargetIsCompiledCheck(func, frameState, &checkAlreadyDeopt, &exit);
1764 
1765     GateRef methodId = builder_.GetMethodId(glue, func);
1766     GateRef check = builder_.Equal(methodId, acc_.GetValueIn(gate, 1));
1767     builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT3);
1768     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1769 }
1770 
LowerJSNewObjRangeCallTargetCheck(GateRef gate,GateRef glue)1771 void TypedHCRLowering::LowerJSNewObjRangeCallTargetCheck(GateRef gate, GateRef glue)
1772 {
1773     Environment env(gate, circuit_, &builder_);
1774     GateRef frameState = GetFrameState(gate);
1775     auto ctor = acc_.GetValueIn(gate, 0);
1776     builder_.HeapObjectCheck(ctor, frameState);
1777     GateRef isJsFunc = builder_.IsJSFunction(glue, ctor);
1778     builder_.DeoptCheck(isJsFunc, frameState, DeoptType::NOTJSNEWCALLTGT);
1779     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1780 }
1781 
LowerCallTargetCheck(GateRef gate)1782 void TypedHCRLowering::LowerCallTargetCheck(GateRef gate)
1783 {
1784     Environment env(gate, circuit_, &builder_);
1785     GateRef frameState = GetFrameState(gate);
1786 
1787     BuiltinLowering lowering(circuit_, builder_.GetCompilationConfig(), traceBuiltins_);
1788     GateRef funcheck = lowering.LowerCallTargetCheck(&env, gate);
1789     GateRef check = lowering.CheckPara(gate, funcheck);
1790     builder_.DeoptCheck(check, frameState, DeoptType::NOTCALLTGT1);
1791 
1792     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1793 }
1794 
LowerJSInlineTargetTypeCheck(GateRef gate,GateRef glue)1795 void TypedHCRLowering::LowerJSInlineTargetTypeCheck(GateRef gate, GateRef glue)
1796 {
1797     Environment env(gate, circuit_, &builder_);
1798     GateRef frameState = GetFrameState(gate);
1799     auto func = acc_.GetValueIn(gate, 0);
1800     builder_.HeapObjectCheck(func, frameState);
1801     GateRef isFunction = builder_.IsJSFunction(glue, func);
1802     builder_.DeoptCheck(isFunction, frameState, DeoptType::NOTJSFUNCTION);
1803     GateRef check = builder_.Equal(builder_.GetMethodId(glue, func), acc_.GetValueIn(gate, 1));
1804     builder_.DeoptCheck(check, frameState, DeoptType::INLINEFAIL1);
1805     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1806 }
1807 
LowerJSInlineTargetHeapConstantCheck(GateRef gate)1808 void TypedHCRLowering::LowerJSInlineTargetHeapConstantCheck(GateRef gate)
1809 {
1810     Environment env(gate, circuit_, &builder_);
1811     GateRef frameState = GetFrameState(gate);
1812     auto func = acc_.GetValueIn(gate, 0);
1813     auto heapConstant = acc_.GetValueIn(gate, 1); // 1: the second value, heapConstant
1814     builder_.DeoptCheck(builder_.Equal(func, heapConstant), frameState, DeoptType::NOTCALLTARGETHEAPOBJECT);
1815     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1816 }
1817 
LowerInlineSuperCtorCheck(GateRef glue,GateRef gate)1818 void TypedHCRLowering::LowerInlineSuperCtorCheck(GateRef glue, GateRef gate)
1819 {
1820     Environment env(gate, circuit_, &builder_);
1821     GateRef frameState = GetFrameState(gate);
1822     auto func = acc_.GetValueIn(gate, 0);
1823     GateRef newTarget = acc_.GetValueIn(gate, 2); // 2: newTarget
1824     GateRef constant = acc_.GetValueIn(gate, 1); // 1: Heap constant or method ID
1825     GateRef check = Circuit::NullGate();
1826     if (acc_.GetOpCode(constant) == OpCode::HEAP_CONSTANT) {
1827         check = LogicAndBuilder(&env)
1828             .And(builder_.Equal(func, constant))
1829             .And(builder_.BoolNot(builder_.TaggedIsUndefined(newTarget)))
1830             .Done();
1831     } else {
1832         builder_.HeapObjectCheck(func, frameState);
1833         check = LogicAndBuilder(&env)
1834             .And(builder_.IsJSFunction(glue, func))
1835             .And(builder_.IsConstructor(glue, func))
1836             .And(builder_.Equal(builder_.GetMethodId(glue, func), acc_.GetValueIn(gate, 1)))
1837             .And(builder_.BoolNot(builder_.TaggedIsUndefined(newTarget)))
1838             .Done();
1839     }
1840     builder_.DeoptCheck(check, frameState, DeoptType::INLINESUPERFAIL);
1841     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1842 }
1843 
LowerTypedNewAllocateThis(GateRef gate,GateRef glue)1844 void TypedHCRLowering::LowerTypedNewAllocateThis(GateRef gate, GateRef glue)
1845 {
1846     Environment env(gate, circuit_, &builder_);
1847     ArgumentAccessor *argAcc = circuit_->GetArgumentAccessor();
1848     GateRef ctor = acc_.GetValueIn(gate, 0); // 0: 1st argument
1849     GateRef ihclass = acc_.GetValueIn(gate, 1); // 1: 2nd argument
1850     GateRef size = acc_.GetValueIn(gate, 2); // 2: 3rd argument
1851     Label isBase(&builder_);
1852     Label exit(&builder_);
1853     DEFVALUE(thisObj, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1854     BRANCH_CIR(builder_.IsBase(glue, ctor), &isBase, &exit);
1855     builder_.Bind(&isBase);
1856     if (compilationEnv_->IsJitCompiler()) {
1857         thisObj = builder_.CallStub(glue, gate, CommonStubCSigns::NewJSObject, {glue, ihclass, size});
1858         builder_.Jump(&exit);
1859     } else {
1860         NewObjectStubBuilder newBuilder(builder_.GetCurrentEnvironment());
1861         newBuilder.SetParameters(glue, 0);
1862         newBuilder.NewJSObject(&thisObj, &exit, ihclass, size);
1863     }
1864     builder_.Bind(&exit);
1865     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *thisObj);
1866 }
1867 
LowerTypedSuperAllocateThis(GateRef gate,GateRef glue)1868 void TypedHCRLowering::LowerTypedSuperAllocateThis(GateRef gate, GateRef glue)
1869 {
1870     Environment env(gate, circuit_, &builder_);
1871     GateRef superCtor = acc_.GetValueIn(gate, 0);
1872     GateRef newTarget = acc_.GetValueIn(gate, 1);
1873 
1874     DEFVALUE(thisObj, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1875     Label allocate(&builder_);
1876     Label exit(&builder_);
1877 
1878     GateRef isBase = builder_.IsBase(glue, superCtor);
1879     BRANCH_CIR(isBase, &allocate, &exit);
1880     builder_.Bind(&allocate);
1881     {
1882         thisObj = builder_.CallStub(glue, gate, CommonStubCSigns::FastSuperAllocateThis,
1883             { glue, superCtor, newTarget });
1884         builder_.Jump(&exit);
1885     }
1886     builder_.Bind(&exit);
1887     ReplaceHirWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), *thisObj);
1888 }
1889 
LowerGetSuperConstructor(GateRef glue,GateRef gate)1890 void TypedHCRLowering::LowerGetSuperConstructor(GateRef glue, GateRef gate)
1891 {
1892     Environment env(gate, circuit_, &builder_);
1893     GateRef ctor = acc_.GetValueIn(gate, 0);
1894     GateRef hclass = builder_.LoadHClassByConstOffset(glue, ctor);
1895     GateRef superCtor = builder_.LoadPrototype(glue_, hclass);
1896     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), superCtor);
1897 }
1898 
GetVarType(PropertyLookupResult plr)1899 VariableType TypedHCRLowering::GetVarType(PropertyLookupResult plr)
1900 {
1901     if (plr.GetRepresentation() == Representation::DOUBLE) {
1902         return kungfu::VariableType::FLOAT64();
1903     } else if (plr.GetRepresentation() == Representation::INT) {
1904         return kungfu::VariableType::INT32();
1905     } else {
1906         return kungfu::VariableType::INT64();
1907     }
1908 }
1909 
GetLengthFromSupers(GateRef supers)1910 GateRef TypedHCRLowering::GetLengthFromSupers(GateRef supers)
1911 {
1912     return builder_.LoadConstOffset(VariableType::INT32(), supers, TaggedArray::EXTRA_LENGTH_OFFSET);
1913 }
1914 
GetValueFromSupers(GateRef supers,size_t index)1915 GateRef TypedHCRLowering::GetValueFromSupers(GateRef supers, size_t index)
1916 {
1917     GateRef val = builder_.LoadFromTaggedArray(supers, index);
1918     return builder_.LoadObjectFromWeakRef(val);
1919 }
1920 
CallAccessor(GateRef glue,GateRef gate,GateRef function,GateRef receiver,AccessorMode mode,GateRef value)1921 GateRef TypedHCRLowering::CallAccessor(GateRef glue, GateRef gate, GateRef function, GateRef receiver,
1922     AccessorMode mode, GateRef value)
1923 {
1924     if (g_isEnableCMCGC) {
1925         builder_.CallNGCRuntime(glue, RTSTUB_ID(CopyCallTarget), Gate::InvalidGateRef, {glue, function}, glue);
1926     }
1927     const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(JSCall));
1928     GateRef target = builder_.IntPtr(RTSTUB_ID(JSCall));
1929     GateRef newTarget = builder_.Undefined();
1930     GateRef argc = builder_.Int64(NUM_MANDATORY_JSFUNC_ARGS + (mode == AccessorMode::SETTER ? 1 : 0));  // 1: value
1931     GateRef argv = builder_.IntPtr(0);
1932     std::vector<GateRef> args { glue, argc, argv, function, newTarget, receiver };
1933     if (mode == AccessorMode::SETTER) {
1934         args.emplace_back(value);
1935     }
1936 
1937     return builder_.Call(cs, glue, target, builder_.GetDepend(), args, gate);
1938 }
1939 
ReplaceHirWithPendingException(GateRef hirGate,GateRef glue,GateRef state,GateRef depend,GateRef value)1940 void TypedHCRLowering::ReplaceHirWithPendingException(GateRef hirGate, GateRef glue, GateRef state, GateRef depend,
1941                                                       GateRef value)
1942 {
1943     auto condition = builder_.HasPendingException(glue, compilationEnv_);
1944     GateRef ifBranch = builder_.Branch(state, condition, 1, BranchWeight::DEOPT_WEIGHT, "checkException");
1945     GateRef ifTrue = builder_.IfTrue(ifBranch);
1946     GateRef ifFalse = builder_.IfFalse(ifBranch);
1947     GateRef eDepend = builder_.DependRelay(ifTrue, depend);
1948     GateRef sDepend = builder_.DependRelay(ifFalse, depend);
1949 
1950     StateDepend success(ifFalse, sDepend);
1951     StateDepend exception(ifTrue, eDepend);
1952     acc_.ReplaceHirWithIfBranch(hirGate, success, exception, value);
1953 }
1954 
LowerLookupHolder(GateRef glue,GateRef gate)1955 void TypedHCRLowering::LowerLookupHolder(GateRef glue, GateRef gate)
1956 {
1957     Environment env(gate, circuit_, &builder_);
1958     ASSERT(acc_.GetNumValueIn(gate) == 3);  // 3: receiver, holderHC, jsFunc
1959     GateRef receiver = acc_.GetValueIn(gate, 0);
1960     GateRef holderHCIndex = acc_.GetValueIn(gate, 1);
1961     GateRef unsharedConstPool = acc_.GetValueIn(gate, 2);  // 2: constpool
1962     GateRef holderHC = builder_.LoadHClassFromConstpool(unsharedConstPool,
1963         acc_.GetConstantValue(holderHCIndex));
1964     GateRef frameState = acc_.GetFrameState(gate);
1965     DEFVALUE(holder, (&builder_), VariableType::JS_ANY(), receiver);
1966     Label loopHead(&builder_);
1967     Label exit(&builder_);
1968     Label lookUpProto(&builder_);
1969     builder_.Jump(&loopHead);
1970 
1971     builder_.LoopBegin(&loopHead);
1972     builder_.DeoptCheck(builder_.TaggedIsNotNull(*holder), frameState, DeoptType::INCONSISTENTHCLASS13);
1973     auto curHC = builder_.LoadHClassByConstOffset(glue, *holder);
1974     BRANCH_CIR(builder_.Equal(curHC, holderHC), &exit, &lookUpProto);
1975 
1976     builder_.Bind(&lookUpProto);
1977     holder = builder_.LoadPrototype(glue_, curHC);
1978     builder_.LoopEnd(&loopHead);
1979 
1980     builder_.Bind(&exit);
1981     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *holder);
1982 }
1983 
LowerLoadGetter(GateRef gate,GateRef glue)1984 void TypedHCRLowering::LowerLoadGetter(GateRef gate, GateRef glue)
1985 {
1986     Environment env(gate, circuit_, &builder_);
1987     ASSERT(acc_.GetNumValueIn(gate) == 2);  // 2: holder, plr
1988     GateRef holder = acc_.GetValueIn(gate, 0);
1989     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1990     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1991     ASSERT(plr.IsAccessor());
1992 
1993     GateRef getter;
1994     if (plr.IsInlinedProps()) {
1995         auto acceessorData = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset());
1996         getter = builder_.LoadConstOffset(VariableType::JS_ANY(), acceessorData, AccessorData::GETTER_OFFSET);
1997     } else {
1998         auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
1999         auto acceessorData = builder_.GetValueFromTaggedArray(glue, properties, builder_.Int32(plr.GetOffset()));
2000         getter = builder_.LoadConstOffset(VariableType::JS_ANY(), acceessorData, AccessorData::GETTER_OFFSET);
2001     }
2002     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), getter);
2003 }
2004 
LowerLoadSetter(GateRef gate,GateRef glue)2005 void TypedHCRLowering::LowerLoadSetter(GateRef gate, GateRef glue)
2006 {
2007     Environment env(gate, circuit_, &builder_);
2008     ASSERT(acc_.GetNumValueIn(gate) == 2);  // 2: holder, plr
2009     GateRef holder = acc_.GetValueIn(gate, 0);
2010     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
2011     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
2012     ASSERT(plr.IsAccessor());
2013 
2014     GateRef setter;
2015     if (plr.IsInlinedProps()) {
2016         auto acceessorData = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset());
2017         setter = builder_.LoadConstOffset(VariableType::JS_ANY(), acceessorData, AccessorData::SETTER_OFFSET);
2018     } else {
2019         auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
2020         auto acceessorData = builder_.GetValueFromTaggedArray(glue, properties, builder_.Int32(plr.GetOffset()));
2021         setter = builder_.LoadConstOffset(VariableType::JS_ANY(), acceessorData, AccessorData::SETTER_OFFSET);
2022     }
2023     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), setter);
2024 }
2025 
LowerPrototypeCheck(GateRef glue,GateRef gate)2026 void TypedHCRLowering::LowerPrototypeCheck(GateRef glue, GateRef gate)
2027 {
2028     Environment env(gate, circuit_, &builder_);
2029     GateRef unsharedConstPool = acc_.GetValueIn(gate, 0);
2030     GateRef frameState = acc_.GetFrameState(gate);
2031 
2032     uint32_t hclassIndex = acc_.GetHClassIndex(gate);
2033     auto expectedReceiverHC = builder_.LoadHClassFromConstpool(unsharedConstPool, hclassIndex);
2034 
2035     auto prototype = builder_.LoadPrototype(glue_, expectedReceiverHC);
2036     auto protoHClass = builder_.LoadHClassByConstOffset(glue, prototype);
2037     auto marker = builder_.LoadProtoChangeMarker(glue, protoHClass);
2038     builder_.DeoptCheck(builder_.TaggedIsNotNull(marker), frameState, DeoptType::PROTOTYPECHANGED1);
2039     auto check = LogicAndBuilder(&env)
2040         .And(builder_.BoolNot(builder_.GetHasChanged(marker)))
2041         .And(builder_.BoolNot(builder_.GetAccessorHasChanged(marker)))
2042         .Done();
2043     builder_.DeoptCheck(check, frameState, DeoptType::INLINEFAIL2);
2044     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2045     return;
2046 }
2047 
LowerStringEqual(GateRef gate,GateRef glue)2048 void TypedHCRLowering::LowerStringEqual(GateRef gate, GateRef glue)
2049 {
2050     Environment env(gate, circuit_, &builder_);
2051     GateRef left = acc_.GetValueIn(gate, 0);
2052     GateRef right = acc_.GetValueIn(gate, 1);
2053     GateRef leftLength = GetLengthFromString(left);
2054     GateRef rightLength = GetLengthFromString(right);
2055 
2056     DEFVALUE(result, (&builder_), VariableType::BOOL(), builder_.False());
2057     Label lenEqual(&builder_);
2058     Label exit(&builder_);
2059     BRANCH_CIR(builder_.Equal(leftLength, rightLength), &lenEqual, &exit);
2060     builder_.Bind(&lenEqual);
2061     {
2062         result = builder_.CallStub(glue, gate, CommonStubCSigns::FastStringEqual,
2063                                    {glue, left, right, circuit_->GetGlobalEnvCache()});
2064         builder_.Jump(&exit);
2065     }
2066     builder_.Bind(&exit);
2067     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
2068 }
2069 
LowerTypeOfCheck(GateRef gate)2070 void TypedHCRLowering::LowerTypeOfCheck(GateRef gate)
2071 {
2072     Environment env(gate, circuit_, &builder_);
2073     GateRef frameState = GetFrameState(gate);
2074     GateRef glue = glue_;
2075     GateRef value = acc_.GetValueIn(gate, 0);
2076     GateTypeAccessor accessor(acc_.TryGetValue(gate));
2077     ParamType type = accessor.GetParamType();
2078     GateRef check = Circuit::NullGate();
2079     if (type.IsNumberType()) {
2080         check = builder_.TaggedIsNumber(value);
2081     } else if (type.IsBooleanType()) {
2082         check = builder_.TaggedIsBoolean(value);
2083     } else if (type.IsNullType()) {
2084         check = builder_.TaggedIsNull(value);
2085     } else if (type.IsUndefinedType()) {
2086         check = builder_.TaggedIsUndefined(value);
2087     } else {
2088         // NOTICE-PGO: wx add support for builtin(Function Object ArrayKind)
2089         builder_.DeoptCheck(builder_.TaggedIsHeapObject(value, compilationEnv_),
2090                             frameState, DeoptType::INCONSISTENTTYPE1);
2091         if (type.IsStringType()) {
2092             check = builder_.TaggedIsString(glue, value);
2093         } else if (type.IsBigIntType()) {
2094             check = builder_.IsJsType(glue, value, JSType::BIGINT);
2095         } else if (type.IsSymbolType()) {
2096             check = builder_.IsJsType(glue, value, JSType::SYMBOL);
2097         } else {
2098             UNREACHABLE();
2099         }
2100     }
2101 
2102     builder_.DeoptCheck(check, frameState, DeoptType::INCONSISTENTTYPE1);
2103     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2104 }
2105 
LowerTypeOf(GateRef gate,GateRef glue)2106 void TypedHCRLowering::LowerTypeOf(GateRef gate, GateRef glue)
2107 {
2108     Environment env(gate, circuit_, &builder_);
2109     GateTypeAccessor accessor(acc_.TryGetValue(gate));
2110     ParamType type = accessor.GetParamType();
2111     GateRef gConstAddr = builder_.LoadWithoutBarrier(VariableType::JS_POINTER(), glue,
2112         builder_.IntPtr(JSThread::GlueData::GetGlobalConstOffset(builder_.GetCompilationConfig()->Is32Bit())));
2113     ConstantIndex index;
2114     // NOTICE-PGO: wx add support for builtin(Function Object ArrayKind)
2115     if (type.IsNumberType()) {
2116         index = ConstantIndex::NUMBER_STRING_INDEX;
2117     } else if (type.IsBooleanType()) {
2118         index = ConstantIndex::BOOLEAN_STRING_INDEX;
2119     } else if (type.IsNullType()) {
2120         index = ConstantIndex::OBJECT_STRING_INDEX;
2121     } else if (type.IsUndefinedType()) {
2122         index = ConstantIndex::UNDEFINED_STRING_INDEX;
2123     } else if (type.IsStringType()) {
2124         index = ConstantIndex::STRING_STRING_INDEX;
2125     } else if (type.IsBigIntType()) {
2126         index = ConstantIndex::BIGINT_STRING_INDEX;
2127     } else if (type.IsSymbolType()) {
2128         index = ConstantIndex::SYMBOL_STRING_INDEX;
2129     } else {
2130         UNREACHABLE();
2131     }
2132 
2133     GateRef result = builder_.LoadWithoutBarrier(VariableType::JS_POINTER(), gConstAddr,
2134                                                  builder_.GetGlobalConstantOffset(index));
2135     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
2136 }
2137 
LowerTypedConstructorCheck(GateRef gate,GateRef glue)2138 void TypedHCRLowering::LowerTypedConstructorCheck(GateRef gate, GateRef glue)
2139 {
2140     static const std::map<size_t, DeoptType> deoptType = {
2141         {GlobalEnv::ARRAY_FUNCTION_INDEX, DeoptType::NEWBUILTINCTORARRAY},
2142         {GlobalEnv::OBJECT_FUNCTION_INDEX, DeoptType::NEWBUILTINCTOROBJECT},
2143         {GlobalEnv::FLOAT32_ARRAY_FUNCTION_INDEX, DeoptType::NEWBUILTINCTORFLOAT32ARRAY},
2144         {GlobalEnv::BOOLEAN_FUNCTION_INDEX, DeoptType::NEWBUILTINCTORBOOLEAN},
2145         {GlobalEnv::BUILTINS_MAP_FUNCTION_INDEX, DeoptType::NEWBUILTINCTORMAP},
2146         {GlobalEnv::BUILTINS_SET_FUNCTION_INDEX, DeoptType::NEWBUILTINCTORSET},
2147         {GlobalEnv::DATE_FUNCTION_INDEX, DeoptType::NEWBUILTINCTORDATE},
2148         {GlobalEnv::ERROR_FUNCTION_INDEX, DeoptType::NEWBUILTINCTORERROR},
2149     };
2150     Environment env(gate, circuit_, &builder_);
2151     size_t functionIndex = static_cast<size_t>(acc_.TryGetValue(gate));
2152     GateRef frameState = GetFrameState(gate);
2153     GateRef newTarget = acc_.GetValueIn(gate, 0);
2154     GateRef globalEnv = circuit_->GetGlobalEnvCache();
2155     GateRef builtinFunc = builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, functionIndex);
2156     GateRef check = builder_.Equal(builtinFunc, newTarget);
2157     auto type =
2158         deoptType.find(functionIndex) != deoptType.end() ? deoptType.at(functionIndex) : DeoptType::NEWBUILTINCTORFAIL1;
2159     builder_.DeoptCheck(check, frameState, type);
2160     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2161 }
2162 
LowerArrayConstructorCheck(GateRef gate,GateRef glue)2163 void TypedHCRLowering::LowerArrayConstructorCheck(GateRef gate, GateRef glue)
2164 {
2165     Environment env(gate, circuit_, &builder_);
2166     GateRef frameState = GetFrameState(gate);
2167     GateRef newTarget = acc_.GetValueIn(gate, 0);
2168     Label isHeapObject(&builder_);
2169     Label exit(&builder_);
2170     DEFVALUE(check, (&builder_), VariableType::BOOL(), builder_.True());
2171     check = builder_.TaggedIsHeapObject(newTarget, compilationEnv_);
2172     BRANCH_CIR(*check, &isHeapObject, &exit);
2173     builder_.Bind(&isHeapObject);
2174     {
2175         Label isJSFunction(&builder_);
2176         check = builder_.IsJSFunction(glue, newTarget);
2177         BRANCH_CIR(*check, &isJSFunction, &exit);
2178         builder_.Bind(&isJSFunction);
2179         {
2180             Label getHclass(&builder_);
2181             GateRef globalEnv = circuit_->GetGlobalEnvCache();
2182             GateRef arrayFunc =
2183                 builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
2184             check = builder_.Equal(arrayFunc, newTarget);
2185             BRANCH_CIR(*check, &getHclass, &exit);
2186             builder_.Bind(&getHclass);
2187             {
2188                 GateRef intialHClass = builder_.Load(VariableType::JS_ANY(), glue, newTarget,
2189                                                      builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2190                 check = builder_.IsJSHClass(glue, intialHClass);
2191                 builder_.Jump(&exit);
2192             }
2193         }
2194     }
2195     builder_.Bind(&exit);
2196     builder_.DeoptCheck(*check, frameState, DeoptType::NEWBUILTINCTORARRAY);
2197     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2198 }
2199 
LowerArrayConstructor(GateRef gate,GateRef glue)2200 void TypedHCRLowering::LowerArrayConstructor(GateRef gate, GateRef glue)
2201 {
2202     Environment env(gate, circuit_, &builder_);
2203     if (acc_.GetNumValueIn(gate) == 1) {
2204         NewArrayConstructorWithNoArgs(gate, glue);
2205         return;
2206     }
2207     ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: new target and arg0
2208     DEFVALUE(res, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
2209     Label slowPath(&builder_);
2210     Label exit(&builder_);
2211     GateRef newTarget = acc_.GetValueIn(gate, 0);
2212     GateRef arg0 = acc_.GetValueIn(gate, 1);
2213     GateRef intialHClass =
2214         builder_.Load(VariableType::JS_ANY(), glue, newTarget, builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2215     DEFVALUE(arrayLength, (&builder_), VariableType::INT64(), builder_.Int64(0));
2216     Label argIsNumber(&builder_);
2217     Label arrayCreate(&builder_);
2218     BRANCH_CIR(builder_.TaggedIsNumber(arg0), &argIsNumber, &slowPath);
2219     builder_.Bind(&argIsNumber);
2220     {
2221         Label argIsInt(&builder_);
2222         Label argIsDouble(&builder_);
2223         BRANCH_CIR(builder_.TaggedIsInt(arg0), &argIsInt, &argIsDouble);
2224         builder_.Bind(&argIsInt);
2225         {
2226             Label validIntLength(&builder_);
2227             GateRef intLen = builder_.GetInt64OfTInt(arg0);
2228             GateRef isGEZero = builder_.Int64GreaterThanOrEqual(intLen, builder_.Int64(0));
2229             GateRef isLEMaxLen = builder_.Int64LessThanOrEqual(intLen, builder_.Int64(JSArray::MAX_ARRAY_INDEX));
2230             BRANCH_CIR(builder_.BitAnd(isGEZero, isLEMaxLen), &validIntLength, &slowPath);
2231             builder_.Bind(&validIntLength);
2232             {
2233                 arrayLength = intLen;
2234                 builder_.Jump(&arrayCreate);
2235             }
2236         }
2237         builder_.Bind(&argIsDouble);
2238         {
2239             Label validDoubleLength(&builder_);
2240             GateRef doubleLength = builder_.GetDoubleOfTDouble(arg0);
2241             GateRef doubleToInt = builder_.TruncDoubleToInt(glue, doubleLength, base::INT32_BITS);
2242             GateRef intToDouble = builder_.CastInt64ToFloat64(builder_.SExtInt32ToInt64(doubleToInt));
2243             GateRef doubleEqual = builder_.DoubleEqual(doubleLength, intToDouble);
2244             GateRef doubleLEMaxLen =
2245                 builder_.DoubleLessThanOrEqual(doubleLength, builder_.Double(JSArray::MAX_ARRAY_INDEX));
2246             BRANCH_CIR(builder_.BitAnd(doubleEqual, doubleLEMaxLen), &validDoubleLength, &slowPath);
2247             builder_.Bind(&validDoubleLength);
2248             {
2249                 arrayLength = builder_.SExtInt32ToInt64(doubleToInt);
2250                 builder_.Jump(&arrayCreate);
2251             }
2252         }
2253     }
2254     builder_.Bind(&arrayCreate);
2255     {
2256         Label lengthValid(&builder_);
2257         BRANCH_CIR(
2258             builder_.Int64GreaterThan(*arrayLength, builder_.Int64(JSObject::MAX_GAP)), &slowPath, &lengthValid);
2259         builder_.Bind(&lengthValid);
2260         {
2261             NewObjectStubBuilder newBuilder(builder_.GetCurrentEnvironment(), circuit_->GetGlobalEnvCache());
2262             newBuilder.SetParameters(glue, 0);
2263             res = newBuilder.NewJSArrayWithSize(intialHClass, *arrayLength);
2264             GateRef lengthOffset = builder_.IntPtr(JSArray::LENGTH_OFFSET);
2265             builder_.Store(VariableType::INT32(), glue, *res, lengthOffset, builder_.TruncInt64ToInt32(*arrayLength));
2266             GateRef accessor = builder_.GetGlobalConstantValue(ConstantIndex::ARRAY_LENGTH_ACCESSOR);
2267             builder_.SetPropertyInlinedProps(glue, *res, intialHClass, accessor,
2268                 builder_.Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_ANY());
2269             builder_.SetExtensibleToBitfield(glue, *res, true);
2270             builder_.Jump(&exit);
2271         }
2272     }
2273     builder_.Bind(&slowPath);
2274     {
2275         size_t range = acc_.GetNumValueIn(gate);
2276         std::vector<GateRef> args(range);
2277         for (size_t i = 0; i < range; ++i) {
2278             args[i] = acc_.GetValueIn(gate, i);
2279         }
2280         res = LowerCallRuntime(glue, gate, RTSTUB_ID(OptNewObjRange), args, true);
2281         builder_.Jump(&exit);
2282     }
2283     builder_.Bind(&exit);
2284     ReplaceGateWithPendingException(glue, gate, builder_.GetState(), builder_.GetDepend(), *res);
2285 }
2286 
LowerFloat32ArrayConstructorCheck(GateRef gate,GateRef glue)2287 void TypedHCRLowering::LowerFloat32ArrayConstructorCheck(GateRef gate, GateRef glue)
2288 {
2289     Environment env(gate, circuit_, &builder_);
2290     GateRef frameState = GetFrameState(gate);
2291     GateRef newTarget = acc_.GetValueIn(gate, 0);
2292     GateRef globalEnv = circuit_->GetGlobalEnvCache();
2293     GateRef arrayFunc =
2294         builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::FLOAT32_ARRAY_FUNCTION_INDEX);
2295     GateRef check = builder_.Equal(arrayFunc, newTarget);
2296     builder_.DeoptCheck(check, frameState, DeoptType::NEWBUILTINCTORFLOAT32ARRAY);
2297     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2298 }
2299 
NewFloat32ArrayConstructorWithNoArgs(GateRef gate,GateRef glue)2300 void TypedHCRLowering::NewFloat32ArrayConstructorWithNoArgs(GateRef gate, GateRef glue)
2301 {
2302     NewObjectStubBuilder newBuilder(builder_.GetCurrentEnvironment(), circuit_->GetGlobalEnvCache());
2303     newBuilder.SetParameters(glue, 0);
2304     GateRef res = newBuilder.NewFloat32ArrayWithSize(glue, builder_.Int32(0));
2305     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), res);
2306 }
2307 
ConvertFloat32ArrayConstructorLength(GateRef len,Variable * arrayLength,Label * arrayCreate,Label * slowPath)2308 void TypedHCRLowering::ConvertFloat32ArrayConstructorLength(GateRef len, Variable *arrayLength,
2309                                                             Label *arrayCreate, Label *slowPath)
2310 {
2311     Label argIsNumber(&builder_);
2312     BRANCH_CIR(builder_.TaggedIsNumber(len), &argIsNumber, slowPath);
2313     builder_.Bind(&argIsNumber);
2314     {
2315         Label argIsInt(&builder_);
2316         Label argIsDouble(&builder_);
2317         BRANCH_CIR(builder_.TaggedIsInt(len), &argIsInt, &argIsDouble);
2318         builder_.Bind(&argIsInt);
2319         {
2320             Label validIntLength(&builder_);
2321             GateRef intLen = builder_.GetInt64OfTInt(len);
2322             GateRef isGEZero = builder_.Int64GreaterThanOrEqual(intLen, builder_.Int64(0));
2323             GateRef isLEMaxLen = builder_.Int64LessThanOrEqual(intLen, builder_.Int64(JSObject::MAX_GAP));
2324             BRANCH_CIR(builder_.BitAnd(isGEZero, isLEMaxLen), &validIntLength, slowPath);
2325             builder_.Bind(&validIntLength);
2326             {
2327                 *arrayLength = intLen;
2328                 builder_.Jump(arrayCreate);
2329             }
2330         }
2331         builder_.Bind(&argIsDouble);
2332         {
2333             Label validDoubleLength(&builder_);
2334             GateRef doubleLength = builder_.GetDoubleOfTDouble(len);
2335             GateRef doubleToInt = builder_.TruncDoubleToInt(glue_, doubleLength, base::INT32_BITS);
2336             GateRef intToDouble = builder_.CastInt64ToFloat64(builder_.SExtInt32ToInt64(doubleToInt));
2337             GateRef doubleEqual = builder_.DoubleEqual(doubleLength, intToDouble);
2338             GateRef doubleLEMaxLen =
2339                 builder_.DoubleLessThanOrEqual(doubleLength, builder_.Double(JSObject::MAX_GAP));
2340             BRANCH_CIR(builder_.BitAnd(doubleEqual, doubleLEMaxLen), &validDoubleLength, slowPath);
2341             builder_.Bind(&validDoubleLength);
2342             {
2343                 *arrayLength = builder_.SExtInt32ToInt64(doubleToInt);
2344                 builder_.Jump(arrayCreate);
2345             }
2346         }
2347     }
2348 }
2349 
LowerFloat32ArrayConstructor(GateRef gate,GateRef glue)2350 void TypedHCRLowering::LowerFloat32ArrayConstructor(GateRef gate, GateRef glue)
2351 {
2352     Environment env(gate, circuit_, &builder_);
2353     if (compilationEnv_->IsJitCompiler()) {
2354         GateRef res = Circuit::NullGate();
2355         if (acc_.GetNumValueIn(gate) == 1) {
2356             res = builder_.CallStub(glue, gate, CommonStubCSigns::NewFloat32ArrayWithNoArgs,
2357                                     {glue, circuit_->GetGlobalEnvCache()}, "NewFloat32ArrayWithNoArgs stub");
2358         } else {
2359             ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: new target and arg0
2360             res = builder_.CallStub(
2361                 glue, gate, CommonStubCSigns::NewFloat32Array,
2362                 {glue, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1), circuit_->GetGlobalEnvCache()},
2363                 "NewFloat32Array stub");
2364         }
2365         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), res);
2366         return;
2367     }
2368     if (acc_.GetNumValueIn(gate) == 1) {
2369         NewFloat32ArrayConstructorWithNoArgs(gate, glue);
2370         return;
2371     }
2372     ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: new target and arg0
2373     DEFVALUE(res, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
2374     Label slowPath(&builder_);
2375     Label exit(&builder_);
2376     GateRef ctor = acc_.GetValueIn(gate, 0);
2377     GateRef arg0 = acc_.GetValueIn(gate, 1);
2378     DEFVALUE(arrayLength, (&builder_), VariableType::INT64(), builder_.Int64(0));
2379     Label arrayCreateByLength(&builder_);
2380     Label arrayCreate(&builder_);
2381     ConvertFloat32ArrayConstructorLength(arg0, &arrayLength, &arrayCreateByLength, &arrayCreate);
2382     builder_.Bind(&arrayCreateByLength);
2383     {
2384         NewObjectStubBuilder newBuilder(builder_.GetCurrentEnvironment(), circuit_->GetGlobalEnvCache());
2385         newBuilder.SetParameters(glue, 0);
2386         GateRef truncedLength = builder_.TruncInt64ToInt32(*arrayLength);
2387         res = newBuilder.NewFloat32ArrayWithSize(glue, truncedLength);
2388         builder_.Jump(&exit);
2389     }
2390     builder_.Bind(&arrayCreate);
2391     {
2392         NewObjectStubBuilder newBuilder(builder_.GetCurrentEnvironment(), circuit_->GetGlobalEnvCache());
2393         newBuilder.SetParameters(glue, 0);
2394         GateRef thisObj = newBuilder.NewFloat32ArrayObj(glue);
2395         GateRef argc = builder_.Int64(4); // 4: means func newtarget thisObj arg0
2396         GateRef argv = builder_.IntPtr(0);
2397         std::vector<GateRef> args { glue, argc, argv, ctor, ctor, thisObj, arg0 };
2398         res = builder_.CallNew(gate, args);
2399         builder_.Jump(&exit);
2400     }
2401     builder_.Bind(&exit);
2402     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *res);
2403 }
2404 
NewArrayConstructorWithNoArgs(GateRef gate,GateRef glue)2405 void TypedHCRLowering::NewArrayConstructorWithNoArgs(GateRef gate, GateRef glue)
2406 {
2407     GateRef newTarget = acc_.GetValueIn(gate, 0);
2408     GateRef intialHClass =
2409         builder_.Load(VariableType::JS_ANY(), glue, newTarget, builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2410     GateRef arrayLength = builder_.Int64(0);
2411     NewObjectStubBuilder newBuilder(builder_.GetCurrentEnvironment(), circuit_->GetGlobalEnvCache());
2412     newBuilder.SetParameters(glue, 0);
2413     GateRef res = newBuilder.NewJSArrayWithSize(intialHClass, arrayLength);
2414     GateRef lengthOffset = builder_.IntPtr(JSArray::LENGTH_OFFSET);
2415     builder_.Store(VariableType::INT32(), glue, res, lengthOffset, builder_.TruncInt64ToInt32(arrayLength));
2416     GateRef accessor = builder_.GetGlobalConstantValue(ConstantIndex::ARRAY_LENGTH_ACCESSOR);
2417     builder_.SetPropertyInlinedProps(glue, res, intialHClass, accessor,
2418                                      builder_.Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_ANY());
2419     builder_.SetExtensibleToBitfield(glue, res, true);
2420     ReplaceGateWithPendingException(glue, gate, builder_.GetState(), builder_.GetDepend(), res);
2421 }
2422 
LowerObjectConstructorCheck(GateRef gate,GateRef glue)2423 void TypedHCRLowering::LowerObjectConstructorCheck(GateRef gate, GateRef glue)
2424 {
2425     Environment env(gate, circuit_, &builder_);
2426     GateRef frameState = GetFrameState(gate);
2427     GateRef newTarget = acc_.GetValueIn(gate, 0);
2428     Label isHeapObject(&builder_);
2429     Label exit(&builder_);
2430     DEFVALUE(check, (&builder_), VariableType::BOOL(), builder_.True());
2431     check = builder_.TaggedIsHeapObject(newTarget, compilationEnv_);
2432     BRANCH_CIR(*check, &isHeapObject, &exit);
2433     builder_.Bind(&isHeapObject);
2434     {
2435         Label isJSFunction(&builder_);
2436         check = builder_.IsJSFunction(glue, newTarget);
2437         BRANCH_CIR(*check, &isJSFunction, &exit);
2438         builder_.Bind(&isJSFunction);
2439         {
2440             Label getHclass(&builder_);
2441             GateRef globalEnv = circuit_->GetGlobalEnvCache();
2442             GateRef targetFunc =
2443                 builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::OBJECT_FUNCTION_INDEX);
2444             check = builder_.Equal(targetFunc, newTarget);
2445             BRANCH_CIR(*check, &getHclass, &exit);
2446             builder_.Bind(&getHclass);
2447             {
2448                 GateRef intialHClass = builder_.Load(VariableType::JS_ANY(), glue, newTarget,
2449                                                      builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2450                 check = builder_.IsJSHClass(glue, intialHClass);
2451                 builder_.Jump(&exit);
2452             }
2453         }
2454     }
2455     builder_.Bind(&exit);
2456     builder_.DeoptCheck(*check, frameState, DeoptType::NEWBUILTINCTOROBJECT);
2457     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2458 }
2459 
LowerObjectConstructor(GateRef gate,GateRef glue)2460 void TypedHCRLowering::LowerObjectConstructor(GateRef gate, GateRef glue)
2461 {
2462     Environment env(gate, circuit_, &builder_);
2463     GateRef value = builder_.Undefined();
2464     ASSERT(acc_.GetNumValueIn(gate) <= 2); // 2: new target and arg0
2465     if (acc_.GetNumValueIn(gate) > 1) {
2466         value = acc_.GetValueIn(gate, 1);
2467     }
2468     DEFVALUE(res, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
2469     Label slowPath(&builder_);
2470     Label exit(&builder_);
2471 
2472     Label isHeapObj(&builder_);
2473     Label notHeapObj(&builder_);
2474     BRANCH_CIR(builder_.TaggedIsHeapObject(value, compilationEnv_), &isHeapObj, &notHeapObj);
2475     builder_.Bind(&isHeapObj);
2476     {
2477         Label isEcmaObj(&builder_);
2478         Label notEcmaObj(&builder_);
2479         BRANCH_CIR(builder_.TaggedObjectIsEcmaObject(glue, value), &isEcmaObj, &notEcmaObj);
2480         builder_.Bind(&isEcmaObj);
2481         {
2482             res = value;
2483             builder_.Jump(&exit);
2484         }
2485         builder_.Bind(&notEcmaObj);
2486         {
2487             Label isSymbol(&builder_);
2488             Label notSymbol(&builder_);
2489             BRANCH_CIR(builder_.TaggedIsSymbol(glue, value), &isSymbol, &notSymbol);
2490             builder_.Bind(&isSymbol);
2491             {
2492                 res = NewJSPrimitiveRef(PrimitiveType::PRIMITIVE_SYMBOL, glue, value);
2493                 builder_.Jump(&exit);
2494             }
2495             builder_.Bind(&notSymbol);
2496             {
2497                 Label isBigInt(&builder_);
2498                 BRANCH_CIR(builder_.TaggedIsBigInt(glue, value), &isBigInt, &slowPath);
2499                 builder_.Bind(&isBigInt);
2500                 {
2501                     res = NewJSPrimitiveRef(PrimitiveType::PRIMITIVE_BIGINT, glue, value);
2502                     builder_.Jump(&exit);
2503                 }
2504             }
2505         }
2506     }
2507     builder_.Bind(&notHeapObj);
2508     {
2509         Label isNumber(&builder_);
2510         Label notNumber(&builder_);
2511         BRANCH_CIR(builder_.TaggedIsNumber(value), &isNumber, &notNumber);
2512         builder_.Bind(&isNumber);
2513         {
2514             res = NewJSPrimitiveRef(PrimitiveType::PRIMITIVE_NUMBER, glue, value);
2515             builder_.Jump(&exit);
2516         }
2517         builder_.Bind(&notNumber);
2518         {
2519             Label isBoolean(&builder_);
2520             Label notBoolean(&builder_);
2521             BRANCH_CIR(builder_.TaggedIsBoolean(value), &isBoolean, &notBoolean);
2522             builder_.Bind(&isBoolean);
2523             {
2524                 res = NewJSPrimitiveRef(PrimitiveType::PRIMITIVE_BOOLEAN, glue, value);
2525                 builder_.Jump(&exit);
2526             }
2527             builder_.Bind(&notBoolean);
2528             {
2529                 Label isNullOrUndefined(&builder_);
2530                 BRANCH_CIR(builder_.TaggedIsUndefinedOrNull(value), &isNullOrUndefined, &slowPath);
2531                 builder_.Bind(&isNullOrUndefined);
2532                 {
2533                     GateRef globalEnv = circuit_->GetGlobalEnvCache();
2534                     GateRef objectFunctionPrototype = builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue,
2535                         globalEnv, GlobalEnv::OBJECT_FUNCTION_PROTOTYPE_INDEX);
2536                     res = builder_.OrdinaryNewJSObjectCreate(glue, objectFunctionPrototype);
2537                     builder_.Jump(&exit);
2538                 }
2539             }
2540         }
2541     }
2542     builder_.Bind(&slowPath);
2543     {
2544         size_t range = acc_.GetNumValueIn(gate);
2545         std::vector<GateRef> args(range);
2546         for (size_t i = 0; i < range; ++i) {
2547             args[i] = acc_.GetValueIn(gate, i);
2548         }
2549         res = LowerCallRuntime(glue, gate, RTSTUB_ID(OptNewObjRange), args, true);
2550         builder_.Jump(&exit);
2551     }
2552     builder_.Bind(&exit);
2553     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *res);
2554 }
2555 
LowerBooleanConstructorCheck(GateRef gate,GateRef glue)2556 void TypedHCRLowering::LowerBooleanConstructorCheck(GateRef gate, GateRef glue)
2557 {
2558     Environment env(gate, circuit_, &builder_);
2559     GateRef frameState = GetFrameState(gate);
2560     GateRef newTarget = acc_.GetValueIn(gate, 0);
2561     Label isHeapObject(&builder_);
2562     Label exit(&builder_);
2563     DEFVALUE(check, (&builder_), VariableType::BOOL(), builder_.True());
2564     check = builder_.TaggedIsHeapObject(newTarget, compilationEnv_);
2565     BRANCH_CIR(*check, &isHeapObject, &exit);
2566     builder_.Bind(&isHeapObject);
2567     {
2568         Label isJSFunction(&builder_);
2569         check = builder_.IsJSFunction(glue, newTarget);
2570         BRANCH_CIR(*check, &isJSFunction, &exit);
2571         builder_.Bind(&isJSFunction);
2572         {
2573             Label getHclass(&builder_);
2574             GateRef globalEnv = circuit_->GetGlobalEnvCache();
2575             GateRef booleanFunc =
2576                 builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::BOOLEAN_FUNCTION_INDEX);
2577             check = builder_.Equal(booleanFunc, newTarget);
2578             BRANCH_CIR(*check, &getHclass, &exit);
2579             builder_.Bind(&getHclass);
2580             {
2581                 GateRef intialHClass = builder_.Load(VariableType::JS_ANY(), glue, newTarget,
2582                                                      builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2583                 check = builder_.IsJSHClass(glue, intialHClass);
2584                 builder_.Jump(&exit);
2585             }
2586         }
2587     }
2588     builder_.Bind(&exit);
2589     builder_.DeoptCheck(*check, frameState, DeoptType::NEWBUILTINCTORBOOLEAN);
2590     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2591 }
2592 
LowerBooleanConstructor(GateRef gate,GateRef glue)2593 void TypedHCRLowering::LowerBooleanConstructor(GateRef gate, GateRef glue)
2594 {
2595     Environment env(gate, circuit_, &builder_);
2596     GateRef value = builder_.Undefined();
2597     ASSERT(acc_.GetNumValueIn(gate) <= 2); // 2: new target and arg0
2598     if (acc_.GetNumValueIn(gate) > 1) {
2599         value = acc_.GetValueIn(gate, 1);
2600     }
2601     DEFVALUE(res, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
2602     Label isBoolean(&builder_);
2603     Label slowPath(&builder_);
2604     Label exit(&builder_);
2605     BRANCH_CIR(builder_.TaggedIsBoolean(value), &isBoolean, &slowPath);
2606     builder_.Bind(&isBoolean);
2607     {
2608         res = NewJSPrimitiveRef(PrimitiveType::PRIMITIVE_BOOLEAN, glue, value);
2609         builder_.Jump(&exit);
2610     }
2611     builder_.Bind(&slowPath);
2612     {
2613         size_t range = acc_.GetNumValueIn(gate);
2614         std::vector<GateRef> args(range);
2615         for (size_t i = 0; i < range; ++i) {
2616             args[i] = acc_.GetValueIn(gate, i);
2617         }
2618         res = LowerCallRuntime(glue, gate, RTSTUB_ID(OptNewObjRange), args, true);
2619         builder_.Jump(&exit);
2620     }
2621     builder_.Bind(&exit);
2622     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *res);
2623 }
2624 
NewJSPrimitiveRef(PrimitiveType type,GateRef glue,GateRef value)2625 GateRef TypedHCRLowering::NewJSPrimitiveRef(PrimitiveType type, GateRef glue, GateRef value)
2626 {
2627     GateRef globalEnv = circuit_->GetGlobalEnvCache();
2628     GateRef ctor = Circuit::NullGate();
2629     switch (type) {
2630         case PrimitiveType::PRIMITIVE_NUMBER: {
2631             ctor =
2632                 builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::NUMBER_FUNCTION_INDEX);
2633             break;
2634         }
2635         case PrimitiveType::PRIMITIVE_SYMBOL: {
2636             ctor =
2637                 builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::SYMBOL_FUNCTION_INDEX);
2638             break;
2639         }
2640         case PrimitiveType::PRIMITIVE_BOOLEAN: {
2641             ctor =
2642                 builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::BOOLEAN_FUNCTION_INDEX);
2643             break;
2644         }
2645         case PrimitiveType::PRIMITIVE_BIGINT: {
2646             ctor =
2647                 builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::BIGINT_FUNCTION_INDEX);
2648             break;
2649         }
2650         default: {
2651             LOG_ECMA(FATAL) << "this branch is unreachable " << static_cast<int>(type);
2652             UNREACHABLE();
2653         }
2654     }
2655     GateRef hclass =
2656         builder_.Load(VariableType::JS_ANY(), glue, ctor, builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2657     NewObjectStubBuilder newBuilder(builder_.GetCurrentEnvironment());
2658     GateRef res = newBuilder.NewJSObject(glue, hclass);
2659     GateRef valueOffset = builder_.IntPtr(JSPrimitiveRef::VALUE_OFFSET);
2660     builder_.Store(VariableType::JS_ANY(), glue, res, valueOffset, value);
2661     return res;
2662 }
2663 
ReplaceGateWithPendingException(GateRef glue,GateRef gate,GateRef state,GateRef depend,GateRef value)2664 void TypedHCRLowering::ReplaceGateWithPendingException(GateRef glue, GateRef gate, GateRef state, GateRef depend,
2665                                                        GateRef value)
2666 {
2667     auto condition = builder_.HasPendingException(glue, compilationEnv_);
2668     GateRef ifBranch = builder_.Branch(state, condition, 1, BranchWeight::DEOPT_WEIGHT, "checkException");
2669     GateRef ifTrue = builder_.IfTrue(ifBranch);
2670     GateRef ifFalse = builder_.IfFalse(ifBranch);
2671     GateRef eDepend = builder_.DependRelay(ifTrue, depend);
2672     GateRef sDepend = builder_.DependRelay(ifFalse, depend);
2673 
2674     StateDepend success(ifFalse, sDepend);
2675     StateDepend exception(ifTrue, eDepend);
2676     acc_.ReplaceHirWithIfBranch(gate, success, exception, value);
2677 }
2678 
LowerLoadBuiltinObject(GateRef gate)2679 void TypedHCRLowering::LowerLoadBuiltinObject(GateRef gate)
2680 {
2681     if (!enableLoweringBuiltin_) {
2682         return;
2683     }
2684     Environment env(gate, circuit_, &builder_);
2685     auto frameState = GetFrameState(gate);
2686     GateRef glue = glue_;
2687     auto builtinEntriesOffset = JSThread::GlueData::GetBuiltinEntriesOffset(false);
2688     size_t index = acc_.GetIndex(gate);
2689     auto boxOffset = builtinEntriesOffset + BuiltinIndex::GetInstance().GetBuiltinBoxOffset(index);
2690     GateRef box = builder_.LoadConstOffset(VariableType::JS_POINTER(), glue, boxOffset);
2691     GateRef builtin = builder_.LoadConstOffset(VariableType::JS_POINTER(), box, PropertyBox::VALUE_OFFSET);
2692     auto builtinIsNotHole = builder_.TaggedIsNotHole(builtin);
2693     // attributes on globalThis may change, it will cause renew a PropertyBox, the old box will be abandoned
2694     // so we need deopt
2695     builder_.DeoptCheck(builtinIsNotHole, frameState, DeoptType::BUILTINISHOLE1);
2696     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), builtin);
2697 }
2698 
LowerOrdinaryHasInstanceForJIT(GateRef gate,GateRef glue)2699 void TypedHCRLowering::LowerOrdinaryHasInstanceForJIT(GateRef gate, GateRef glue)
2700 {
2701     Environment env(gate, circuit_, &builder_);
2702     GateRef obj = acc_.GetValueIn(gate, 0);
2703     GateRef target = acc_.GetValueIn(gate, 1);
2704     auto result = builder_.CallStub(glue, gate, CommonStubCSigns::OrdinaryHasInstance,
2705                                     {glue, obj, target, circuit_->GetGlobalEnvCache()}, "OrdinaryHasInstance stub");
2706     ReplaceGateWithPendingException(glue, gate, builder_.GetState(), builder_.GetDepend(), result);
2707 }
2708 
LowerOrdinaryHasInstance(GateRef gate,GateRef glue)2709 void TypedHCRLowering::LowerOrdinaryHasInstance(GateRef gate, GateRef glue)
2710 {
2711     Environment env(gate, circuit_, &builder_);
2712     GateRef obj = acc_.GetValueIn(gate, 0);
2713     GateRef target = acc_.GetValueIn(gate, 1);
2714 
2715     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.TaggedFalse());
2716     DEFVALUE(object, (&builder_), VariableType::JS_ANY(), obj);
2717     Label exit(&builder_);
2718 
2719     Label targetIsBoundFunction(&builder_);
2720     Label targetNotBoundFunction(&builder_);
2721     // 2. If C has a [[BoundTargetFunction]] internal slot, then
2722     //    a. Let BC be the value of C's [[BoundTargetFunction]] internal slot.
2723     //    b. Return InstanceofOperator(O,BC)  (see 12.9.4).
2724     BRANCH_CIR(builder_.TaggedIsBoundFunction(glue, target), &targetIsBoundFunction, &targetNotBoundFunction);
2725     builder_.Bind(&targetIsBoundFunction);
2726     {
2727         GateRef boundTarget = builder_.LoadConstOffset(VariableType::JS_ANY(), target,
2728                                                        JSBoundFunction::BOUND_TARGET_OFFSET);
2729         result = builder_.CallRuntime(glue, RTSTUB_ID(InstanceOf), Gate::InvalidGateRef,
2730                                       { obj, boundTarget }, gate);
2731         builder_.Jump(&exit);
2732     }
2733     builder_.Bind(&targetNotBoundFunction);
2734 
2735     // 3. If Type(O) is not Object, return false
2736     Label objIsHeapObject(&builder_);
2737     Label objIsEcmaObject(&builder_);
2738     Label objNotEcmaObject(&builder_);
2739     BRANCH_CIR(builder_.TaggedIsHeapObject(obj, compilationEnv_), &objIsHeapObject, &objNotEcmaObject);
2740     builder_.Bind(&objIsHeapObject);
2741     BRANCH_CIR(builder_.TaggedObjectIsEcmaObject(glue, obj), &objIsEcmaObject, &objNotEcmaObject);
2742     builder_.Bind(&objNotEcmaObject);
2743     {
2744         result = builder_.TaggedFalse();
2745         builder_.Jump(&exit);
2746     }
2747     builder_.Bind(&objIsEcmaObject);
2748     {
2749         // 4. Let P be Get(C, "prototype").
2750         Label getCtorProtoSlowPath(&builder_);
2751         Label ctorIsJSFunction(&builder_);
2752         Label gotCtorPrototype(&builder_);
2753         Label isHeapObject(&builder_);
2754         DEFVALUE(constructorPrototype, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
2755         BRANCH_CIR(builder_.IsJSFunction(glue, target), &ctorIsJSFunction, &getCtorProtoSlowPath);
2756         builder_.Bind(&ctorIsJSFunction);
2757         {
2758             Label getCtorProtoFastPath(&builder_);
2759             GateRef ctorProtoOrHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), target,
2760                                                              JSFunction::PROTO_OR_DYNCLASS_OFFSET);
2761 
2762             BRANCH_CIR(builder_.TaggedIsHole(ctorProtoOrHC), &getCtorProtoSlowPath, &getCtorProtoFastPath);
2763             builder_.Bind(&getCtorProtoFastPath);
2764             {
2765                 Label isHClass(&builder_);
2766                 Label isPrototype(&builder_);
2767                 BRANCH_CIR(builder_.TaggedIsHeapObject(ctorProtoOrHC, compilationEnv_),
2768                            &isHeapObject, &getCtorProtoSlowPath);
2769                 builder_.Bind(&isHeapObject);
2770                 BRANCH_CIR(builder_.IsJSHClass(glue, ctorProtoOrHC), &isHClass, &isPrototype);
2771                 builder_.Bind(&isHClass);
2772                 {
2773                     constructorPrototype = builder_.LoadPrototype(glue_, ctorProtoOrHC);
2774                     builder_.Jump(&gotCtorPrototype);
2775                 }
2776                 builder_.Bind(&isPrototype);
2777                 {
2778                     constructorPrototype = ctorProtoOrHC;
2779                     builder_.Jump(&gotCtorPrototype);
2780                 }
2781             }
2782         }
2783         builder_.Bind(&getCtorProtoSlowPath);
2784         {
2785             auto prototypeString = builder_.GetGlobalConstantValue(ConstantIndex::PROTOTYPE_STRING_INDEX);
2786             constructorPrototype = builder_.CallRuntime(glue, RTSTUB_ID(GetPropertyByName), Gate::InvalidGateRef,
2787                                                         { target, prototypeString }, gate);
2788             builder_.Jump(&gotCtorPrototype);
2789         }
2790         // 6. If Type(P) is not Object, throw a TypeError exception.
2791         Label prototypeIsEcmaObj(&builder_);
2792         Label prototypeNotEcmaObj(&builder_);
2793         builder_.Bind(&gotCtorPrototype);
2794         {
2795             BRANCH_CIR(builder_.IsEcmaObject(glue, *constructorPrototype), &prototypeIsEcmaObj, &prototypeNotEcmaObj);
2796             builder_.Bind(&prototypeNotEcmaObj);
2797             {
2798                 GateRef taggedId = builder_.Int32(GET_MESSAGE_STRING_ID(TargetTypeNotObject));
2799                 builder_.CallRuntime(glue, RTSTUB_ID(ThrowTypeError), Gate::InvalidGateRef,
2800                                      { builder_.Int32ToTaggedInt(taggedId) }, gate);
2801                 result = builder_.ExceptionConstant();
2802                 builder_.Jump(&exit);
2803             }
2804         }
2805         builder_.Bind(&prototypeIsEcmaObj);
2806         // 7. Repeat
2807         //    a.Let O be O.[[GetPrototypeOf]]().
2808         //    b.ReturnIfAbrupt(O).
2809         //    c.If O is null, return false.
2810         //    d.If SameValue(P, O) is true, return true.
2811         Label loopHead(&builder_);
2812         Label loopEnd(&builder_);
2813         Label afterLoop(&builder_);
2814         Label strictEqual1(&builder_);
2815         Label notStrictEqual1(&builder_);
2816         Label shouldReturn(&builder_);
2817         Label shouldContinue(&builder_);
2818 
2819         BRANCH_CIR(builder_.TaggedIsNull(*object), &afterLoop, &loopHead);
2820         builder_.LoopBegin(&loopHead);
2821         {
2822             GateRef isEqual = builder_.Equal(*object, *constructorPrototype);
2823 
2824             BRANCH_CIR(isEqual, &strictEqual1, &notStrictEqual1);
2825             builder_.Bind(&strictEqual1);
2826             {
2827                 result = builder_.TaggedTrue();
2828                 builder_.Jump(&exit);
2829             }
2830             builder_.Bind(&notStrictEqual1);
2831             {
2832                 Label objectIsHeapObject(&builder_);
2833                 Label objectIsEcmaObject(&builder_);
2834                 Label objectNotEcmaObject(&builder_);
2835 
2836                 BRANCH_CIR(builder_.TaggedIsHeapObject(*object, compilationEnv_),
2837                            &objectIsHeapObject, &objectNotEcmaObject);
2838                 builder_.Bind(&objectIsHeapObject);
2839                 BRANCH_CIR(builder_.TaggedObjectIsEcmaObject(glue, *object), &objectIsEcmaObject, &objectNotEcmaObject);
2840                 builder_.Bind(&objectNotEcmaObject);
2841                 {
2842                     GateRef taggedId = builder_.Int32(GET_MESSAGE_STRING_ID(CanNotGetNotEcmaObject));
2843                     builder_.CallRuntime(glue, RTSTUB_ID(ThrowTypeError), Gate::InvalidGateRef,
2844                                          { builder_.Int32ToTaggedInt(taggedId) }, gate);
2845                     result = builder_.ExceptionConstant();
2846                     builder_.Jump(&exit);
2847                 }
2848                 builder_.Bind(&objectIsEcmaObject);
2849                 {
2850                     Label objectIsJsProxy(&builder_);
2851                     Label objectNotIsJsProxy(&builder_);
2852                     BRANCH_CIR(builder_.IsJsProxy(glue, *object), &objectIsJsProxy, &objectNotIsJsProxy);
2853                     builder_.Bind(&objectIsJsProxy);
2854                     {
2855                         object = builder_.CallRuntime(glue, RTSTUB_ID(CallGetPrototype), Gate::InvalidGateRef,
2856                                                       { *object }, gate);
2857                         builder_.Jump(&shouldContinue);
2858                     }
2859                     builder_.Bind(&objectNotIsJsProxy);
2860                     {
2861                         GateRef objHClass = builder_.LoadHClassByConstOffset(glue, *object);
2862                         object = builder_.LoadPrototype(glue_, objHClass);
2863                         builder_.Jump(&shouldContinue);
2864                     }
2865                 }
2866             }
2867             builder_.Bind(&shouldContinue);
2868             BRANCH_CIR(builder_.TaggedIsNull(*object), &afterLoop, &loopEnd);
2869         }
2870         builder_.Bind(&loopEnd);
2871         builder_.LoopEnd(&loopHead);
2872         builder_.Bind(&afterLoop);
2873         {
2874             result = builder_.TaggedFalse();
2875             builder_.Jump(&exit);
2876         }
2877     }
2878     builder_.Bind(&exit);
2879     ReplaceGateWithPendingException(glue, gate, builder_.GetState(), builder_.GetDepend(), *result);
2880 }
2881 
LowerProtoChangeMarkerCheck(GateRef glue,GateRef gate)2882 void TypedHCRLowering::LowerProtoChangeMarkerCheck(GateRef glue, GateRef gate)
2883 {
2884     Environment env(gate, circuit_, &builder_);
2885     GateRef frameState = acc_.GetFrameState(gate);
2886     GateRef receiver = acc_.GetValueIn(gate, 0);
2887     auto hclass = builder_.LoadHClassByConstOffset(glue, receiver);
2888     auto prototype = builder_.LoadPrototype(glue_, hclass);
2889     auto protoHClass = builder_.LoadHClassByConstOffset(glue, prototype);
2890     auto marker = builder_.LoadProtoChangeMarker(glue_, protoHClass);
2891     auto notNull = builder_.TaggedIsNotNull(marker);
2892     builder_.DeoptCheck(notNull, frameState, DeoptType::PROTOTYPECHANGED2);
2893     auto hasChanged = builder_.GetHasChanged(marker);
2894     builder_.DeoptCheck(builder_.BoolNot(hasChanged), frameState, DeoptType::PROTOTYPECHANGED2);
2895     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2896 }
2897 
LowerPrimitiveTypeProtoChangeMarkerCheck(GateRef glue,GateRef gate)2898 void TypedHCRLowering::LowerPrimitiveTypeProtoChangeMarkerCheck(GateRef glue, GateRef gate)
2899 {
2900     Environment env(gate, circuit_, &builder_);
2901     GateRef frameState = acc_.GetFrameState(gate);
2902     GateRef prototype = acc_.GetValueIn(gate, 0);
2903     auto protoHClass = builder_.LoadHClassByConstOffset(glue, prototype);
2904     auto marker = builder_.LoadProtoChangeMarker(glue_, protoHClass);
2905     auto notNull = builder_.TaggedIsNotNull(marker);
2906     builder_.DeoptCheck(notNull, frameState, DeoptType::PRIMTYPEPROTOTYPECHANGED);
2907     auto hasChanged = builder_.GetHasChanged(marker);
2908     builder_.DeoptCheck(builder_.BoolNot(hasChanged), frameState, DeoptType::PRIMTYPEPROTOTYPECHANGED);
2909     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2910 }
2911 
LowerMonoLoadPropertyOnProto(GateRef glue,GateRef gate)2912 void TypedHCRLowering::LowerMonoLoadPropertyOnProto(GateRef glue, GateRef gate)
2913 {
2914     Environment env(gate, circuit_, &builder_);
2915     GateRef frameState = acc_.GetFrameState(gate);
2916     GateRef receiver = acc_.GetValueIn(gate, 0);
2917     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1); // 1: propertyLookupResult
2918     GateRef hclassIndex = acc_.GetValueIn(gate, 2); // 2: hclassIndex
2919     GateRef unsharedConstPool = acc_.GetValueIn(gate, 3); // 3: constPool
2920     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
2921     GateRef result = Circuit::NullGate();
2922     ASSERT(plr.IsLocal() || plr.IsFunction());
2923 
2924     Label loadHolder(&builder_);
2925     DEFVALUE(current, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
2926     GetPropertyHolderFromProtoChain(glue, { receiver, hclassIndex, unsharedConstPool, frameState },
2927                                     &loadHolder, &current, DeoptType::INCONSISTENTHCLASS8);
2928     builder_.Bind(&loadHolder);
2929     result = LoadPropertyFromHolder(*current, plr);
2930     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
2931 }
2932 
GetPropertyHolderFromProtoChain(GateRef glue,ProtoTypeHolderInfo holderInfo,Label * loadHolder,Variable * current,DeoptType deoptType)2933 void TypedHCRLowering::GetPropertyHolderFromProtoChain(
2934     GateRef glue, ProtoTypeHolderInfo holderInfo, Label *loadHolder, Variable *current, DeoptType deoptType)
2935 {
2936     if (compilationEnv_->SupportHeapConstant()) {
2937         auto *jitCompilationEnv = static_cast<JitCompilationEnv*>(compilationEnv_);
2938         const auto &holderHClassIndex2HeapConstantIndex = jitCompilationEnv->GetHolderHClassIndex2HeapConstantIndex();
2939         auto holderHClassIndex = acc_.GetConstantValue(holderInfo.holderHClassIndex);
2940         auto itr = holderHClassIndex2HeapConstantIndex.find(holderHClassIndex);
2941         if (itr != holderHClassIndex2HeapConstantIndex.end()) {
2942             *current = builder_.HeapConstant(itr->second);
2943             builder_.Jump(loadHolder);
2944             return;
2945         }
2946     }
2947     auto receiverHC = builder_.LoadHClassByConstOffset(glue, holderInfo.receiver);
2948     *current = builder_.LoadPrototype(glue_, receiverHC);
2949 
2950     // lookup from receiver for holder
2951     auto holderHC = builder_.LoadHClassFromConstpool(
2952         holderInfo.unsharedConstPool, acc_.GetConstantValue(holderInfo.holderHClassIndex));
2953     Label loopHead(&builder_);
2954     Label lookUpProto(&builder_);
2955     builder_.Jump(&loopHead);
2956 
2957     builder_.LoopBegin(&loopHead);
2958     builder_.DeoptCheck(builder_.TaggedIsNotNull(current->ReadVariable()), holderInfo.frameState, deoptType);
2959     auto curHC = builder_.LoadHClassByConstOffset(glue, current->ReadVariable());
2960     BRANCH_CIR(builder_.Equal(curHC, holderHC), loadHolder, &lookUpProto);
2961 
2962     builder_.Bind(&lookUpProto);
2963     *current = builder_.LoadPrototype(glue_, curHC);
2964     builder_.LoopEnd(&loopHead);
2965 }
2966 
LowerMonoCallGetterOnProto(GateRef gate,GateRef glue)2967 void TypedHCRLowering::LowerMonoCallGetterOnProto(GateRef gate, GateRef glue)
2968 {
2969     Environment env(gate, circuit_, &builder_);
2970     GateRef frameState = acc_.GetFrameState(gate);
2971     GateRef receiver = acc_.GetValueIn(gate, 0);
2972     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1); // 1: propertyLookupResult
2973     GateRef hclassIndex = acc_.GetValueIn(gate, 2); // 2: hclassIndex
2974     GateRef unsharedConstPool = acc_.GetValueIn(gate, 3); // 3: constPool
2975     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
2976     GateRef accessor = Circuit::NullGate();
2977     GateRef holder = Circuit::NullGate();
2978 
2979     Label loadHolder(&builder_);
2980     DEFVALUE(current, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
2981     GetPropertyHolderFromProtoChain(glue, { receiver, hclassIndex, unsharedConstPool, frameState },
2982                                     &loadHolder, &current, DeoptType::INCONSISTENTHCLASS9);
2983 
2984     builder_.Bind(&loadHolder);
2985     holder = *current;
2986     accessor = LoadPropertyFromHolder(holder, plr);
2987     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
2988     Label isInternalAccessor(&builder_);
2989     Label notInternalAccessor(&builder_);
2990     Label callGetter(&builder_);
2991     Label exit(&builder_);
2992     BRANCH_CIR(builder_.IsAccessorInternal(glue, accessor), &isInternalAccessor, &notInternalAccessor);
2993     {
2994         builder_.Bind(&isInternalAccessor);
2995         {
2996             result = builder_.CallRuntime(glue, RTSTUB_ID(CallInternalGetter),
2997                 Gate::InvalidGateRef, { accessor, holder }, gate);
2998             builder_.Jump(&exit);
2999         }
3000         builder_.Bind(&notInternalAccessor);
3001         {
3002             GateRef getter = builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::GETTER_OFFSET);
3003             BRANCH_CIR(builder_.IsSpecial(getter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callGetter);
3004             builder_.Bind(&callGetter);
3005             {
3006                 result = CallAccessor(glue, gate, getter, receiver, AccessorMode::GETTER);
3007                 builder_.Jump(&exit);
3008             }
3009         }
3010     }
3011     builder_.Bind(&exit);
3012     ReplaceHirWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), *result);
3013 }
3014 
LoadPropertyFromHolder(GateRef holder,PropertyLookupResult plr)3015 GateRef TypedHCRLowering::LoadPropertyFromHolder(GateRef holder, PropertyLookupResult plr)
3016 {
3017     GateRef result = Circuit::NullGate();
3018     GateRef glue = glue_;
3019     // while loading from iterator result, it may be the case that traversing an array including holes using 'for of',
3020     // need to convert hole to undefined
3021     if (plr.IsNotHole() || (compilationEnv_->IsJitCompiler() && !plr.IsLoadFromIterResult())) {
3022         ASSERT(plr.IsLocal());
3023         if (plr.IsInlinedProps()) {
3024             result = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset());
3025         } else {
3026             auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
3027             result = builder_.GetValueFromTaggedArray(glue, properties, builder_.Int32(plr.GetOffset()));
3028         }
3029     } else if (plr.IsLocal()) {
3030         if (plr.IsInlinedProps()) {
3031             result = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset());
3032         } else {
3033             auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
3034             result = builder_.GetValueFromTaggedArray(glue, properties, builder_.Int32(plr.GetOffset()));
3035         }
3036         result = builder_.ConvertHoleAsUndefined(result);
3037     } else {
3038         UNREACHABLE();
3039     }
3040     return result;
3041 }
3042 
LowerMonoStorePropertyLookUpProto(GateRef gate,GateRef glue)3043 void TypedHCRLowering::LowerMonoStorePropertyLookUpProto(GateRef gate, GateRef glue)
3044 {
3045     Environment env(gate, circuit_, &builder_);
3046     GateRef frameState = acc_.GetFrameState(gate);
3047     GateRef receiver = acc_.GetValueIn(gate, 0);
3048     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1); // 1: propertyLookupResult
3049     GateRef hclassIndex = acc_.GetValueIn(gate, 2); // 2: hclassIndex
3050     GateRef unsharedConstPool = acc_.GetValueIn(gate, 3); // 3: constpool
3051     GateRef value = acc_.GetValueIn(gate, 4); // 4: value
3052     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
3053     bool noBarrier = acc_.IsNoBarrier(gate);
3054 
3055     Label loadHolder(&builder_);
3056     DEFVALUE(current, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
3057     GetPropertyHolderFromProtoChain(glue, { receiver, hclassIndex, unsharedConstPool, frameState },
3058                                     &loadHolder, &current, DeoptType::INCONSISTENTHCLASS10);
3059     builder_.Bind(&loadHolder);
3060     Label exit(&builder_);
3061 
3062     builder_.Bind(&loadHolder);
3063     if (!plr.IsAccessor()) {
3064         StorePropertyOnHolder(*current, value, plr, noBarrier);
3065         builder_.Jump(&exit);
3066     } else {
3067         GateRef accessor = LoadPropertyFromHolder(*current, plr);
3068         Label isInternalAccessor(&builder_);
3069         Label notInternalAccessor(&builder_);
3070         Label callSetter(&builder_);
3071         BRANCH_CIR(builder_.IsAccessorInternal(glue, accessor), &isInternalAccessor, &notInternalAccessor);
3072         {
3073             builder_.Bind(&isInternalAccessor);
3074             {
3075                 builder_.CallRuntime(glue, RTSTUB_ID(CallInternalSetter),
3076                     Gate::InvalidGateRef, { receiver, accessor, value }, gate);
3077                 builder_.Jump(&exit);
3078             }
3079             builder_.Bind(&notInternalAccessor);
3080             {
3081                 GateRef setter =
3082                     builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::SETTER_OFFSET);
3083                 BRANCH_CIR(builder_.IsSpecial(setter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callSetter);
3084                 builder_.Bind(&callSetter);
3085                 {
3086                     CallAccessor(glue, gate, setter, receiver, AccessorMode::SETTER, value);
3087                     builder_.Jump(&exit);
3088                 }
3089             }
3090         }
3091     }
3092     builder_.Bind(&exit);
3093     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
3094 }
3095 
LowerMonoStoreProperty(GateRef gate,GateRef glue)3096 void TypedHCRLowering::LowerMonoStoreProperty(GateRef gate, GateRef glue)
3097 {
3098     Environment env(gate, circuit_, &builder_);
3099     GateRef frameState = acc_.GetFrameState(gate);
3100     GateRef receiver = acc_.GetValueIn(gate, 0);
3101     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1); // 1: propertyLookupResult
3102     GateRef hclassIndex = acc_.GetValueIn(gate, 2); // 2: hclassIndex
3103     GateRef unsharedConstPool = acc_.GetValueIn(gate, 3); // 3: constPool
3104     GateRef value = acc_.GetValueIn(gate, 4); // 4: value
3105     GateRef keyIndex = acc_.GetValueIn(gate, 5); // 5: keyIndex
3106     bool isPrototype = acc_.TryGetValue(acc_.GetValueIn(gate, 6)); // 6: proto flag Index
3107     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
3108     bool noBarrier = acc_.IsNoBarrier(gate);
3109     auto receiverHC = builder_.LoadHClassByConstOffset(glue, receiver);
3110     // transition happened
3111     Label exit(&builder_);
3112     Label notProto(&builder_);
3113     Label isProto(&builder_);
3114     auto newHolderHC = builder_.LoadHClassFromConstpool(unsharedConstPool, acc_.GetConstantValue(hclassIndex));
3115     if (compilationEnv_->IsAotCompiler()) {
3116         auto prototype = builder_.LoadPrototype(glue_, receiverHC);
3117         builder_.StorePrototype(glue_, newHolderHC, prototype);
3118     }
3119     if (isPrototype) {
3120         builder_.Branch(builder_.IsPrototypeHClass(receiverHC), &isProto, &notProto,
3121             BranchWeight::ONE_WEIGHT, BranchWeight::DEOPT_WEIGHT, "isPrototypeHClass");
3122         builder_.Bind(&isProto);
3123 
3124         uint32_t heapConstantIndex = JitCompilationEnv::INVALID_HEAP_CONSTANT_INDEX;
3125         GateRef propKey = 0;
3126         if (compilationEnv_->SupportHeapConstant()) {
3127             auto *jitCompilationEnv = static_cast<JitCompilationEnv*>(compilationEnv_);
3128             const auto &gate2HeapConstantIndex = jitCompilationEnv->GetGate2HeapConstantIndex();
3129             auto itr = gate2HeapConstantIndex.find(gate);
3130             if (itr != gate2HeapConstantIndex.end()) {
3131                 heapConstantIndex = itr->second;
3132                 propKey = builder_.HeapConstant(heapConstantIndex);
3133             }
3134         }
3135         if (heapConstantIndex == JitCompilationEnv::INVALID_HEAP_CONSTANT_INDEX) {
3136             propKey = builder_.GetObjectByIndexFromConstPool(glue, gate, frameState, keyIndex, ConstPoolType::STRING);
3137         }
3138         builder_.CallRuntime(glue, RTSTUB_ID(UpdateAOTHClass), Gate::InvalidGateRef,
3139             { receiverHC, newHolderHC, propKey }, gate);
3140         builder_.Jump(&notProto);
3141         builder_.Bind(&notProto);
3142     }
3143     MemoryAttribute mAttr = MemoryAttribute::NeedBarrierAndAtomic();
3144     builder_.TransitionHClass(glue, receiver, newHolderHC, mAttr);
3145     if (!plr.IsInlinedProps()) {
3146         auto properties =
3147             builder_.LoadConstOffset(VariableType::JS_ANY(), receiver, JSObject::PROPERTIES_OFFSET);
3148         auto capacity = builder_.LoadConstOffset(VariableType::INT32(), properties, TaggedArray::LENGTH_OFFSET);
3149         auto index = builder_.Int32(plr.GetOffset());
3150         Label needExtend(&builder_);
3151         Label notExtend(&builder_);
3152         BRANCH_CIR(builder_.Int32UnsignedLessThan(index, capacity), &notExtend, &needExtend);
3153         builder_.Bind(&notExtend);
3154         {
3155             if (!plr.IsAccessor()) {
3156                 StorePropertyOnHolder(receiver, value, plr, noBarrier);
3157                 builder_.Jump(&exit);
3158             } else {
3159                 GateRef accessor = LoadPropertyFromHolder(receiver, plr);
3160                 Label isInternalAccessor(&builder_);
3161                 Label notInternalAccessor(&builder_);
3162                 Label callSetter(&builder_);
3163                 BRANCH_CIR(builder_.IsAccessorInternal(glue, accessor), &isInternalAccessor, &notInternalAccessor);
3164                 {
3165                     builder_.Bind(&isInternalAccessor);
3166                     {
3167                         builder_.CallRuntime(glue, RTSTUB_ID(CallInternalSetter),
3168                             Gate::InvalidGateRef, { receiver, accessor, value }, gate);
3169                         builder_.Jump(&exit);
3170                     }
3171                     builder_.Bind(&notInternalAccessor);
3172                     {
3173                         GateRef setter =
3174                             builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::SETTER_OFFSET);
3175                         BRANCH_CIR(builder_.IsSpecial(setter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callSetter);
3176                         builder_.Bind(&callSetter);
3177                         {
3178                             CallAccessor(glue, gate, setter, receiver, AccessorMode::SETTER, value);
3179                             builder_.Jump(&exit);
3180                         }
3181                     }
3182                 }
3183             }
3184         }
3185         builder_.Bind(&needExtend);
3186         {
3187             builder_.CallRuntime(glue,
3188                 RTSTUB_ID(PropertiesSetValue),
3189                 Gate::InvalidGateRef,
3190                 { receiver, value, properties, builder_.Int32ToTaggedInt(capacity),
3191                 builder_.Int32ToTaggedInt(index) }, gate);
3192             builder_.Jump(&exit);
3193         }
3194     } else {
3195         if (!plr.IsAccessor()) {
3196             StorePropertyOnHolder(receiver, value, plr, noBarrier);
3197             builder_.Jump(&exit);
3198         } else {
3199             GateRef accessor = LoadPropertyFromHolder(receiver, plr);
3200             Label isInternalAccessor(&builder_);
3201             Label notInternalAccessor(&builder_);
3202             Label callSetter(&builder_);
3203             BRANCH_CIR(builder_.IsAccessorInternal(glue, accessor), &isInternalAccessor, &notInternalAccessor);
3204             {
3205                 builder_.Bind(&isInternalAccessor);
3206                 {
3207                     builder_.CallRuntime(glue, RTSTUB_ID(CallInternalSetter),
3208                         Gate::InvalidGateRef, { receiver, accessor, value }, gate);
3209                     builder_.Jump(&exit);
3210                 }
3211                 builder_.Bind(&notInternalAccessor);
3212                 {
3213                     GateRef setter =
3214                         builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::SETTER_OFFSET);
3215                     BRANCH_CIR(builder_.IsSpecial(setter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callSetter);
3216                     builder_.Bind(&callSetter);
3217                     {
3218                         CallAccessor(glue, gate, setter, receiver, AccessorMode::SETTER, value);
3219                         builder_.Jump(&exit);
3220                     }
3221                 }
3222             }
3223         }
3224     }
3225     builder_.Bind(&exit);
3226     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
3227 }
3228 
StorePropertyOnHolder(GateRef holder,GateRef value,PropertyLookupResult plr,bool noBarrier)3229 void TypedHCRLowering::StorePropertyOnHolder(GateRef holder, GateRef value, PropertyLookupResult plr, bool noBarrier)
3230 {
3231     if (!noBarrier) {
3232         if (plr.IsInlinedProps()) {
3233             builder_.StoreConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset(), value);
3234         } else {
3235             auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
3236             builder_.SetValueToTaggedArray(
3237                 VariableType::JS_ANY(), glue_, properties, builder_.Int32(plr.GetOffset()), value);
3238         }
3239     } else {
3240         if (plr.IsInlinedProps()) {
3241             builder_.StoreConstOffset(GetVarType(plr), holder, plr.GetOffset(), value);
3242         } else {
3243             auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
3244             builder_.SetValueToTaggedArray(
3245                 GetVarType(plr), glue_, properties, builder_.Int32(plr.GetOffset()), value);
3246         }
3247     }
3248 }
3249 
GetOldObject(CompilationEnv * compilationEnv,CircuitBuilder & builder,const GateAccessor & acc,GateRef glue,GateRef gate)3250 static GateRef GetOldObject(CompilationEnv *compilationEnv, CircuitBuilder &builder,
3251     const GateAccessor &acc, GateRef glue, GateRef gate)
3252 {
3253     if (compilationEnv->SupportHeapConstant()) {
3254         auto *jitCompilationEnv = static_cast<JitCompilationEnv*>(compilationEnv);
3255         const auto &gate2HeapConstantIndex = jitCompilationEnv->GetGate2HeapConstantIndex();
3256         auto itr = gate2HeapConstantIndex.find(gate);
3257         // object must be found in unshared constpool,
3258         // which is ensured by TypedBytecodeLowering::LowerCreateObjectWithBuffer
3259         ASSERT(itr != gate2HeapConstantIndex.end());
3260         return builder.HeapConstant(itr->second);
3261     }
3262     GateRef frameState = acc.GetFrameState(gate);
3263     GateRef index = acc.GetValueIn(gate, 1); // 1: index
3264     return builder.GetObjectByIndexFromConstPool(
3265         glue, gate, frameState, builder.TruncInt64ToInt32(index), ConstPoolType::OBJECT_LITERAL);
3266 }
3267 
LowerTypedCreateObjWithBuffer(GateRef gate,GateRef glue)3268 void TypedHCRLowering::LowerTypedCreateObjWithBuffer(GateRef gate, GateRef glue)
3269 {
3270     Environment env(gate, circuit_, &builder_);
3271     DEFVALUE(ret, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
3272     Label equal(&builder_);
3273     Label notEqual(&builder_);
3274     Label exit(&builder_);
3275     GateRef objSize = acc_.GetValueIn(gate, 0); // 0: objSize
3276     GateRef lexEnv = acc_.GetValueIn(gate, 3); // 3: lexenv
3277     size_t numValueIn = acc_.GetNumValueIn(gate);
3278 
3279     GateRef oldObj = GetOldObject(compilationEnv_, builder_, acc_, glue, gate);
3280     GateRef hclass = builder_.LoadHClassByConstOffset(glue, oldObj);
3281     GateRef emptyArray = builder_.GetGlobalConstantValue(ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
3282     GateRef objectSize = builder_.GetObjectSizeFromHClass(hclass);
3283     BRANCH_CIR(builder_.Equal(objectSize, objSize), &equal, &notEqual);
3284     builder_.Bind(&equal);
3285     {
3286         builder_.StartAllocate();
3287         GateRef newObj = builder_.HeapAlloc(glue, objSize, GateType::TaggedValue(), RegionSpaceFlag::IN_YOUNG_SPACE);
3288         builder_.StoreHClass(glue, newObj, hclass, MemoryAttribute::NeedBarrierAndAtomic());
3289         builder_.StoreConstOffset(VariableType::INT64(), newObj,
3290             JSObject::HASH_OFFSET, builder_.Int64(JSTaggedValue(0).GetRawData()));
3291         builder_.StoreConstOffset(VariableType::INT64(), newObj, JSObject::PROPERTIES_OFFSET, emptyArray);
3292         builder_.StoreConstOffset(VariableType::INT64(), newObj, JSObject::ELEMENTS_OFFSET, emptyArray);
3293         size_t fixedNumValueIn = 4; // objSize, index, hclass, lexEnv
3294         for (uint32_t i = 0; i < numValueIn - fixedNumValueIn; i += 2) { // 2 : value, offset
3295             builder_.StoreConstOffset(VariableType::INT64(), newObj,
3296                 acc_.GetConstantValue(acc_.GetValueIn(gate, i + fixedNumValueIn + 1)),
3297                 acc_.GetValueIn(gate, i + fixedNumValueIn));
3298         }
3299         ret = builder_.FinishAllocate(newObj);
3300         builder_.Jump(&exit);
3301     }
3302     builder_.Bind(&notEqual);
3303     {
3304         ret = builder_.CallRuntime(glue, RTSTUB_ID(CreateObjectHavingMethod),
3305             Gate::InvalidGateRef, { oldObj, lexEnv }, gate);
3306         builder_.Jump(&exit);
3307     }
3308     builder_.Bind(&exit);
3309     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *ret);
3310 }
3311 
LowerStringFromSingleCharCode(GateRef gate,GateRef glue)3312 void TypedHCRLowering::LowerStringFromSingleCharCode(GateRef gate, GateRef glue)
3313 {
3314     Environment env(gate, circuit_, &builder_);
3315     DEFVALUE(value, (&builder_), VariableType::INT16(), builder_.Int16(0));
3316     DEFVALUE(res, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
3317     Label isPendingException(&builder_);
3318     Label noPendingException(&builder_);
3319     Label exit(&builder_);
3320     Label isInt(&builder_);
3321     Label notInt(&builder_);
3322     Label newObj(&builder_);
3323     Label canBeCompress(&builder_);
3324     Label canNotBeCompress(&builder_);
3325     GateRef codePointTag = acc_.GetValueIn(gate);
3326     GateRef codePointValue = builder_.ToNumber(gate, codePointTag, glue);
3327     BRANCH_CIR(builder_.HasPendingException(glue, compilationEnv_), &isPendingException, &noPendingException);
3328     builder_.Bind(&isPendingException);
3329     {
3330         res = builder_.ExceptionConstant();
3331         builder_.Jump(&exit);
3332     }
3333     builder_.Bind(&noPendingException);
3334     {
3335         BRANCH_CIR(builder_.TaggedIsInt(codePointValue), &isInt, &notInt);
3336         builder_.Bind(&isInt);
3337         {
3338             value = builder_.TruncInt32ToInt16(builder_.GetInt32OfTInt(codePointValue));
3339             builder_.Jump(&newObj);
3340         }
3341         builder_.Bind(&notInt);
3342         {
3343             value = builder_.TruncInt32ToInt16(
3344                 builder_.TruncDoubleToInt(glue, builder_.GetDoubleOfTDouble(codePointValue), base::INT16_BITS));
3345             builder_.Jump(&newObj);
3346         }
3347         builder_.Bind(&newObj);
3348         BRANCH_CIR(builder_.IsASCIICharacter(builder_.ZExtInt16ToInt32(*value)), &canBeCompress, &canNotBeCompress);
3349         NewObjectStubBuilder newBuilder(&env);
3350         newBuilder.SetParameters(glue, 0);
3351         builder_.Bind(&canBeCompress);
3352         {
3353             GateRef singleCharTable = builder_.GetGlobalConstantValue(ConstantIndex::SINGLE_CHAR_TABLE_INDEX);
3354             res = builder_.GetValueFromTaggedArray(glue, singleCharTable, builder_.ZExtInt16ToInt32(*value));
3355             builder_.Jump(&exit);
3356         }
3357         builder_.Bind(&canNotBeCompress);
3358         {
3359             Label afterNew1(&builder_);
3360             newBuilder.AllocLineStringObject(&res, &afterNew1, builder_.Int32(1), false);
3361             builder_.Bind(&afterNew1);
3362             {
3363                 GateRef dst = builder_.ChangeTaggedPointerToInt64(
3364                     builder_.PtrAdd(*res, builder_.IntPtr(LineString::DATA_OFFSET)));
3365                 builder_.Store(VariableType::INT16(), glue, dst, builder_.IntPtr(0), *value);
3366                 builder_.Jump(&exit);
3367             }
3368         }
3369     }
3370     builder_.Bind(&exit);
3371     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *res);
3372 }
3373 
LowerMigrateArrayWithKind(GateRef gate,GateRef glue)3374 void TypedHCRLowering::LowerMigrateArrayWithKind(GateRef gate, GateRef glue)
3375 {
3376     Environment env(gate, circuit_, &builder_);
3377     Label exit(&builder_);
3378     GateRef object = acc_.GetValueIn(gate, 0);
3379     GateRef oldKind = acc_.GetValueIn(gate, 1); // 1: objSize
3380     GateRef newKind = acc_.GetValueIn(gate, 2); // 2: index
3381 
3382     DEFVALUE(newElements, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
3383     Label doMigration(&builder_);
3384     Label migrateFromInt(&builder_);
3385     Label migrateOtherKinds(&builder_);
3386     GateRef noNeedMigration = LogicOrBuilder(&env)
3387         .Or(builder_.Int32Equal(oldKind, newKind))
3388         .Or(builder_.BitAnd(builder_.Int32Equal(oldKind, builder_.Int32(Elements::ToUint(ElementsKind::INT))),
3389             builder_.Int32Equal(newKind, builder_.Int32(Elements::ToUint(ElementsKind::HOLE_INT)))))
3390         .Or(builder_.BitAnd(builder_.Int32Equal(oldKind, builder_.Int32(Elements::ToUint(ElementsKind::NUMBER))),
3391             builder_.Int32Equal(newKind, builder_.Int32(Elements::ToUint(ElementsKind::HOLE_NUMBER)))))
3392         .Done();
3393     BRANCH_CIR(noNeedMigration, &exit, &doMigration);
3394     builder_.Bind(&doMigration);
3395 
3396     GateRef needCOW = builder_.IsJsCOWArray(glue, object, compilationEnv_);
3397     BRANCH_CIR(builder_.ElementsKindIsIntOrHoleInt(oldKind), &migrateFromInt, &migrateOtherKinds);
3398     builder_.Bind(&migrateFromInt);
3399     {
3400         Label migrateToHeapValuesFromInt(&builder_);
3401         Label migrateToRawValuesFromInt(&builder_);
3402         Label migrateToNumbersFromInt(&builder_);
3403         BRANCH_CIR(builder_.ElementsKindIsHeapKind(newKind),
3404                    &migrateToHeapValuesFromInt, &migrateToRawValuesFromInt);
3405         builder_.Bind(&migrateToHeapValuesFromInt);
3406         {
3407             newElements = builder_.MigrateFromRawValueToHeapValues(object, needCOW, builder_.True());
3408             builder_.StoreConstOffset(VariableType::JS_ANY(), object, JSObject::ELEMENTS_OFFSET, *newElements);
3409             builder_.Jump(&exit);
3410         }
3411         builder_.Bind(&migrateToRawValuesFromInt);
3412         {
3413             BRANCH_CIR(builder_.ElementsKindIsNumOrHoleNum(newKind), &migrateToNumbersFromInt, &exit);
3414             builder_.Bind(&migrateToNumbersFromInt);
3415             {
3416                 builder_.MigrateFromHoleIntToHoleNumber(object);
3417                 builder_.Jump(&exit);
3418             }
3419         }
3420     }
3421     builder_.Bind(&migrateOtherKinds);
3422     {
3423         Label migrateFromNumber(&builder_);
3424         Label migrateToHeapValuesFromNum(&builder_);
3425         Label migrateToRawValuesFromNum(&builder_);
3426         Label migrateToIntFromNum(&builder_);
3427         Label migrateToRawValueFromTagged(&builder_);
3428         BRANCH_CIR(builder_.ElementsKindIsNumOrHoleNum(oldKind), &migrateFromNumber, &migrateToRawValueFromTagged);
3429         builder_.Bind(&migrateFromNumber);
3430         {
3431             BRANCH_CIR(builder_.ElementsKindIsHeapKind(newKind),
3432                        &migrateToHeapValuesFromNum, &migrateToRawValuesFromNum);
3433             builder_.Bind(&migrateToHeapValuesFromNum);
3434             {
3435                 Label migrateToTaggedFromNum(&builder_);
3436                 BRANCH_CIR(builder_.ElementsKindIsHeapKind(newKind), &migrateToTaggedFromNum, &exit);
3437                 builder_.Bind(&migrateToTaggedFromNum);
3438                 {
3439                     newElements = builder_.MigrateFromRawValueToHeapValues(object, needCOW, builder_.False());
3440                     builder_.StoreConstOffset(VariableType::JS_ANY(), object, JSObject::ELEMENTS_OFFSET, *newElements);
3441                     builder_.Jump(&exit);
3442                 }
3443             }
3444             builder_.Bind(&migrateToRawValuesFromNum);
3445             {
3446                 BRANCH_CIR(builder_.ElementsKindIsIntOrHoleInt(newKind), &migrateToIntFromNum, &exit);
3447                 builder_.Bind(&migrateToIntFromNum);
3448                 {
3449                     builder_.MigrateFromHoleNumberToHoleInt(object);
3450                     builder_.Jump(&exit);
3451                 }
3452             }
3453         }
3454         builder_.Bind(&migrateToRawValueFromTagged);
3455         {
3456             Label migrateToIntFromTagged(&builder_);
3457             Label migrateToOthersFromTagged(&builder_);
3458             BRANCH_CIR(builder_.ElementsKindIsIntOrHoleInt(newKind),
3459                        &migrateToIntFromTagged, &migrateToOthersFromTagged);
3460             builder_.Bind(&migrateToIntFromTagged);
3461             {
3462                 newElements = builder_.MigrateFromHeapValueToRawValue(object, needCOW, builder_.True());
3463                 builder_.StoreConstOffset(VariableType::JS_ANY(), object, JSObject::ELEMENTS_OFFSET, *newElements);
3464                 builder_.Jump(&exit);
3465             }
3466             builder_.Bind(&migrateToOthersFromTagged);
3467             {
3468                 Label migrateToNumFromTagged(&builder_);
3469                 BRANCH_CIR(builder_.ElementsKindIsNumOrHoleNum(newKind), &migrateToNumFromTagged, &exit);
3470                 builder_.Bind(&migrateToNumFromTagged);
3471                 {
3472                     newElements = builder_.MigrateFromHeapValueToRawValue(object, needCOW, builder_.False());
3473                     builder_.StoreConstOffset(VariableType::JS_ANY(), object, JSObject::ELEMENTS_OFFSET, *newElements);
3474                     builder_.Jump(&exit);
3475                 }
3476             }
3477         }
3478     }
3479     builder_.Bind(&exit);
3480     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
3481 }
3482 
LowerNumberToString(GateRef gate,GateRef glue)3483 void TypedHCRLowering::LowerNumberToString(GateRef gate, GateRef glue)
3484 {
3485     Environment env(gate, circuit_, &builder_);
3486     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
3487     GateRef number = acc_.GetValueIn(gate, 0);
3488     result = builder_.CallRuntime(glue, RTSTUB_ID(NumberToString),
3489         Gate::InvalidGateRef, { number }, gate);
3490     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
3491 }
3492 
LowerEcmaObjectCheck(GateRef gate)3493 void TypedHCRLowering::LowerEcmaObjectCheck(GateRef gate)
3494 {
3495     Environment env(gate, circuit_, &builder_);
3496     GateRef value = acc_.GetValueIn(gate, 0);
3497     GateRef frameState = acc_.GetFrameState(gate);
3498     builder_.HeapObjectCheck(value, frameState);
3499     builder_.HeapObjectIsEcmaObjectCheck(value, frameState);
3500     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
3501 }
3502 
LowerElementskindCheck(GateRef glue,GateRef gate)3503 void TypedHCRLowering::LowerElementskindCheck(GateRef glue, GateRef gate)
3504 {
3505     Environment env(gate, circuit_, &builder_);
3506     GateRef frameState = acc_.GetFrameState(gate);
3507     ArrayMetaDataAccessor accessor = acc_.GetArrayMetaDataAccessor(gate);
3508     ElementsKind kind = accessor.GetElementsKind();
3509     GateRef check = Circuit::NullGate();
3510     GateRef receiver = acc_.GetValueIn(gate, 0);
3511     GateRef hclass = builder_.LoadHClassByConstOffset(glue, receiver);
3512 
3513     if (Elements::IsComplex(kind)) {
3514         check = builder_.Int32GreaterThanOrEqual(builder_.Int32(Elements::ToUint(kind)),
3515                                                  builder_.GetElementsKindByHClass(hclass));
3516     } else {
3517         check = builder_.Equal(builder_.Int32(Elements::ToUint(kind)), builder_.GetElementsKindByHClass(hclass));
3518     }
3519     builder_.DeoptCheck(check, frameState, DeoptType::INCONSISTENTELEMENTSKIND);
3520     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
3521 }
3522 
LowerCheckConstructor(GateRef gate,GateRef glue)3523 void TypedHCRLowering::LowerCheckConstructor(GateRef gate, GateRef glue)
3524 {
3525     Environment env(gate, circuit_, &builder_);
3526     NewObjectStubBuilder objBuilder(&env);
3527     GateRef superFunc = acc_.GetValueIn(gate, 0); // 0 : Super func
3528     GateRef ctorResult = acc_.GetValueIn(gate, 1); // 1: Constructor result
3529     GateRef thisObj = acc_.GetValueIn(gate, 2); // 2: This object
3530     GateRef result = objBuilder.ConstructorCheck(glue, superFunc, ctorResult, thisObj);
3531     ReplaceHirWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), result);
3532 }
3533 }  // namespace panda::ecmascript::kungfu
3534