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