• 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/type_mcr_lowering.h"
17 #include "ecmascript/compiler/builtins_lowering.h"
18 #include "ecmascript/compiler/new_object_stub_builder.h"
19 #include "ecmascript/deoptimizer/deoptimizer.h"
20 #include "ecmascript/js_arraybuffer.h"
21 #include "ecmascript/js_native_pointer.h"
22 #include "ecmascript/subtyping_operator.h"
23 #include "ecmascript/vtable.h"
24 #include "ecmascript/message_string.h"
25 namespace panda::ecmascript::kungfu {
RunTypeMCRLowering()26 void TypeMCRLowering::RunTypeMCRLowering()
27 {
28     std::vector<GateRef> gateList;
29     circuit_->GetAllGates(gateList);
30     for (const auto &gate : gateList) {
31         LowerType(gate);
32     }
33 
34     if (IsLogEnabled()) {
35         LOG_COMPILER(INFO) << "";
36         LOG_COMPILER(INFO) << "\033[34m" << "=================="
37                            << " After TypeMCRlowering "
38                            << "[" << GetMethodName() << "] "
39                            << "==================" << "\033[0m";
40         circuit_->PrintAllGatesWithBytecode();
41         LOG_COMPILER(INFO) << "\033[34m" << "=========================== End =========================" << "\033[0m";
42     }
43 }
44 
LowerType(GateRef gate)45 void TypeMCRLowering::LowerType(GateRef gate)
46 {
47     GateRef glue = acc_.GetGlueFromArgList();
48     auto op = acc_.GetOpCode(gate);
49     switch (op) {
50         case OpCode::PRIMITIVE_TYPE_CHECK:
51             LowerPrimitiveTypeCheck(gate);
52             break;
53         case OpCode::STABLE_ARRAY_CHECK:
54             LowerStableArrayCheck(gate);
55             break;
56         case OpCode::TYPED_ARRAY_CHECK:
57             LowerTypedArrayCheck(gate);
58             break;
59         case OpCode::LOAD_TYPED_ARRAY_LENGTH:
60             LowerLoadTypedArrayLength(gate);
61             break;
62         case OpCode::OBJECT_TYPE_CHECK:
63             LowerObjectTypeCheck(gate);
64             break;
65         case OpCode::OBJECT_TYPE_COMPARE:
66             LowerObjectTypeCompare(gate);
67             break;
68         case OpCode::INDEX_CHECK:
69             LowerIndexCheck(gate);
70             break;
71         case OpCode::TYPED_CALLTARGETCHECK_OP:
72             LowerJSCallTargetCheck(gate);
73             break;
74         case OpCode::TYPED_CALL_CHECK:
75             LowerCallTargetCheck(gate);
76             break;
77         case OpCode::JSINLINETARGET_TYPE_CHECK:
78             LowerJSInlineTargetTypeCheck(gate);
79             break;
80         case OpCode::TYPE_CONVERT:
81             LowerTypeConvert(gate);
82             break;
83         case OpCode::LOAD_PROPERTY:
84             LowerLoadProperty(gate);
85             break;
86         case OpCode::CALL_GETTER:
87             LowerCallGetter(gate, glue);
88             break;
89         case OpCode::STORE_PROPERTY:
90         case OpCode::STORE_PROPERTY_NO_BARRIER:
91             LowerStoreProperty(gate);
92             break;
93         case OpCode::CALL_SETTER:
94             LowerCallSetter(gate, glue);
95             break;
96         case OpCode::LOAD_ARRAY_LENGTH:
97             LowerLoadArrayLength(gate);
98             break;
99         case OpCode::LOAD_ELEMENT:
100             LowerLoadElement(gate);
101             break;
102         case OpCode::STORE_ELEMENT:
103             LowerStoreElement(gate, glue);
104             break;
105         case OpCode::TYPED_CALL_BUILTIN:
106             LowerTypedCallBuitin(gate);
107             break;
108         case OpCode::TYPED_NEW_ALLOCATE_THIS:
109             LowerTypedNewAllocateThis(gate, glue);
110             break;
111         case OpCode::TYPED_SUPER_ALLOCATE_THIS:
112             LowerTypedSuperAllocateThis(gate, glue);
113             break;
114         case OpCode::GET_SUPER_CONSTRUCTOR:
115             LowerGetSuperConstructor(gate);
116             break;
117         case OpCode::COW_ARRAY_CHECK:
118             LowerCowArrayCheck(gate, glue);
119             break;
120         case OpCode::LOAD_GETTER:
121             LowerLoadGetter(gate);
122             break;
123         case OpCode::LOAD_SETTER:
124             LowerLoadSetter(gate);
125             break;
126         case OpCode::INLINE_ACCESSOR_CHECK:
127             LowerInlineAccessorCheck(gate);
128             break;
129         default:
130             break;
131     }
132 }
133 
LowerJSCallTargetCheck(GateRef gate)134 void TypeMCRLowering::LowerJSCallTargetCheck(GateRef gate)
135 {
136     TypedCallTargetCheckOp Op = acc_.GetTypedCallTargetCheckOp(gate);
137     switch (Op) {
138         case TypedCallTargetCheckOp::JSCALL_IMMEDIATE_AFTER_FUNC_DEF: {
139             LowerJSCallTargetFromDefineFuncCheck(gate);
140             break;
141         }
142         case TypedCallTargetCheckOp::JSCALL: {
143             LowerJSCallTargetTypeCheck(gate);
144             break;
145         }
146         case TypedCallTargetCheckOp::JSCALL_FAST: {
147             LowerJSFastCallTargetTypeCheck(gate);
148             break;
149         }
150         case TypedCallTargetCheckOp::JSCALLTHIS: {
151             LowerJSCallThisTargetTypeCheck(gate);
152             break;
153         }
154         case TypedCallTargetCheckOp::JSCALLTHIS_FAST: {
155             LowerJSFastCallThisTargetTypeCheck(gate);
156             break;
157         }
158         case TypedCallTargetCheckOp::JSCALLTHIS_NOGC: {
159             LowerJSNoGCCallThisTargetTypeCheck(gate);
160             break;
161         }
162         case TypedCallTargetCheckOp::JSCALLTHIS_FAST_NOGC: {
163             LowerJSNoGCFastCallThisTargetTypeCheck(gate);
164             break;
165         }
166         default:
167             LOG_ECMA(FATAL) << "this branch is unreachable";
168             UNREACHABLE();
169     }
170 }
171 
LowerPrimitiveTypeCheck(GateRef gate)172 void TypeMCRLowering::LowerPrimitiveTypeCheck(GateRef gate)
173 {
174     Environment env(gate, circuit_, &builder_);
175     auto type = acc_.GetParamGateType(gate);
176     if (type.IsIntType()) {
177         LowerIntCheck(gate);
178     } else if (type.IsDoubleType()) {
179         LowerDoubleCheck(gate);
180     } else if (type.IsNumberType()) {
181         LowerNumberCheck(gate);
182     } else if (type.IsBooleanType()) {
183         LowerBooleanCheck(gate);
184     } else {
185         LOG_ECMA(FATAL) << "this branch is unreachable";
186         UNREACHABLE();
187     }
188 }
189 
LowerIntCheck(GateRef gate)190 void TypeMCRLowering::LowerIntCheck(GateRef gate)
191 {
192     GateRef frameState = GetFrameState(gate);
193 
194     GateRef value = acc_.GetValueIn(gate, 0);
195     GateRef typeCheck = builder_.TaggedIsInt(value);
196     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTINT);
197 
198     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
199 }
200 
LowerDoubleCheck(GateRef gate)201 void TypeMCRLowering::LowerDoubleCheck(GateRef gate)
202 {
203     GateRef frameState = GetFrameState(gate);
204 
205     GateRef value = acc_.GetValueIn(gate, 0);
206     GateRef typeCheck = builder_.TaggedIsDouble(value);
207     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTDOUBLE);
208 
209     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
210 }
211 
LowerNumberCheck(GateRef gate)212 void TypeMCRLowering::LowerNumberCheck(GateRef gate)
213 {
214     GateRef frameState = GetFrameState(gate);
215 
216     GateRef value = acc_.GetValueIn(gate, 0);
217     GateRef typeCheck = builder_.TaggedIsNumber(value);
218     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTNUMBER);
219 
220     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
221 }
222 
LowerBooleanCheck(GateRef gate)223 void TypeMCRLowering::LowerBooleanCheck(GateRef gate)
224 {
225     GateRef frameState = GetFrameState(gate);
226 
227     GateRef value = acc_.GetValueIn(gate, 0);
228     GateRef typeCheck = builder_.TaggedIsBoolean(value);
229     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTBOOL);
230 
231     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
232 }
233 
LowerStableArrayCheck(GateRef gate)234 void TypeMCRLowering::LowerStableArrayCheck(GateRef gate)
235 {
236     Environment env(gate, circuit_, &builder_);
237     GateRef frameState = GetFrameState(gate);
238 
239     GateRef receiver = acc_.GetValueIn(gate, 0);
240     builder_.HeapObjectCheck(receiver, frameState);
241 
242     GateRef receiverHClass = builder_.LoadConstOffset(
243         VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
244     ArrayMetaDataAccessor accessor = acc_.GetArrayMetaDataAccessor(gate);
245     builder_.HClassStableArrayCheck(receiverHClass, frameState, accessor);
246     builder_.ArrayGuardianCheck(frameState);
247 
248     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
249 }
250 
SetDeoptTypeInfo(BuiltinTypeId id,DeoptType & type,size_t & funcIndex)251 void TypeMCRLowering::SetDeoptTypeInfo(BuiltinTypeId id, DeoptType &type, size_t &funcIndex)
252 {
253     type = DeoptType::NOTARRAY;
254     switch (id) {
255         case BuiltinTypeId::INT8_ARRAY:
256             funcIndex = GlobalEnv::INT8_ARRAY_FUNCTION_INDEX;
257             break;
258         case BuiltinTypeId::UINT8_ARRAY:
259             funcIndex = GlobalEnv::UINT8_ARRAY_FUNCTION_INDEX;
260             break;
261         case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
262             funcIndex = GlobalEnv::UINT8_CLAMPED_ARRAY_FUNCTION_INDEX;
263             break;
264         case BuiltinTypeId::INT16_ARRAY:
265             funcIndex = GlobalEnv::INT16_ARRAY_FUNCTION_INDEX;
266             break;
267         case BuiltinTypeId::UINT16_ARRAY:
268             funcIndex = GlobalEnv::UINT16_ARRAY_FUNCTION_INDEX;
269             break;
270         case BuiltinTypeId::INT32_ARRAY:
271             funcIndex = GlobalEnv::INT32_ARRAY_FUNCTION_INDEX;
272             break;
273         case BuiltinTypeId::UINT32_ARRAY:
274             funcIndex = GlobalEnv::UINT32_ARRAY_FUNCTION_INDEX;
275             break;
276         case BuiltinTypeId::FLOAT32_ARRAY:
277             funcIndex = GlobalEnv::FLOAT32_ARRAY_FUNCTION_INDEX;
278             break;
279         case BuiltinTypeId::FLOAT64_ARRAY:
280             funcIndex = GlobalEnv::FLOAT64_ARRAY_FUNCTION_INDEX;
281             break;
282         default:
283             LOG_ECMA(FATAL) << "this branch is unreachable";
284             UNREACHABLE();
285     }
286 }
287 
LowerTypedArrayCheck(GateRef gate)288 void TypeMCRLowering::LowerTypedArrayCheck(GateRef gate)
289 {
290     Environment env(gate, circuit_, &builder_);
291     auto type = acc_.GetParamGateType(gate);
292     size_t typedArrayFuncIndex = GlobalEnv::TYPED_ARRAY_FUNCTION_INDEX;
293     auto deoptType = DeoptType::NOTCHECK;
294 
295     auto builtinTypeId = tsManager_->GetTypedArrayBuiltinId(type);
296     SetDeoptTypeInfo(builtinTypeId, deoptType, typedArrayFuncIndex);
297 
298     GateRef frameState = GetFrameState(gate);
299     GateRef glueGlobalEnv = builder_.GetGlobalEnv();
300     GateRef receiver = acc_.GetValueIn(gate, 0);
301     GateRef receiverHClass = builder_.LoadHClass(receiver);
302     GateRef protoOrHclass = builder_.GetGlobalEnvObjHClass(glueGlobalEnv, typedArrayFuncIndex);
303     GateRef check = builder_.Equal(receiverHClass, protoOrHclass);
304     builder_.DeoptCheck(check, frameState, deoptType);
305     GateRef isOnHeap = builder_.LoadConstOffset(VariableType::BOOL(), receiver, JSTypedArray::ON_HEAP_OFFSET);
306     builder_.DeoptCheck(isOnHeap, frameState, DeoptType::NOTONHEAP);
307 
308     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
309 }
310 
LowerLoadTypedArrayLength(GateRef gate)311 void TypeMCRLowering::LowerLoadTypedArrayLength(GateRef gate)
312 {
313     Environment env(gate, circuit_, &builder_);
314     GateRef receiver = acc_.GetValueIn(gate, 0);
315     GateRef length = builder_.LoadConstOffset(VariableType::INT32(), receiver, JSTypedArray::ARRAY_LENGTH_OFFSET);
316     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), length);
317 }
318 
LowerObjectTypeCheck(GateRef gate)319 void TypeMCRLowering::LowerObjectTypeCheck(GateRef gate)
320 {
321     Environment env(gate, circuit_, &builder_);
322     GateType type = acc_.GetObjectTypeAccessor(gate).GetType();
323     if (tsManager_->IsClassInstanceTypeKind(type)) {
324         LowerTSSubtypingCheck(gate);
325     } else if (tsManager_->IsClassTypeKind(type) ||
326                tsManager_->IsObjectTypeKind(type)) {
327         LowerSimpleHClassCheck(gate);
328     } else {
329         LOG_COMPILER(FATAL) << "this branch is unreachable";
330         UNREACHABLE();
331     }
332 }
333 
LowerTSSubtypingCheck(GateRef gate)334 void TypeMCRLowering::LowerTSSubtypingCheck(GateRef gate)
335 {
336     GateRef frameState = GetFrameState(gate);
337     Label levelValid(&builder_);
338     Label exit(&builder_);
339     GateRef compare = BuildCompareSubTyping(gate, frameState, &levelValid, &exit);
340     builder_.DeoptCheck(compare, frameState, DeoptType::INCONSISTENTHCLASS);
341     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
342 }
343 
LowerSimpleHClassCheck(GateRef gate)344 void TypeMCRLowering::LowerSimpleHClassCheck(GateRef gate)
345 {
346     GateRef frameState = GetFrameState(gate);
347     GateRef compare = BuildCompareHClass(gate, frameState);
348     builder_.DeoptCheck(compare, frameState, DeoptType::INCONSISTENTHCLASS);
349     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
350 }
351 
LowerObjectTypeCompare(GateRef gate)352 void TypeMCRLowering::LowerObjectTypeCompare(GateRef gate)
353 {
354     Environment env(gate, circuit_, &builder_);
355     auto type = acc_.GetObjectTypeAccessor(gate).GetType();
356     if (tsManager_->IsClassInstanceTypeKind(type)) {
357         LowerTSSubtypingCompare(gate);
358     } else if (tsManager_->IsClassTypeKind(type) ||
359                tsManager_->IsObjectTypeKind(type)) {
360         LowerSimpleHClassCompare(gate);
361     } else {
362         LOG_COMPILER(FATAL) << "this branch is unreachable";
363         UNREACHABLE();
364     }
365 }
366 
LowerSimpleHClassCompare(GateRef gate)367 void TypeMCRLowering::LowerSimpleHClassCompare(GateRef gate)
368 {
369     GateRef frameState = GetFrameState(gate);
370     GateRef compare = BuildCompareHClass(gate, frameState) ;
371     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), compare);
372 }
373 
LowerTSSubtypingCompare(GateRef gate)374 void TypeMCRLowering::LowerTSSubtypingCompare(GateRef gate)
375 {
376     GateRef frameState = GetFrameState(gate);
377     Label levelValid(&builder_);
378     Label exit(&builder_);
379     GateRef compare = BuildCompareSubTyping(gate, frameState, &levelValid, &exit);
380     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), compare);
381 }
382 
BuildCompareSubTyping(GateRef gate,GateRef frameState,Label * levelValid,Label * exit)383 GateRef TypeMCRLowering::BuildCompareSubTyping(GateRef gate, GateRef frameState, Label *levelValid, Label *exit)
384 {
385     GateRef receiver = acc_.GetValueIn(gate, 0);
386     bool isHeapObject = acc_.GetObjectTypeAccessor(gate).IsHeapObject();
387     if (!isHeapObject) {
388         builder_.HeapObjectCheck(receiver, frameState);
389     }
390 
391     GateRef aotHCIndex = acc_.GetValueIn(gate, 1);
392     ArgumentAccessor argAcc(circuit_);
393     GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC);
394     JSTaggedValue aotHC = tsManager_->GetValueFromCache(acc_.TryGetValue(aotHCIndex));
395     ASSERT(aotHC.IsJSHClass());
396 
397     int32_t level = JSHClass::Cast(aotHC.GetTaggedObject())->GetLevel();
398     ASSERT(level >= 0);
399 
400     GateRef receiverHClass = builder_.LoadConstOffset(
401         VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
402     GateRef supers = LoadSupers(receiverHClass);
403 
404     auto hclassIndex = acc_.GetConstantValue(aotHCIndex);
405     GateRef aotHCGate = LoadFromConstPool(jsFunc, hclassIndex);
406 
407     if (LIKELY(static_cast<uint32_t>(level) < SubtypingOperator::DEFAULT_SUPERS_CAPACITY)) {
408         return builder_.Equal(aotHCGate, GetValueFromSupers(supers, level));
409     }
410 
411     DEFVAlUE(check, (&builder_), VariableType::BOOL(), builder_.False());
412     GateRef levelGate = builder_.Int32(level);
413     GateRef length = GetLengthFromSupers(supers);
414 
415     builder_.Branch(builder_.Int32LessThan(levelGate, length), levelValid, exit);
416     builder_.Bind(levelValid);
417     {
418         check = builder_.Equal(aotHCGate, GetValueFromSupers(supers, level));
419         builder_.Jump(exit);
420     }
421     builder_.Bind(exit);
422 
423     return *check;
424 }
425 
BuildCompareHClass(GateRef gate,GateRef frameState)426 GateRef TypeMCRLowering::BuildCompareHClass(GateRef gate, GateRef frameState)
427 {
428     GateRef receiver = acc_.GetValueIn(gate, 0);
429     bool isHeapObject = acc_.GetObjectTypeAccessor(gate).IsHeapObject();
430     if (!isHeapObject) {
431         builder_.HeapObjectCheck(receiver, frameState);
432     }
433 
434     GateRef aotHCIndex = acc_.GetValueIn(gate, 1);
435     auto hclassIndex = acc_.GetConstantValue(aotHCIndex);
436     ArgumentAccessor argAcc(circuit_);
437     GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC);
438     GateRef aotHCGate = LoadFromConstPool(jsFunc, hclassIndex);
439     GateRef receiverHClass = builder_.LoadConstOffset(
440         VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
441     return builder_.Equal(aotHCGate, receiverHClass);
442 }
443 
LowerIndexCheck(GateRef gate)444 void TypeMCRLowering::LowerIndexCheck(GateRef gate)
445 {
446     Environment env(gate, circuit_, &builder_);
447     auto deoptType = DeoptType::NOTARRAYIDX;
448 
449     GateRef frameState = GetFrameState(gate);
450     GateRef length = acc_.GetValueIn(gate, 0);
451     GateRef index = acc_.GetValueIn(gate, 1);
452     ASSERT(acc_.GetGateType(length).IsNJSValueType());
453     // UnsignedLessThan can check both lower and upper bounds
454     GateRef lengthCheck = builder_.Int32UnsignedLessThan(index, length);
455     builder_.DeoptCheck(lengthCheck, frameState, deoptType);
456     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), index);
457 }
458 
LowerCallRuntime(GateRef glue,GateRef hirGate,int index,const std::vector<GateRef> & args,bool useLabel)459 GateRef TypeMCRLowering::LowerCallRuntime(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args,
460                                           bool useLabel)
461 {
462     if (useLabel) {
463         GateRef result = builder_.CallRuntime(glue, index, Gate::InvalidGateRef, args, hirGate);
464         return result;
465     } else {
466         const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
467         GateRef target = builder_.IntPtr(index);
468         GateRef result = builder_.Call(cs, glue, target, dependEntry_, args, hirGate);
469         return result;
470     }
471 }
472 
LowerTypeConvert(GateRef gate)473 void TypeMCRLowering::LowerTypeConvert(GateRef gate)
474 {
475     Environment env(gate, circuit_, &builder_);
476     auto leftType = acc_.GetLeftType(gate);
477     auto rightType = acc_.GetRightType(gate);
478     if (rightType.IsNumberType()) {
479         GateRef value = acc_.GetValueIn(gate, 0);
480         if (leftType.IsDigitablePrimitiveType()) {
481             LowerPrimitiveToNumber(gate, value, leftType);
482         }
483         return;
484     }
485 }
486 
LowerPrimitiveToNumber(GateRef dst,GateRef src,GateType srcType)487 void TypeMCRLowering::LowerPrimitiveToNumber(GateRef dst, GateRef src, GateType srcType)
488 {
489     DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
490     if (srcType.IsBooleanType()) {
491         Label exit(&builder_);
492         Label isTrue(&builder_);
493         Label isFalse(&builder_);
494         builder_.Branch(builder_.TaggedIsTrue(src), &isTrue, &isFalse);
495         builder_.Bind(&isTrue);
496         {
497             result = IntToTaggedIntPtr(builder_.Int32(1));
498             builder_.Jump(&exit);
499         }
500         builder_.Bind(&isFalse);
501         {
502             result = IntToTaggedIntPtr(builder_.Int32(0));
503             builder_.Jump(&exit);
504         }
505         builder_.Bind(&exit);
506     } else if (srcType.IsUndefinedType()) {
507         result = DoubleToTaggedDoublePtr(builder_.Double(base::NAN_VALUE));
508     } else if (srcType.IsBigIntType() || srcType.IsNumberType()) {
509         result = src;
510     } else if (srcType.IsNullType()) {
511         result = IntToTaggedIntPtr(builder_.Int32(0));
512     } else {
513         LOG_ECMA(FATAL) << "this branch is unreachable";
514         UNREACHABLE();
515     }
516     acc_.ReplaceGate(dst, builder_.GetState(), builder_.GetDepend(), *result);
517 }
518 
LoadFromConstPool(GateRef jsFunc,size_t index)519 GateRef TypeMCRLowering::LoadFromConstPool(GateRef jsFunc, size_t index)
520 {
521     GateRef constPool = builder_.GetConstPool(jsFunc);
522     return builder_.LoadFromTaggedArray(constPool, index);
523 }
524 
GetObjectFromConstPool(GateRef jsFunc,GateRef index)525 GateRef TypeMCRLowering::GetObjectFromConstPool(GateRef jsFunc, GateRef index)
526 {
527     GateRef constPool = builder_.GetConstPool(jsFunc);
528     return builder_.GetValueFromTaggedArray(constPool, index);
529 }
530 
LowerLoadProperty(GateRef gate)531 void TypeMCRLowering::LowerLoadProperty(GateRef gate)
532 {
533     Environment env(gate, circuit_, &builder_);
534     ASSERT(acc_.GetNumValueIn(gate) == 2);  // 2: receiver, plr
535     GateRef receiver = acc_.GetValueIn(gate, 0);
536     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
537     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
538     ASSERT(plr.IsLocal() || plr.IsFunction());
539 
540     GateRef result = Circuit::NullGate();
541     if (plr.IsNotHole()) {
542         ASSERT(plr.IsLocal());
543         result = builder_.LoadConstOffset(VariableType::JS_ANY(), receiver, plr.GetOffset());
544     } else if (plr.IsLocal()) {
545         result = builder_.LoadConstOffset(VariableType::JS_ANY(), receiver, plr.GetOffset());
546         result = builder_.ConvertHoleAsUndefined(result);
547     } else {
548         result = LoadFromVTable(receiver, plr.GetOffset());
549     }
550 
551     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
552 }
553 
LowerCallGetter(GateRef gate,GateRef glue)554 void TypeMCRLowering::LowerCallGetter(GateRef gate, GateRef glue)
555 {
556     Environment env(gate, circuit_, &builder_);
557     ASSERT(acc_.GetNumValueIn(gate) == 2);  // 2: receiver, plr
558     GateRef receiver = acc_.GetValueIn(gate, 0);
559     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
560 
561     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
562     ASSERT(plr.IsAccessor());
563     GateRef accessor = LoadFromVTable(receiver, plr.GetOffset());
564     GateRef getter = builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::GETTER_OFFSET);
565 
566     DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
567     Label callGetter(&builder_);
568     Label exit(&builder_);
569     builder_.Branch(builder_.IsSpecial(getter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callGetter);
570     builder_.Bind(&callGetter);
571     {
572         result = CallAccessor(glue, gate, getter, receiver, AccessorMode::GETTER);
573         builder_.Jump(&exit);
574     }
575     builder_.Bind(&exit);
576     ReplaceHirWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), *result);
577 }
578 
LowerStoreProperty(GateRef gate)579 void TypeMCRLowering::LowerStoreProperty(GateRef gate)
580 {
581     Environment env(gate, circuit_, &builder_);
582     ASSERT(acc_.GetNumValueIn(gate) == 3);  // 3: receiver, plr, value
583     GateRef receiver = acc_.GetValueIn(gate, 0);
584     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
585     GateRef value = acc_.GetValueIn(gate, 2); // 2: value
586     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
587     ASSERT(plr.IsLocal());
588     auto op = OpCode(acc_.GetOpCode(gate));
589     if (op == OpCode::STORE_PROPERTY) {
590         builder_.StoreConstOffset(VariableType::JS_ANY(), receiver, plr.GetOffset(), value);
591     } else if (op == OpCode::STORE_PROPERTY_NO_BARRIER) {
592         builder_.StoreConstOffset(GetVarType(plr), receiver, plr.GetOffset(), value);
593     } else {
594         UNREACHABLE();
595     }
596     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
597 }
598 
LowerCallSetter(GateRef gate,GateRef glue)599 void TypeMCRLowering::LowerCallSetter(GateRef gate, GateRef glue)
600 {
601     Environment env(gate, circuit_, &builder_);
602     ASSERT(acc_.GetNumValueIn(gate) == 3);  // 3: receiver, plr, value
603     GateRef receiver = acc_.GetValueIn(gate, 0);
604     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
605     GateRef value = acc_.GetValueIn(gate, 2);
606 
607     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
608     ASSERT(plr.IsAccessor());
609     GateRef accessor = LoadFromVTable(receiver, plr.GetOffset());
610     GateRef setter = builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::SETTER_OFFSET);
611 
612     Label callSetter(&builder_);
613     Label exit(&builder_);
614     builder_.Branch(builder_.IsSpecial(setter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callSetter);
615     builder_.Bind(&callSetter);
616     {
617         CallAccessor(glue, gate, setter, receiver, AccessorMode::SETTER, value);
618         builder_.Jump(&exit);
619     }
620     builder_.Bind(&exit);
621     ReplaceHirWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
622 }
623 
LowerLoadArrayLength(GateRef gate)624 void TypeMCRLowering::LowerLoadArrayLength(GateRef gate)
625 {
626     Environment env(gate, circuit_, &builder_);
627     GateRef array = acc_.GetValueIn(gate, 0);
628     GateRef result = builder_.LoadConstOffset(VariableType::INT32(), array, JSArray::LENGTH_OFFSET);
629     acc_.SetGateType(gate, GateType::NJSValue());
630     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
631 }
632 
GetElementSize(BuiltinTypeId id)633 GateRef TypeMCRLowering::GetElementSize(BuiltinTypeId id)
634 {
635     GateRef elementSize = Circuit::NullGate();
636     switch (id) {
637         case BuiltinTypeId::INT8_ARRAY:
638         case BuiltinTypeId::UINT8_ARRAY:
639         case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
640             elementSize = builder_.Int32(sizeof(uint8_t));
641             break;
642         case BuiltinTypeId::INT16_ARRAY:
643         case BuiltinTypeId::UINT16_ARRAY:
644             elementSize = builder_.Int32(sizeof(uint16_t));
645             break;
646         case BuiltinTypeId::INT32_ARRAY:
647         case BuiltinTypeId::UINT32_ARRAY:
648         case BuiltinTypeId::FLOAT32_ARRAY:
649             elementSize = builder_.Int32(sizeof(uint32_t));
650             break;
651         case BuiltinTypeId::FLOAT64_ARRAY:
652             elementSize = builder_.Int32(sizeof(double));
653             break;
654         default:
655             LOG_ECMA(FATAL) << "this branch is unreachable";
656             UNREACHABLE();
657     }
658     return elementSize;
659 }
660 
GetVariableType(BuiltinTypeId id)661 VariableType TypeMCRLowering::GetVariableType(BuiltinTypeId id)
662 {
663     VariableType type = VariableType::JS_ANY();
664     switch (id) {
665         case BuiltinTypeId::INT8_ARRAY:
666         case BuiltinTypeId::UINT8_ARRAY:
667         case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
668             type = VariableType::INT8();
669             break;
670         case BuiltinTypeId::INT16_ARRAY:
671         case BuiltinTypeId::UINT16_ARRAY:
672             type = VariableType::INT16();
673             break;
674         case BuiltinTypeId::INT32_ARRAY:
675         case BuiltinTypeId::UINT32_ARRAY:
676             type = VariableType::INT32();
677             break;
678         case BuiltinTypeId::FLOAT32_ARRAY:
679             type = VariableType::FLOAT32();
680             break;
681         case BuiltinTypeId::FLOAT64_ARRAY:
682             type = VariableType::FLOAT64();
683             break;
684         default:
685             LOG_ECMA(FATAL) << "this branch is unreachable";
686             UNREACHABLE();
687     }
688     return type;
689 }
690 
LowerLoadElement(GateRef gate)691 void TypeMCRLowering::LowerLoadElement(GateRef gate)
692 {
693     Environment env(gate, circuit_, &builder_);
694     auto op = acc_.GetTypedLoadOp(gate);
695     switch (op) {
696         case TypedLoadOp::ARRAY_LOAD_INT_ELEMENT:
697         case TypedLoadOp::ARRAY_LOAD_DOUBLE_ELEMENT:
698         case TypedLoadOp::ARRAY_LOAD_OBJECT_ELEMENT:
699         case TypedLoadOp::ARRAY_LOAD_TAGGED_ELEMENT:
700             LowerArrayLoadElement(gate, ArrayState::PACKED);
701             break;
702         case TypedLoadOp::ARRAY_LOAD_HOLE_TAGGED_ELEMENT:
703             LowerArrayLoadElement(gate, ArrayState::HOLEY);
704             break;
705         case TypedLoadOp::INT8ARRAY_LOAD_ELEMENT:
706             LowerTypedArrayLoadElement(gate, BuiltinTypeId::INT8_ARRAY);
707             break;
708         case TypedLoadOp::UINT8ARRAY_LOAD_ELEMENT:
709             LowerTypedArrayLoadElement(gate, BuiltinTypeId::UINT8_ARRAY);
710             break;
711         case TypedLoadOp::UINT8CLAMPEDARRAY_LOAD_ELEMENT:
712             LowerTypedArrayLoadElement(gate, BuiltinTypeId::UINT8_CLAMPED_ARRAY);
713             break;
714         case TypedLoadOp::INT16ARRAY_LOAD_ELEMENT:
715             LowerTypedArrayLoadElement(gate, BuiltinTypeId::INT16_ARRAY);
716             break;
717         case TypedLoadOp::UINT16ARRAY_LOAD_ELEMENT:
718             LowerTypedArrayLoadElement(gate, BuiltinTypeId::UINT16_ARRAY);
719             break;
720         case TypedLoadOp::INT32ARRAY_LOAD_ELEMENT:
721             LowerTypedArrayLoadElement(gate, BuiltinTypeId::INT32_ARRAY);
722             break;
723         case TypedLoadOp::UINT32ARRAY_LOAD_ELEMENT:
724             LowerTypedArrayLoadElement(gate, BuiltinTypeId::UINT32_ARRAY);
725             break;
726         case TypedLoadOp::FLOAT32ARRAY_LOAD_ELEMENT:
727             LowerTypedArrayLoadElement(gate, BuiltinTypeId::FLOAT32_ARRAY);
728             break;
729         case TypedLoadOp::FLOAT64ARRAY_LOAD_ELEMENT:
730             LowerTypedArrayLoadElement(gate, BuiltinTypeId::FLOAT64_ARRAY);
731             break;
732         default:
733             LOG_ECMA(FATAL) << "this branch is unreachable";
734             UNREACHABLE();
735     }
736 }
737 
LowerCowArrayCheck(GateRef gate,GateRef glue)738 void TypeMCRLowering::LowerCowArrayCheck(GateRef gate, GateRef glue) {
739     Environment env(gate, circuit_, &builder_);
740     GateRef receiver = acc_.GetValueIn(gate, 0);
741     Label notCOWArray(&builder_);
742     Label isCOWArray(&builder_);
743     builder_.Branch(builder_.IsJsCOWArray(receiver), &isCOWArray, &notCOWArray);
744     builder_.Bind(&isCOWArray);
745     {
746         LowerCallRuntime(glue, gate, RTSTUB_ID(CheckAndCopyArray), {receiver}, true);
747         builder_.Jump(&notCOWArray);
748     }
749     builder_.Bind(&notCOWArray);
750 
751     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
752 }
753 
754 // for JSArray
LowerArrayLoadElement(GateRef gate,ArrayState arrayState)755 void TypeMCRLowering::LowerArrayLoadElement(GateRef gate, ArrayState arrayState)
756 {
757     Environment env(gate, circuit_, &builder_);
758     GateRef receiver = acc_.GetValueIn(gate, 0);
759     GateRef index = acc_.GetValueIn(gate, 1);
760     GateRef element = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, JSObject::ELEMENTS_OFFSET);
761     GateRef result = builder_.GetValueFromTaggedArray(element, index);
762     if (arrayState == ArrayState::HOLEY) {
763         result = builder_.ConvertHoleAsUndefined(result);
764     }
765     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
766 }
767 
LowerTypedArrayLoadElement(GateRef gate,BuiltinTypeId id)768 void TypeMCRLowering::LowerTypedArrayLoadElement(GateRef gate, BuiltinTypeId id)
769 {
770     Environment env(gate, circuit_, &builder_);
771     GateRef receiver = acc_.GetValueIn(gate, 0);
772     GateRef arrbuffer =
773         builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
774     GateRef index = acc_.GetValueIn(gate, 1);
775     GateRef elementSize = GetElementSize(id);
776     GateRef offset = builder_.PtrMul(index, elementSize);
777 
778     GateRef data = builder_.PtrAdd(arrbuffer, builder_.IntPtr(ByteArray::DATA_OFFSET));
779     auto type = GetVariableType(id);
780     GateRef result = builder_.Load(type, data, offset);
781     switch (id) {
782         case BuiltinTypeId::INT8_ARRAY:
783             result = builder_.SExtInt8ToInt32(result);
784             break;
785         case BuiltinTypeId::UINT8_ARRAY:
786         case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
787             result = builder_.ZExtInt8ToInt32(result);
788             break;
789         case BuiltinTypeId::INT16_ARRAY:
790             result = builder_.SExtInt16ToInt32(result);
791             break;
792         case BuiltinTypeId::UINT16_ARRAY:
793             result = builder_.ZExtInt16ToInt32(result);
794             break;
795         case BuiltinTypeId::FLOAT32_ARRAY:
796             result = builder_.ExtFloat32ToDouble(result);
797             break;
798         default:
799             break;
800     }
801     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
802 }
803 
LowerStoreElement(GateRef gate,GateRef glue)804 void TypeMCRLowering::LowerStoreElement(GateRef gate, GateRef glue)
805 {
806     Environment env(gate, circuit_, &builder_);
807     auto op = acc_.GetTypedStoreOp(gate);
808     switch (op) {
809         case TypedStoreOp::ARRAY_STORE_ELEMENT:
810             LowerArrayStoreElement(gate, glue);
811             break;
812         case TypedStoreOp::INT8ARRAY_STORE_ELEMENT:
813             LowerTypedArrayStoreElement(gate, BuiltinTypeId::INT8_ARRAY);
814             break;
815         case TypedStoreOp::UINT8ARRAY_STORE_ELEMENT:
816             LowerTypedArrayStoreElement(gate, BuiltinTypeId::UINT8_ARRAY);
817             break;
818         case TypedStoreOp::UINT8CLAMPEDARRAY_STORE_ELEMENT:
819             LowerUInt8ClampedArrayStoreElement(gate);
820             break;
821         case TypedStoreOp::INT16ARRAY_STORE_ELEMENT:
822             LowerTypedArrayStoreElement(gate, BuiltinTypeId::INT16_ARRAY);
823             break;
824         case TypedStoreOp::UINT16ARRAY_STORE_ELEMENT:
825             LowerTypedArrayStoreElement(gate, BuiltinTypeId::UINT16_ARRAY);
826             break;
827         case TypedStoreOp::INT32ARRAY_STORE_ELEMENT:
828             LowerTypedArrayStoreElement(gate, BuiltinTypeId::INT32_ARRAY);
829             break;
830         case TypedStoreOp::UINT32ARRAY_STORE_ELEMENT:
831             LowerTypedArrayStoreElement(gate, BuiltinTypeId::UINT32_ARRAY);
832             break;
833         case TypedStoreOp::FLOAT32ARRAY_STORE_ELEMENT:
834             LowerTypedArrayStoreElement(gate, BuiltinTypeId::FLOAT32_ARRAY);
835             break;
836         case TypedStoreOp::FLOAT64ARRAY_STORE_ELEMENT:
837             LowerTypedArrayStoreElement(gate, BuiltinTypeId::FLOAT64_ARRAY);
838             break;
839         default:
840             LOG_ECMA(FATAL) << "this branch is unreachable";
841             UNREACHABLE();
842     }
843 }
844 
845 // for JSArray
LowerArrayStoreElement(GateRef gate,GateRef glue)846 void TypeMCRLowering::LowerArrayStoreElement(GateRef gate, GateRef glue)
847 {
848     Environment env(gate, circuit_, &builder_);
849     GateRef receiver = acc_.GetValueIn(gate, 0);  // 0: receiver
850     GateRef index = acc_.GetValueIn(gate, 1);     // 1: index
851     GateRef value = acc_.GetValueIn(gate, 2);     // 2: value
852 
853     GateRef element = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, JSObject::ELEMENTS_OFFSET);
854     builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue, element, index, value);
855 
856     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
857 }
858 
859 // for JSTypedArray
LowerTypedArrayStoreElement(GateRef gate,BuiltinTypeId id)860 void TypeMCRLowering::LowerTypedArrayStoreElement(GateRef gate, BuiltinTypeId id)
861 {
862     Environment env(gate, circuit_, &builder_);
863     GateRef receiver = acc_.GetValueIn(gate, 0);
864     GateRef index = acc_.GetValueIn(gate, 1);
865     GateRef value = acc_.GetValueIn(gate, 2);
866 
867     GateRef elementSize = GetElementSize(id);
868     GateRef offset = builder_.PtrMul(index, elementSize);
869     switch (id) {
870         case BuiltinTypeId::INT8_ARRAY:
871         case BuiltinTypeId::UINT8_ARRAY:
872             value = builder_.TruncInt32ToInt8(value);
873             break;
874         case BuiltinTypeId::INT16_ARRAY:
875         case BuiltinTypeId::UINT16_ARRAY:
876             value = builder_.TruncInt32ToInt16(value);
877             break;
878         case BuiltinTypeId::FLOAT32_ARRAY:
879             value = builder_.TruncDoubleToFloat32(value);
880             break;
881         default:
882             break;
883     }
884     GateRef arrbuffer = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver,
885         JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
886     GateRef data = builder_.PtrAdd(arrbuffer, builder_.IntPtr(ByteArray::DATA_OFFSET));
887 
888     builder_.StoreMemory(MemoryType::ELEMENT_TYPE, VariableType::VOID(), data, offset, value);
889     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
890 }
891 
892 // for UInt8ClampedArray
LowerUInt8ClampedArrayStoreElement(GateRef gate)893 void TypeMCRLowering::LowerUInt8ClampedArrayStoreElement(GateRef gate)
894 {
895     Environment env(gate, circuit_, &builder_);
896 
897     GateRef receiver = acc_.GetValueIn(gate, 0);
898     GateRef index = acc_.GetValueIn(gate, 1);
899     GateRef elementSize = builder_.Int32(sizeof(uint8_t));
900     GateRef offset = builder_.PtrMul(index, elementSize);
901     GateRef value = acc_.GetValueIn(gate, 2);
902 
903     DEFVAlUE(result, (&builder_), VariableType::INT32(), value);
904     GateRef topValue = builder_.Int32(static_cast<uint32_t>(UINT8_MAX));
905     GateRef bottomValue = builder_.Int32(static_cast<uint32_t>(0));
906     Label isOverFlow(&builder_);
907     Label notOverFlow(&builder_);
908     Label exit(&builder_);
909     builder_.Branch(builder_.Int32GreaterThan(value, topValue), &isOverFlow, &notOverFlow);
910     builder_.Bind(&isOverFlow);
911     {
912         result = topValue;
913         builder_.Jump(&exit);
914     }
915     builder_.Bind(&notOverFlow);
916     {
917         Label isUnderSpill(&builder_);
918         builder_.Branch(builder_.Int32LessThan(value, bottomValue), &isUnderSpill, &exit);
919         builder_.Bind(&isUnderSpill);
920         {
921             result = bottomValue;
922             builder_.Jump(&exit);
923         }
924     }
925     builder_.Bind(&exit);
926     value = builder_.TruncInt32ToInt8(*result);
927 
928     GateRef arrbuffer = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver,
929         JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
930 
931     GateRef data = builder_.PtrAdd(arrbuffer, builder_.IntPtr(ByteArray::DATA_OFFSET));
932 
933     builder_.StoreMemory(MemoryType::ELEMENT_TYPE, VariableType::VOID(), data, offset, value);
934     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
935 }
936 
DoubleToTaggedDoublePtr(GateRef gate)937 GateRef TypeMCRLowering::DoubleToTaggedDoublePtr(GateRef gate)
938 {
939     return builder_.DoubleToTaggedDoublePtr(gate);
940 }
941 
ChangeInt32ToFloat64(GateRef gate)942 GateRef TypeMCRLowering::ChangeInt32ToFloat64(GateRef gate)
943 {
944     return builder_.ChangeInt32ToFloat64(gate);
945 }
946 
TruncDoubleToInt(GateRef gate)947 GateRef TypeMCRLowering::TruncDoubleToInt(GateRef gate)
948 {
949     return builder_.TruncInt64ToInt32(builder_.TruncFloatToInt64(gate));
950 }
951 
IntToTaggedIntPtr(GateRef x)952 GateRef TypeMCRLowering::IntToTaggedIntPtr(GateRef x)
953 {
954     GateRef val = builder_.SExtInt32ToInt64(x);
955     return builder_.ToTaggedIntPtr(val);
956 }
957 
LowerTypedCallBuitin(GateRef gate)958 void TypeMCRLowering::LowerTypedCallBuitin(GateRef gate)
959 {
960     BuiltinLowering lowering(circuit_);
961     lowering.LowerTypedCallBuitin(gate);
962 }
963 
LowerJSCallTargetFromDefineFuncCheck(GateRef gate)964 void TypeMCRLowering::LowerJSCallTargetFromDefineFuncCheck(GateRef gate)
965 {
966     Environment env(gate, circuit_, &builder_);
967     auto type = acc_.GetParamGateType(gate);
968     if (tsManager_->IsFunctionTypeKind(type)) {
969         GateRef frameState = GetFrameState(gate);
970         auto func = acc_.GetValueIn(gate, 0);
971         GateRef check = builder_.IsOptimized(func);
972         builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT);
973         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
974     } else {
975         LOG_COMPILER(FATAL) << "this branch is unreachable";
976         UNREACHABLE();
977     }
978 }
979 
LowerJSCallTargetTypeCheck(GateRef gate)980 void TypeMCRLowering::LowerJSCallTargetTypeCheck(GateRef gate)
981 {
982     Environment env(gate, circuit_, &builder_);
983     auto type = acc_.GetParamGateType(gate);
984     if (tsManager_->IsFunctionTypeKind(type)) {
985         ArgumentAccessor argAcc(circuit_);
986         GateRef frameState = GetFrameState(gate);
987         GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC);
988         auto func = acc_.GetValueIn(gate, 0);
989         auto methodIndex = acc_.GetValueIn(gate, 1);
990         GateRef isObj = builder_.TaggedIsHeapObject(func);
991         GateRef isOptimized = builder_.IsOptimized(func);
992         GateRef funcMethodTarget = builder_.GetMethodFromFunction(func);
993         GateRef checkFunc = builder_.BoolAnd(isObj, isOptimized);
994         GateRef methodTarget = GetObjectFromConstPool(jsFunc, methodIndex);
995         GateRef check = builder_.BoolAnd(checkFunc, builder_.Equal(funcMethodTarget, methodTarget));
996         builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT);
997         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
998     } else {
999         LOG_COMPILER(FATAL) << "this branch is unreachable";
1000         UNREACHABLE();
1001     }
1002 }
1003 
LowerJSFastCallTargetTypeCheck(GateRef gate)1004 void TypeMCRLowering::LowerJSFastCallTargetTypeCheck(GateRef gate)
1005 {
1006     Environment env(gate, circuit_, &builder_);
1007     auto type = acc_.GetParamGateType(gate);
1008     if (tsManager_->IsFunctionTypeKind(type)) {
1009         ArgumentAccessor argAcc(circuit_);
1010         GateRef frameState = GetFrameState(gate);
1011         GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC);
1012         auto func = acc_.GetValueIn(gate, 0);
1013         auto methodIndex = acc_.GetValueIn(gate, 1);
1014         GateRef isObj = builder_.TaggedIsHeapObject(func);
1015         GateRef canFastCall = builder_.CanFastCall(func);
1016         GateRef funcMethodTarget = builder_.GetMethodFromFunction(func);
1017         GateRef checkFunc = builder_.BoolAnd(isObj, canFastCall);
1018         GateRef methodTarget = GetObjectFromConstPool(jsFunc, methodIndex);
1019         GateRef check = builder_.BoolAnd(checkFunc, builder_.Equal(funcMethodTarget, methodTarget));
1020         builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT);
1021         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1022     } else {
1023         LOG_COMPILER(FATAL) << "this branch is unreachable";
1024         UNREACHABLE();
1025     }
1026 }
1027 
LowerJSCallThisTargetTypeCheck(GateRef gate)1028 void TypeMCRLowering::LowerJSCallThisTargetTypeCheck(GateRef gate)
1029 {
1030     Environment env(gate, circuit_, &builder_);
1031     auto type = acc_.GetParamGateType(gate);
1032     if (tsManager_->IsFunctionTypeKind(type)) {
1033         GateRef frameState = GetFrameState(gate);
1034         auto func = acc_.GetValueIn(gate, 0);
1035         GateRef isObj = builder_.TaggedIsHeapObject(func);
1036         GateRef isOptimized = builder_.IsOptimizedAndNotFastCall(func);
1037         GateRef check = builder_.BoolAnd(isObj, isOptimized);
1038         builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT);
1039         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1040     } else {
1041         LOG_COMPILER(FATAL) << "this branch is unreachable";
1042         UNREACHABLE();
1043     }
1044 }
1045 
LowerJSNoGCCallThisTargetTypeCheck(GateRef gate)1046 void TypeMCRLowering::LowerJSNoGCCallThisTargetTypeCheck(GateRef gate)
1047 {
1048     Environment env(gate, circuit_, &builder_);
1049     auto type = acc_.GetParamGateType(gate);
1050     if (tsManager_->IsFunctionTypeKind(type)) {
1051         GateRef frameState = GetFrameState(gate);
1052         auto func = acc_.GetValueIn(gate, 0);
1053         GateRef isObj = builder_.TaggedIsHeapObject(func);
1054         GateRef isOptimized = builder_.IsOptimizedAndNotFastCall(func);
1055         GateRef methodId = builder_.GetMethodId(func);
1056         GateRef checkOptimized = builder_.BoolAnd(isObj, isOptimized);
1057         GateRef check = builder_.BoolAnd(checkOptimized, builder_.Equal(methodId, acc_.GetValueIn(gate, 1)));
1058         builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT);
1059         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1060     } else {
1061         LOG_COMPILER(FATAL) << "this branch is unreachable";
1062         UNREACHABLE();
1063     }
1064 }
1065 
LowerJSFastCallThisTargetTypeCheck(GateRef gate)1066 void TypeMCRLowering::LowerJSFastCallThisTargetTypeCheck(GateRef gate)
1067 {
1068     Environment env(gate, circuit_, &builder_);
1069     auto type = acc_.GetParamGateType(gate);
1070     if (tsManager_->IsFunctionTypeKind(type)) {
1071         GateRef frameState = GetFrameState(gate);
1072         auto func = acc_.GetValueIn(gate, 0);
1073         GateRef isObj = builder_.TaggedIsHeapObject(func);
1074         GateRef canFastCall = builder_.CanFastCall(func);
1075         GateRef check = builder_.BoolAnd(isObj, canFastCall);
1076         builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT);
1077         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1078     } else {
1079         LOG_COMPILER(FATAL) << "this branch is unreachable";
1080         UNREACHABLE();
1081     }
1082 }
1083 
LowerJSNoGCFastCallThisTargetTypeCheck(GateRef gate)1084 void TypeMCRLowering::LowerJSNoGCFastCallThisTargetTypeCheck(GateRef gate)
1085 {
1086     Environment env(gate, circuit_, &builder_);
1087     auto type = acc_.GetParamGateType(gate);
1088     if (tsManager_->IsFunctionTypeKind(type)) {
1089         GateRef frameState = GetFrameState(gate);
1090         auto func = acc_.GetValueIn(gate, 0);
1091         GateRef isObj = builder_.TaggedIsHeapObject(func);
1092         GateRef canFastCall = builder_.CanFastCall(func);
1093         GateRef methodId = builder_.GetMethodId(func);
1094         GateRef checkOptimized = builder_.BoolAnd(isObj, canFastCall);
1095         GateRef check = builder_.BoolAnd(checkOptimized, builder_.Equal(methodId, acc_.GetValueIn(gate, 1)));
1096         builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT);
1097         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1098     } else {
1099         LOG_COMPILER(FATAL) << "this branch is unreachable";
1100         UNREACHABLE();
1101     }
1102 }
1103 
LowerCallTargetCheck(GateRef gate)1104 void TypeMCRLowering::LowerCallTargetCheck(GateRef gate)
1105 {
1106     Environment env(gate, circuit_, &builder_);
1107     GateRef frameState = GetFrameState(gate);
1108 
1109     BuiltinLowering lowering(circuit_);
1110     GateRef funcheck = lowering.LowerCallTargetCheck(&env, gate);
1111     GateRef check = lowering.CheckPara(gate, funcheck);
1112     builder_.DeoptCheck(check, frameState, DeoptType::NOTCALLTGT);
1113 
1114     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1115 }
1116 
LowerJSInlineTargetTypeCheck(GateRef gate)1117 void TypeMCRLowering::LowerJSInlineTargetTypeCheck(GateRef gate)
1118 {
1119     Environment env(gate, circuit_, &builder_);
1120     GateRef frameState = GetFrameState(gate);
1121     auto func = acc_.GetValueIn(gate, 0);
1122     GateRef isObj = builder_.TaggedIsHeapObject(func);
1123     GateRef isJsFunc = builder_.IsJSFunction(func);
1124     GateRef checkFunc = builder_.BoolAnd(isObj, isJsFunc);
1125     GateRef GetMethodId = builder_.GetMethodId(func);
1126     GateRef check = builder_.BoolAnd(checkFunc, builder_.Equal(GetMethodId, acc_.GetValueIn(gate, 1)));
1127     builder_.DeoptCheck(check, frameState, DeoptType::INLINEFAIL);
1128     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1129 }
1130 
LowerTypedNewAllocateThis(GateRef gate,GateRef glue)1131 void TypeMCRLowering::LowerTypedNewAllocateThis(GateRef gate, GateRef glue)
1132 {
1133     Environment env(gate, circuit_, &builder_);
1134     ArgumentAccessor argAcc(circuit_);
1135     GateRef frameState = GetFrameState(gate);
1136     GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC);
1137 
1138     GateRef ctor = acc_.GetValueIn(gate, 0);
1139 
1140     DEFVAlUE(thisObj, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1141     Label allocate(&builder_);
1142     Label exit(&builder_);
1143 
1144     GateRef isBase = builder_.IsBase(ctor);
1145     builder_.Branch(isBase, &allocate, &exit);
1146     builder_.Bind(&allocate);
1147     {
1148         // add typecheck to detect protoOrHclass is equal with ihclass,
1149         // if pass typecheck: 1.no need to check whether hclass is valid 2.no need to check return result
1150         GateRef protoOrHclass = builder_.LoadConstOffset(VariableType::JS_ANY(), ctor,
1151             JSFunction::PROTO_OR_DYNCLASS_OFFSET);
1152         GateRef ihclassIndex = acc_.GetValueIn(gate, 1);
1153         GateRef ihclass = GetObjectFromConstPool(jsFunc, ihclassIndex);
1154         GateRef check = builder_.Equal(protoOrHclass, ihclass);
1155         builder_.DeoptCheck(check, frameState, DeoptType::NOTNEWOBJ);
1156 
1157         thisObj = builder_.CallStub(glue, gate, CommonStubCSigns::NewJSObject, { glue, protoOrHclass });
1158         builder_.Jump(&exit);
1159     }
1160     builder_.Bind(&exit);
1161     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *thisObj);
1162 }
1163 
LowerTypedSuperAllocateThis(GateRef gate,GateRef glue)1164 void TypeMCRLowering::LowerTypedSuperAllocateThis(GateRef gate, GateRef glue)
1165 {
1166     Environment env(gate, circuit_, &builder_);
1167     GateRef superCtor = acc_.GetValueIn(gate, 0);
1168     GateRef newTarget = acc_.GetValueIn(gate, 1);
1169 
1170     DEFVAlUE(thisObj, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1171     Label allocate(&builder_);
1172     Label exit(&builder_);
1173 
1174     GateRef isBase = builder_.IsBase(superCtor);
1175     builder_.Branch(isBase, &allocate, &exit);
1176     builder_.Bind(&allocate);
1177     {
1178         GateRef protoOrHclass = builder_.LoadConstOffset(VariableType::JS_ANY(), newTarget,
1179             JSFunction::PROTO_OR_DYNCLASS_OFFSET);
1180         GateRef check = builder_.IsJSHClass(protoOrHclass);
1181         GateRef frameState = GetFrameState(gate);
1182         builder_.DeoptCheck(check, frameState, DeoptType::NOTNEWOBJ);
1183 
1184         thisObj = builder_.CallStub(glue, gate, CommonStubCSigns::NewJSObject, { glue, protoOrHclass });
1185         builder_.Jump(&exit);
1186     }
1187     builder_.Bind(&exit);
1188     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *thisObj);
1189 }
1190 
LowerGetSuperConstructor(GateRef gate)1191 void TypeMCRLowering::LowerGetSuperConstructor(GateRef gate)
1192 {
1193     Environment env(gate, circuit_, &builder_);
1194     GateRef ctor = acc_.GetValueIn(gate, 0);
1195     GateRef hclass = builder_.LoadHClass(ctor);
1196     GateRef superCtor = builder_.LoadConstOffset(VariableType::JS_ANY(), hclass, JSHClass::PROTOTYPE_OFFSET);
1197     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), superCtor);
1198 }
1199 
LoadFromVTable(GateRef receiver,size_t index)1200 GateRef TypeMCRLowering::LoadFromVTable(GateRef receiver, size_t index)
1201 {
1202     GateRef hclass = builder_.LoadConstOffset(
1203         VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
1204     GateRef vtable = builder_.LoadConstOffset(VariableType::JS_ANY(),
1205         hclass, JSHClass::VTABLE_OFFSET);
1206 
1207     GateRef itemOwner = builder_.LoadFromTaggedArray(vtable, VTable::TupleItem::OWNER + index);
1208     GateRef itemOffset = builder_.LoadFromTaggedArray(vtable, VTable::TupleItem::OFFSET + index);
1209     return builder_.Load(VariableType::JS_ANY(), itemOwner, builder_.TaggedGetInt(itemOffset));
1210 }
1211 
GetVarType(PropertyLookupResult plr)1212 VariableType TypeMCRLowering::GetVarType(PropertyLookupResult plr)
1213 {
1214     if (plr.GetRepresentation() == Representation::DOUBLE) {
1215         return kungfu::VariableType::FLOAT64();
1216     } else if (plr.GetRepresentation() == Representation::INT) {
1217         return kungfu::VariableType::INT32();
1218     } else {
1219         return kungfu::VariableType::INT64();
1220     }
1221 }
1222 
LoadSupers(GateRef hclass)1223 GateRef TypeMCRLowering::LoadSupers(GateRef hclass)
1224 {
1225     return builder_.LoadConstOffset(VariableType::JS_ANY(), hclass, JSHClass::SUPERS_OFFSET);
1226 }
1227 
GetLengthFromSupers(GateRef supers)1228 GateRef TypeMCRLowering::GetLengthFromSupers(GateRef supers)
1229 {
1230     return builder_.LoadConstOffset(VariableType::INT32(), supers, TaggedArray::EXTRACT_LENGTH_OFFSET);
1231 }
1232 
GetValueFromSupers(GateRef supers,size_t index)1233 GateRef TypeMCRLowering::GetValueFromSupers(GateRef supers, size_t index)
1234 {
1235     GateRef val = builder_.LoadFromTaggedArray(supers, index);
1236     return builder_.LoadObjectFromWeakRef(val);
1237 }
1238 
CallAccessor(GateRef glue,GateRef gate,GateRef function,GateRef receiver,AccessorMode mode,GateRef value)1239 GateRef TypeMCRLowering::CallAccessor(GateRef glue, GateRef gate, GateRef function, GateRef receiver,
1240     AccessorMode mode, GateRef value)
1241 {
1242     const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(JSCall));
1243     GateRef target = builder_.IntPtr(RTSTUB_ID(JSCall));
1244     GateRef newTarget = builder_.Undefined();
1245     GateRef argc = builder_.Int64(NUM_MANDATORY_JSFUNC_ARGS + (mode == AccessorMode::SETTER ? 1 : 0));  // 1: value
1246     std::vector<GateRef> args { glue, argc, function, newTarget, receiver };
1247     if (mode == AccessorMode::SETTER) {
1248         args.emplace_back(value);
1249     }
1250 
1251     return builder_.Call(cs, glue, target, builder_.GetDepend(), args, gate);
1252 }
1253 
ReplaceHirWithPendingException(GateRef hirGate,GateRef glue,GateRef state,GateRef depend,GateRef value)1254 void TypeMCRLowering::ReplaceHirWithPendingException(GateRef hirGate, GateRef glue, GateRef state, GateRef depend,
1255                                                      GateRef value)
1256 {
1257     auto condition = builder_.HasPendingException(glue);
1258     GateRef ifBranch = builder_.Branch(state, condition);
1259     GateRef ifTrue = builder_.IfTrue(ifBranch);
1260     GateRef ifFalse = builder_.IfFalse(ifBranch);
1261     GateRef eDepend = builder_.DependRelay(ifTrue, depend);
1262     GateRef sDepend = builder_.DependRelay(ifFalse, depend);
1263 
1264     StateDepend success(ifFalse, sDepend);
1265     StateDepend exception(ifTrue, eDepend);
1266     acc_.ReplaceHirWithIfBranch(hirGate, success, exception, value);
1267 }
1268 
LowerLoadGetter(GateRef gate)1269 void TypeMCRLowering::LowerLoadGetter(GateRef gate)
1270 {
1271     Environment env(gate, circuit_, &builder_);
1272     ASSERT(acc_.GetNumValueIn(gate) == 2);  // 2: receiver, plr
1273     GateRef receiver = acc_.GetValueIn(gate, 0);
1274     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1275 
1276     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1277     ASSERT(plr.IsAccessor());
1278     GateRef accessor = LoadFromVTable(receiver, plr.GetOffset());
1279     GateRef getter = builder_.Load(VariableType::JS_ANY(), accessor,
1280                                    builder_.IntPtr(AccessorData::GETTER_OFFSET));
1281     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), getter);
1282 }
1283 
LowerLoadSetter(GateRef gate)1284 void TypeMCRLowering::LowerLoadSetter(GateRef gate)
1285 {
1286     Environment env(gate, circuit_, &builder_);
1287     ASSERT(acc_.GetNumValueIn(gate) == 2);  // 2: receiver, plr
1288     GateRef receiver = acc_.GetValueIn(gate, 0);
1289     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1290 
1291     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1292     ASSERT(plr.IsAccessor());
1293     GateRef accessor = LoadFromVTable(receiver, plr.GetOffset());
1294     GateRef setter = builder_.Load(VariableType::JS_ANY(),
1295         accessor, builder_.IntPtr(AccessorData::SETTER_OFFSET));
1296     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), setter);
1297 }
1298 
1299 // subtyping check and hclss check
LowerInlineAccessorCheck(GateRef gate)1300 void TypeMCRLowering::LowerInlineAccessorCheck(GateRef gate)
1301 {
1302     Environment env(gate, circuit_, &builder_);
1303     GateRef receiver = acc_.GetValueIn(gate, 0);
1304     GateRef frameState = acc_.GetFrameState(gate);
1305     builder_.HeapObjectCheck(receiver, frameState);
1306 
1307     GateRef aotHCIndex = acc_.GetValueIn(gate, 1);
1308     ArgumentAccessor argAcc(circuit_);
1309     GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC);
1310     JSTaggedValue aotHC = tsManager_->GetValueFromCache(acc_.TryGetValue(aotHCIndex));
1311     ASSERT(aotHC.IsJSHClass());
1312 
1313     int32_t level = JSHClass::Cast(aotHC.GetTaggedObject())->GetLevel();
1314     ASSERT(level >= 0);
1315 
1316     GateRef receiverHClass = builder_.LoadConstOffset(
1317         VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
1318     GateRef supers = LoadSupers(receiverHClass);
1319 
1320     auto hclassIndex = acc_.GetConstantValue(aotHCIndex);
1321     GateRef aotHCGate = LoadFromConstPool(jsFunc, hclassIndex);
1322     GateRef hclassCompare = builder_.Equal(aotHCGate, receiverHClass);
1323     if (LIKELY(static_cast<uint32_t>(level) < SubtypingOperator::DEFAULT_SUPERS_CAPACITY)) {
1324         GateRef subtypingCompare = builder_.Equal(aotHCGate, GetValueFromSupers(supers, level));
1325         GateRef compare = builder_.BoolAnd(hclassCompare, subtypingCompare);
1326         builder_.DeoptCheck(compare, frameState, DeoptType::INCONSISTENTHCLASS);
1327         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1328         return;
1329     }
1330 
1331     Label levelValid(&builder_);
1332     Label exit(&builder_);
1333     DEFVAlUE(check, (&builder_), VariableType::BOOL(), builder_.False());
1334     GateRef levelGate = builder_.Int32(level);
1335     GateRef length = GetLengthFromSupers(supers);
1336 
1337     builder_.Branch(builder_.Int32LessThan(levelGate, length), &levelValid, &exit);
1338     builder_.Bind(&levelValid);
1339     {
1340         check = builder_.Equal(aotHCGate, GetValueFromSupers(supers, level));
1341         builder_.Jump(&exit);
1342     }
1343     builder_.Bind(&exit);
1344 
1345     GateRef compare = builder_.BoolAnd(hclassCompare, *check);
1346     builder_.DeoptCheck(compare, frameState, DeoptType::INCONSISTENTHCLASS);
1347     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1348 }
1349 }  // namespace panda::ecmascript::kungfu
1350