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