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