• 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 {
740     Environment env(gate, circuit_, &builder_);
741     GateRef receiver = acc_.GetValueIn(gate, 0);
742     Label notCOWArray(&builder_);
743     Label isCOWArray(&builder_);
744     builder_.Branch(builder_.IsJsCOWArray(receiver), &isCOWArray, &notCOWArray);
745     builder_.Bind(&isCOWArray);
746     {
747         LowerCallRuntime(glue, gate, RTSTUB_ID(CheckAndCopyArray), {receiver}, true);
748         builder_.Jump(&notCOWArray);
749     }
750     builder_.Bind(&notCOWArray);
751 
752     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
753 }
754 
755 // for JSArray
LowerArrayLoadElement(GateRef gate,ArrayState arrayState)756 void TypeMCRLowering::LowerArrayLoadElement(GateRef gate, ArrayState arrayState)
757 {
758     Environment env(gate, circuit_, &builder_);
759     GateRef receiver = acc_.GetValueIn(gate, 0);
760     GateRef index = acc_.GetValueIn(gate, 1);
761     GateRef element = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, JSObject::ELEMENTS_OFFSET);
762     GateRef result = builder_.GetValueFromTaggedArray(element, index);
763     if (arrayState == ArrayState::HOLEY) {
764         result = builder_.ConvertHoleAsUndefined(result);
765     }
766     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
767 }
768 
LowerTypedArrayLoadElement(GateRef gate,BuiltinTypeId id)769 void TypeMCRLowering::LowerTypedArrayLoadElement(GateRef gate, BuiltinTypeId id)
770 {
771     Environment env(gate, circuit_, &builder_);
772     GateRef receiver = acc_.GetValueIn(gate, 0);
773     GateRef arrbuffer =
774         builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
775     GateRef index = acc_.GetValueIn(gate, 1);
776     GateRef elementSize = GetElementSize(id);
777     GateRef offset = builder_.PtrMul(index, elementSize);
778 
779     GateRef data = builder_.PtrAdd(arrbuffer, builder_.IntPtr(ByteArray::DATA_OFFSET));
780     auto type = GetVariableType(id);
781     GateRef result = builder_.Load(type, data, offset);
782     switch (id) {
783         case BuiltinTypeId::INT8_ARRAY:
784             result = builder_.SExtInt8ToInt32(result);
785             break;
786         case BuiltinTypeId::UINT8_ARRAY:
787         case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
788             result = builder_.ZExtInt8ToInt32(result);
789             break;
790         case BuiltinTypeId::INT16_ARRAY:
791             result = builder_.SExtInt16ToInt32(result);
792             break;
793         case BuiltinTypeId::UINT16_ARRAY:
794             result = builder_.ZExtInt16ToInt32(result);
795             break;
796         case BuiltinTypeId::FLOAT32_ARRAY:
797             result = builder_.ExtFloat32ToDouble(result);
798             break;
799         default:
800             break;
801     }
802     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
803 }
804 
LowerStoreElement(GateRef gate,GateRef glue)805 void TypeMCRLowering::LowerStoreElement(GateRef gate, GateRef glue)
806 {
807     Environment env(gate, circuit_, &builder_);
808     auto op = acc_.GetTypedStoreOp(gate);
809     switch (op) {
810         case TypedStoreOp::ARRAY_STORE_ELEMENT:
811             LowerArrayStoreElement(gate, glue);
812             break;
813         case TypedStoreOp::INT8ARRAY_STORE_ELEMENT:
814             LowerTypedArrayStoreElement(gate, BuiltinTypeId::INT8_ARRAY);
815             break;
816         case TypedStoreOp::UINT8ARRAY_STORE_ELEMENT:
817             LowerTypedArrayStoreElement(gate, BuiltinTypeId::UINT8_ARRAY);
818             break;
819         case TypedStoreOp::UINT8CLAMPEDARRAY_STORE_ELEMENT:
820             LowerUInt8ClampedArrayStoreElement(gate);
821             break;
822         case TypedStoreOp::INT16ARRAY_STORE_ELEMENT:
823             LowerTypedArrayStoreElement(gate, BuiltinTypeId::INT16_ARRAY);
824             break;
825         case TypedStoreOp::UINT16ARRAY_STORE_ELEMENT:
826             LowerTypedArrayStoreElement(gate, BuiltinTypeId::UINT16_ARRAY);
827             break;
828         case TypedStoreOp::INT32ARRAY_STORE_ELEMENT:
829             LowerTypedArrayStoreElement(gate, BuiltinTypeId::INT32_ARRAY);
830             break;
831         case TypedStoreOp::UINT32ARRAY_STORE_ELEMENT:
832             LowerTypedArrayStoreElement(gate, BuiltinTypeId::UINT32_ARRAY);
833             break;
834         case TypedStoreOp::FLOAT32ARRAY_STORE_ELEMENT:
835             LowerTypedArrayStoreElement(gate, BuiltinTypeId::FLOAT32_ARRAY);
836             break;
837         case TypedStoreOp::FLOAT64ARRAY_STORE_ELEMENT:
838             LowerTypedArrayStoreElement(gate, BuiltinTypeId::FLOAT64_ARRAY);
839             break;
840         default:
841             LOG_ECMA(FATAL) << "this branch is unreachable";
842             UNREACHABLE();
843     }
844 }
845 
846 // for JSArray
LowerArrayStoreElement(GateRef gate,GateRef glue)847 void TypeMCRLowering::LowerArrayStoreElement(GateRef gate, GateRef glue)
848 {
849     Environment env(gate, circuit_, &builder_);
850     GateRef receiver = acc_.GetValueIn(gate, 0);  // 0: receiver
851     GateRef index = acc_.GetValueIn(gate, 1);     // 1: index
852     GateRef value = acc_.GetValueIn(gate, 2);     // 2: value
853 
854     GateRef element = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, JSObject::ELEMENTS_OFFSET);
855     builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue, element, index, value);
856 
857     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
858 }
859 
860 // for JSTypedArray
LowerTypedArrayStoreElement(GateRef gate,BuiltinTypeId id)861 void TypeMCRLowering::LowerTypedArrayStoreElement(GateRef gate, BuiltinTypeId id)
862 {
863     Environment env(gate, circuit_, &builder_);
864     GateRef receiver = acc_.GetValueIn(gate, 0);
865     GateRef index = acc_.GetValueIn(gate, 1);
866     GateRef value = acc_.GetValueIn(gate, 2);
867 
868     GateRef elementSize = GetElementSize(id);
869     GateRef offset = builder_.PtrMul(index, elementSize);
870     switch (id) {
871         case BuiltinTypeId::INT8_ARRAY:
872         case BuiltinTypeId::UINT8_ARRAY:
873             value = builder_.TruncInt32ToInt8(value);
874             break;
875         case BuiltinTypeId::INT16_ARRAY:
876         case BuiltinTypeId::UINT16_ARRAY:
877             value = builder_.TruncInt32ToInt16(value);
878             break;
879         case BuiltinTypeId::FLOAT32_ARRAY:
880             value = builder_.TruncDoubleToFloat32(value);
881             break;
882         default:
883             break;
884     }
885     GateRef arrbuffer = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver,
886         JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
887     GateRef data = builder_.PtrAdd(arrbuffer, builder_.IntPtr(ByteArray::DATA_OFFSET));
888 
889     builder_.StoreMemory(MemoryType::ELEMENT_TYPE, VariableType::VOID(), data, offset, value);
890     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
891 }
892 
893 // for UInt8ClampedArray
LowerUInt8ClampedArrayStoreElement(GateRef gate)894 void TypeMCRLowering::LowerUInt8ClampedArrayStoreElement(GateRef gate)
895 {
896     Environment env(gate, circuit_, &builder_);
897 
898     GateRef receiver = acc_.GetValueIn(gate, 0);
899     GateRef index = acc_.GetValueIn(gate, 1);
900     GateRef elementSize = builder_.Int32(sizeof(uint8_t));
901     GateRef offset = builder_.PtrMul(index, elementSize);
902     GateRef value = acc_.GetValueIn(gate, 2);
903 
904     DEFVAlUE(result, (&builder_), VariableType::INT32(), value);
905     GateRef topValue = builder_.Int32(static_cast<uint32_t>(UINT8_MAX));
906     GateRef bottomValue = builder_.Int32(static_cast<uint32_t>(0));
907     Label isOverFlow(&builder_);
908     Label notOverFlow(&builder_);
909     Label exit(&builder_);
910     builder_.Branch(builder_.Int32GreaterThan(value, topValue), &isOverFlow, &notOverFlow);
911     builder_.Bind(&isOverFlow);
912     {
913         result = topValue;
914         builder_.Jump(&exit);
915     }
916     builder_.Bind(&notOverFlow);
917     {
918         Label isUnderSpill(&builder_);
919         builder_.Branch(builder_.Int32LessThan(value, bottomValue), &isUnderSpill, &exit);
920         builder_.Bind(&isUnderSpill);
921         {
922             result = bottomValue;
923             builder_.Jump(&exit);
924         }
925     }
926     builder_.Bind(&exit);
927     value = builder_.TruncInt32ToInt8(*result);
928 
929     GateRef arrbuffer = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver,
930         JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
931 
932     GateRef data = builder_.PtrAdd(arrbuffer, builder_.IntPtr(ByteArray::DATA_OFFSET));
933 
934     builder_.StoreMemory(MemoryType::ELEMENT_TYPE, VariableType::VOID(), data, offset, value);
935     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
936 }
937 
DoubleToTaggedDoublePtr(GateRef gate)938 GateRef TypeMCRLowering::DoubleToTaggedDoublePtr(GateRef gate)
939 {
940     return builder_.DoubleToTaggedDoublePtr(gate);
941 }
942 
ChangeInt32ToFloat64(GateRef gate)943 GateRef TypeMCRLowering::ChangeInt32ToFloat64(GateRef gate)
944 {
945     return builder_.ChangeInt32ToFloat64(gate);
946 }
947 
TruncDoubleToInt(GateRef gate)948 GateRef TypeMCRLowering::TruncDoubleToInt(GateRef gate)
949 {
950     return builder_.TruncInt64ToInt32(builder_.TruncFloatToInt64(gate));
951 }
952 
IntToTaggedIntPtr(GateRef x)953 GateRef TypeMCRLowering::IntToTaggedIntPtr(GateRef x)
954 {
955     GateRef val = builder_.SExtInt32ToInt64(x);
956     return builder_.ToTaggedIntPtr(val);
957 }
958 
LowerTypedCallBuitin(GateRef gate)959 void TypeMCRLowering::LowerTypedCallBuitin(GateRef gate)
960 {
961     BuiltinLowering lowering(circuit_);
962     lowering.LowerTypedCallBuitin(gate);
963 }
964 
LowerJSCallTargetFromDefineFuncCheck(GateRef gate)965 void TypeMCRLowering::LowerJSCallTargetFromDefineFuncCheck(GateRef gate)
966 {
967     Environment env(gate, circuit_, &builder_);
968     auto type = acc_.GetParamGateType(gate);
969     if (tsManager_->IsFunctionTypeKind(type)) {
970         GateRef frameState = GetFrameState(gate);
971         auto func = acc_.GetValueIn(gate, 0);
972         GateRef check = builder_.IsOptimized(func);
973         builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT);
974         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
975     } else {
976         LOG_COMPILER(FATAL) << "this branch is unreachable";
977         UNREACHABLE();
978     }
979 }
980 
LowerJSCallTargetTypeCheck(GateRef gate)981 void TypeMCRLowering::LowerJSCallTargetTypeCheck(GateRef gate)
982 {
983     Environment env(gate, circuit_, &builder_);
984     auto type = acc_.GetParamGateType(gate);
985     if (tsManager_->IsFunctionTypeKind(type)) {
986         ArgumentAccessor argAcc(circuit_);
987         GateRef frameState = GetFrameState(gate);
988         GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC);
989         auto func = acc_.GetValueIn(gate, 0);
990         auto methodIndex = acc_.GetValueIn(gate, 1);
991         GateRef isObj = builder_.TaggedIsHeapObject(func);
992         GateRef isOptimized = builder_.IsOptimized(func);
993         GateRef funcMethodTarget = builder_.GetMethodFromFunction(func);
994         GateRef checkFunc = builder_.BoolAnd(isObj, isOptimized);
995         GateRef methodTarget = GetObjectFromConstPool(jsFunc, methodIndex);
996         GateRef check = builder_.BoolAnd(checkFunc, builder_.Equal(funcMethodTarget, methodTarget));
997         builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT);
998         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
999     } else {
1000         LOG_COMPILER(FATAL) << "this branch is unreachable";
1001         UNREACHABLE();
1002     }
1003 }
1004 
LowerJSFastCallTargetTypeCheck(GateRef gate)1005 void TypeMCRLowering::LowerJSFastCallTargetTypeCheck(GateRef gate)
1006 {
1007     Environment env(gate, circuit_, &builder_);
1008     auto type = acc_.GetParamGateType(gate);
1009     if (tsManager_->IsFunctionTypeKind(type)) {
1010         ArgumentAccessor argAcc(circuit_);
1011         GateRef frameState = GetFrameState(gate);
1012         GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC);
1013         auto func = acc_.GetValueIn(gate, 0);
1014         auto methodIndex = acc_.GetValueIn(gate, 1);
1015         GateRef isObj = builder_.TaggedIsHeapObject(func);
1016         GateRef canFastCall = builder_.CanFastCall(func);
1017         GateRef funcMethodTarget = builder_.GetMethodFromFunction(func);
1018         GateRef checkFunc = builder_.BoolAnd(isObj, canFastCall);
1019         GateRef methodTarget = GetObjectFromConstPool(jsFunc, methodIndex);
1020         GateRef check = builder_.BoolAnd(checkFunc, builder_.Equal(funcMethodTarget, methodTarget));
1021         builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT);
1022         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1023     } else {
1024         LOG_COMPILER(FATAL) << "this branch is unreachable";
1025         UNREACHABLE();
1026     }
1027 }
1028 
LowerJSCallThisTargetTypeCheck(GateRef gate)1029 void TypeMCRLowering::LowerJSCallThisTargetTypeCheck(GateRef gate)
1030 {
1031     Environment env(gate, circuit_, &builder_);
1032     auto type = acc_.GetParamGateType(gate);
1033     if (tsManager_->IsFunctionTypeKind(type)) {
1034         GateRef frameState = GetFrameState(gate);
1035         auto func = acc_.GetValueIn(gate, 0);
1036         GateRef isObj = builder_.TaggedIsHeapObject(func);
1037         GateRef isOptimized = builder_.IsOptimizedAndNotFastCall(func);
1038         GateRef check = builder_.BoolAnd(isObj, isOptimized);
1039         builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT);
1040         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1041     } else {
1042         LOG_COMPILER(FATAL) << "this branch is unreachable";
1043         UNREACHABLE();
1044     }
1045 }
1046 
LowerJSNoGCCallThisTargetTypeCheck(GateRef gate)1047 void TypeMCRLowering::LowerJSNoGCCallThisTargetTypeCheck(GateRef gate)
1048 {
1049     Environment env(gate, circuit_, &builder_);
1050     auto type = acc_.GetParamGateType(gate);
1051     if (tsManager_->IsFunctionTypeKind(type)) {
1052         GateRef frameState = GetFrameState(gate);
1053         auto func = acc_.GetValueIn(gate, 0);
1054         GateRef isObj = builder_.TaggedIsHeapObject(func);
1055         GateRef isOptimized = builder_.IsOptimizedAndNotFastCall(func);
1056         GateRef methodId = builder_.GetMethodId(func);
1057         GateRef checkOptimized = builder_.BoolAnd(isObj, isOptimized);
1058         GateRef check = builder_.BoolAnd(checkOptimized, builder_.Equal(methodId, acc_.GetValueIn(gate, 1)));
1059         builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT);
1060         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1061     } else {
1062         LOG_COMPILER(FATAL) << "this branch is unreachable";
1063         UNREACHABLE();
1064     }
1065 }
1066 
LowerJSFastCallThisTargetTypeCheck(GateRef gate)1067 void TypeMCRLowering::LowerJSFastCallThisTargetTypeCheck(GateRef gate)
1068 {
1069     Environment env(gate, circuit_, &builder_);
1070     auto type = acc_.GetParamGateType(gate);
1071     if (tsManager_->IsFunctionTypeKind(type)) {
1072         GateRef frameState = GetFrameState(gate);
1073         auto func = acc_.GetValueIn(gate, 0);
1074         GateRef isObj = builder_.TaggedIsHeapObject(func);
1075         GateRef canFastCall = builder_.CanFastCall(func);
1076         GateRef check = builder_.BoolAnd(isObj, canFastCall);
1077         builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT);
1078         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1079     } else {
1080         LOG_COMPILER(FATAL) << "this branch is unreachable";
1081         UNREACHABLE();
1082     }
1083 }
1084 
LowerJSNoGCFastCallThisTargetTypeCheck(GateRef gate)1085 void TypeMCRLowering::LowerJSNoGCFastCallThisTargetTypeCheck(GateRef gate)
1086 {
1087     Environment env(gate, circuit_, &builder_);
1088     auto type = acc_.GetParamGateType(gate);
1089     if (tsManager_->IsFunctionTypeKind(type)) {
1090         GateRef frameState = GetFrameState(gate);
1091         auto func = acc_.GetValueIn(gate, 0);
1092         GateRef isObj = builder_.TaggedIsHeapObject(func);
1093         GateRef canFastCall = builder_.CanFastCall(func);
1094         GateRef methodId = builder_.GetMethodId(func);
1095         GateRef checkOptimized = builder_.BoolAnd(isObj, canFastCall);
1096         GateRef check = builder_.BoolAnd(checkOptimized, builder_.Equal(methodId, acc_.GetValueIn(gate, 1)));
1097         builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT);
1098         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1099     } else {
1100         LOG_COMPILER(FATAL) << "this branch is unreachable";
1101         UNREACHABLE();
1102     }
1103 }
1104 
LowerCallTargetCheck(GateRef gate)1105 void TypeMCRLowering::LowerCallTargetCheck(GateRef gate)
1106 {
1107     Environment env(gate, circuit_, &builder_);
1108     GateRef frameState = GetFrameState(gate);
1109 
1110     BuiltinLowering lowering(circuit_);
1111     GateRef funcheck = lowering.LowerCallTargetCheck(&env, gate);
1112     GateRef check = lowering.CheckPara(gate, funcheck);
1113     builder_.DeoptCheck(check, frameState, DeoptType::NOTCALLTGT);
1114 
1115     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1116 }
1117 
LowerJSInlineTargetTypeCheck(GateRef gate)1118 void TypeMCRLowering::LowerJSInlineTargetTypeCheck(GateRef gate)
1119 {
1120     Environment env(gate, circuit_, &builder_);
1121     GateRef frameState = GetFrameState(gate);
1122     auto func = acc_.GetValueIn(gate, 0);
1123     GateRef isObj = builder_.TaggedIsHeapObject(func);
1124     GateRef isJsFunc = builder_.IsJSFunction(func);
1125     GateRef checkFunc = builder_.BoolAnd(isObj, isJsFunc);
1126     GateRef GetMethodId = builder_.GetMethodId(func);
1127     GateRef check = builder_.BoolAnd(checkFunc, builder_.Equal(GetMethodId, acc_.GetValueIn(gate, 1)));
1128     builder_.DeoptCheck(check, frameState, DeoptType::INLINEFAIL);
1129     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1130 }
1131 
LowerTypedNewAllocateThis(GateRef gate,GateRef glue)1132 void TypeMCRLowering::LowerTypedNewAllocateThis(GateRef gate, GateRef glue)
1133 {
1134     Environment env(gate, circuit_, &builder_);
1135     ArgumentAccessor argAcc(circuit_);
1136     GateRef frameState = GetFrameState(gate);
1137     GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC);
1138 
1139     GateRef ctor = acc_.GetValueIn(gate, 0);
1140 
1141     DEFVAlUE(thisObj, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1142     Label allocate(&builder_);
1143     Label exit(&builder_);
1144 
1145     GateRef isBase = builder_.IsBase(ctor);
1146     builder_.Branch(isBase, &allocate, &exit);
1147     builder_.Bind(&allocate);
1148     {
1149         // add typecheck to detect protoOrHclass is equal with ihclass,
1150         // if pass typecheck: 1.no need to check whether hclass is valid 2.no need to check return result
1151         GateRef protoOrHclass = builder_.LoadConstOffset(VariableType::JS_ANY(), ctor,
1152             JSFunction::PROTO_OR_DYNCLASS_OFFSET);
1153         GateRef ihclassIndex = acc_.GetValueIn(gate, 1);
1154         GateRef ihclass = GetObjectFromConstPool(jsFunc, ihclassIndex);
1155         GateRef check = builder_.Equal(protoOrHclass, ihclass);
1156         builder_.DeoptCheck(check, frameState, DeoptType::NOTNEWOBJ);
1157 
1158         thisObj = builder_.CallStub(glue, gate, CommonStubCSigns::NewJSObject, { glue, protoOrHclass });
1159         builder_.Jump(&exit);
1160     }
1161     builder_.Bind(&exit);
1162     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *thisObj);
1163 }
1164 
LowerTypedSuperAllocateThis(GateRef gate,GateRef glue)1165 void TypeMCRLowering::LowerTypedSuperAllocateThis(GateRef gate, GateRef glue)
1166 {
1167     Environment env(gate, circuit_, &builder_);
1168     GateRef superCtor = acc_.GetValueIn(gate, 0);
1169     GateRef newTarget = acc_.GetValueIn(gate, 1);
1170 
1171     DEFVAlUE(thisObj, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1172     Label allocate(&builder_);
1173     Label exit(&builder_);
1174 
1175     GateRef isBase = builder_.IsBase(superCtor);
1176     builder_.Branch(isBase, &allocate, &exit);
1177     builder_.Bind(&allocate);
1178     {
1179         GateRef protoOrHclass = builder_.LoadConstOffset(VariableType::JS_ANY(), newTarget,
1180             JSFunction::PROTO_OR_DYNCLASS_OFFSET);
1181         GateRef check = builder_.IsJSHClass(protoOrHclass);
1182         GateRef frameState = GetFrameState(gate);
1183         builder_.DeoptCheck(check, frameState, DeoptType::NOTNEWOBJ);
1184 
1185         thisObj = builder_.CallStub(glue, gate, CommonStubCSigns::NewJSObject, { glue, protoOrHclass });
1186         builder_.Jump(&exit);
1187     }
1188     builder_.Bind(&exit);
1189     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *thisObj);
1190 }
1191 
LowerGetSuperConstructor(GateRef gate)1192 void TypeMCRLowering::LowerGetSuperConstructor(GateRef gate)
1193 {
1194     Environment env(gate, circuit_, &builder_);
1195     GateRef ctor = acc_.GetValueIn(gate, 0);
1196     GateRef hclass = builder_.LoadHClass(ctor);
1197     GateRef superCtor = builder_.LoadConstOffset(VariableType::JS_ANY(), hclass, JSHClass::PROTOTYPE_OFFSET);
1198     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), superCtor);
1199 }
1200 
LoadFromVTable(GateRef receiver,size_t index)1201 GateRef TypeMCRLowering::LoadFromVTable(GateRef receiver, size_t index)
1202 {
1203     GateRef hclass = builder_.LoadConstOffset(
1204         VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
1205     GateRef vtable = builder_.LoadConstOffset(VariableType::JS_ANY(),
1206         hclass, JSHClass::VTABLE_OFFSET);
1207 
1208     GateRef itemOwner = builder_.LoadFromTaggedArray(vtable, VTable::TupleItem::OWNER + index);
1209     GateRef itemOffset = builder_.LoadFromTaggedArray(vtable, VTable::TupleItem::OFFSET + index);
1210     return builder_.Load(VariableType::JS_ANY(), itemOwner, builder_.TaggedGetInt(itemOffset));
1211 }
1212 
GetVarType(PropertyLookupResult plr)1213 VariableType TypeMCRLowering::GetVarType(PropertyLookupResult plr)
1214 {
1215     if (plr.GetRepresentation() == Representation::DOUBLE) {
1216         return kungfu::VariableType::FLOAT64();
1217     } else if (plr.GetRepresentation() == Representation::INT) {
1218         return kungfu::VariableType::INT32();
1219     } else {
1220         return kungfu::VariableType::INT64();
1221     }
1222 }
1223 
LoadSupers(GateRef hclass)1224 GateRef TypeMCRLowering::LoadSupers(GateRef hclass)
1225 {
1226     return builder_.LoadConstOffset(VariableType::JS_ANY(), hclass, JSHClass::SUPERS_OFFSET);
1227 }
1228 
GetLengthFromSupers(GateRef supers)1229 GateRef TypeMCRLowering::GetLengthFromSupers(GateRef supers)
1230 {
1231     return builder_.LoadConstOffset(VariableType::INT32(), supers, TaggedArray::EXTRACT_LENGTH_OFFSET);
1232 }
1233 
GetValueFromSupers(GateRef supers,size_t index)1234 GateRef TypeMCRLowering::GetValueFromSupers(GateRef supers, size_t index)
1235 {
1236     GateRef val = builder_.LoadFromTaggedArray(supers, index);
1237     return builder_.LoadObjectFromWeakRef(val);
1238 }
1239 
CallAccessor(GateRef glue,GateRef gate,GateRef function,GateRef receiver,AccessorMode mode,GateRef value)1240 GateRef TypeMCRLowering::CallAccessor(GateRef glue, GateRef gate, GateRef function, GateRef receiver,
1241     AccessorMode mode, GateRef value)
1242 {
1243     const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(JSCall));
1244     GateRef target = builder_.IntPtr(RTSTUB_ID(JSCall));
1245     GateRef newTarget = builder_.Undefined();
1246     GateRef argc = builder_.Int64(NUM_MANDATORY_JSFUNC_ARGS + (mode == AccessorMode::SETTER ? 1 : 0));  // 1: value
1247     std::vector<GateRef> args { glue, argc, function, newTarget, receiver };
1248     if (mode == AccessorMode::SETTER) {
1249         args.emplace_back(value);
1250     }
1251 
1252     return builder_.Call(cs, glue, target, builder_.GetDepend(), args, gate);
1253 }
1254 
ReplaceHirWithPendingException(GateRef hirGate,GateRef glue,GateRef state,GateRef depend,GateRef value)1255 void TypeMCRLowering::ReplaceHirWithPendingException(GateRef hirGate, GateRef glue, GateRef state, GateRef depend,
1256                                                      GateRef value)
1257 {
1258     auto condition = builder_.HasPendingException(glue);
1259     GateRef ifBranch = builder_.Branch(state, condition);
1260     GateRef ifTrue = builder_.IfTrue(ifBranch);
1261     GateRef ifFalse = builder_.IfFalse(ifBranch);
1262     GateRef eDepend = builder_.DependRelay(ifTrue, depend);
1263     GateRef sDepend = builder_.DependRelay(ifFalse, depend);
1264 
1265     StateDepend success(ifFalse, sDepend);
1266     StateDepend exception(ifTrue, eDepend);
1267     acc_.ReplaceHirWithIfBranch(hirGate, success, exception, value);
1268 }
1269 
LowerLoadGetter(GateRef gate)1270 void TypeMCRLowering::LowerLoadGetter(GateRef gate)
1271 {
1272     Environment env(gate, circuit_, &builder_);
1273     ASSERT(acc_.GetNumValueIn(gate) == 2);  // 2: receiver, plr
1274     GateRef receiver = acc_.GetValueIn(gate, 0);
1275     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1276 
1277     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1278     ASSERT(plr.IsAccessor());
1279     GateRef accessor = LoadFromVTable(receiver, plr.GetOffset());
1280     GateRef getter = builder_.Load(VariableType::JS_ANY(), accessor,
1281                                    builder_.IntPtr(AccessorData::GETTER_OFFSET));
1282     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), getter);
1283 }
1284 
LowerLoadSetter(GateRef gate)1285 void TypeMCRLowering::LowerLoadSetter(GateRef gate)
1286 {
1287     Environment env(gate, circuit_, &builder_);
1288     ASSERT(acc_.GetNumValueIn(gate) == 2);  // 2: receiver, plr
1289     GateRef receiver = acc_.GetValueIn(gate, 0);
1290     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1291 
1292     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1293     ASSERT(plr.IsAccessor());
1294     GateRef accessor = LoadFromVTable(receiver, plr.GetOffset());
1295     GateRef setter = builder_.Load(VariableType::JS_ANY(),
1296         accessor, builder_.IntPtr(AccessorData::SETTER_OFFSET));
1297     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), setter);
1298 }
1299 
1300 // subtyping check and hclss check
LowerInlineAccessorCheck(GateRef gate)1301 void TypeMCRLowering::LowerInlineAccessorCheck(GateRef gate)
1302 {
1303     Environment env(gate, circuit_, &builder_);
1304     GateRef receiver = acc_.GetValueIn(gate, 0);
1305     GateRef frameState = acc_.GetFrameState(gate);
1306     builder_.HeapObjectCheck(receiver, frameState);
1307 
1308     GateRef aotHCIndex = acc_.GetValueIn(gate, 1);
1309     ArgumentAccessor argAcc(circuit_);
1310     GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC);
1311     JSTaggedValue aotHC = tsManager_->GetValueFromCache(acc_.TryGetValue(aotHCIndex));
1312     ASSERT(aotHC.IsJSHClass());
1313 
1314     int32_t level = JSHClass::Cast(aotHC.GetTaggedObject())->GetLevel();
1315     ASSERT(level >= 0);
1316 
1317     GateRef receiverHClass = builder_.LoadConstOffset(
1318         VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
1319     GateRef supers = LoadSupers(receiverHClass);
1320 
1321     auto hclassIndex = acc_.GetConstantValue(aotHCIndex);
1322     GateRef aotHCGate = LoadFromConstPool(jsFunc, hclassIndex);
1323     GateRef hclassCompare = builder_.Equal(aotHCGate, receiverHClass);
1324     if (LIKELY(static_cast<uint32_t>(level) < SubtypingOperator::DEFAULT_SUPERS_CAPACITY)) {
1325         GateRef subtypingCompare = builder_.Equal(aotHCGate, GetValueFromSupers(supers, level));
1326         GateRef compare = builder_.BoolAnd(hclassCompare, subtypingCompare);
1327         builder_.DeoptCheck(compare, frameState, DeoptType::INCONSISTENTHCLASS);
1328         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1329         return;
1330     }
1331 
1332     Label levelValid(&builder_);
1333     Label exit(&builder_);
1334     DEFVAlUE(check, (&builder_), VariableType::BOOL(), builder_.False());
1335     GateRef levelGate = builder_.Int32(level);
1336     GateRef length = GetLengthFromSupers(supers);
1337 
1338     builder_.Branch(builder_.Int32LessThan(levelGate, length), &levelValid, &exit);
1339     builder_.Bind(&levelValid);
1340     {
1341         check = builder_.Equal(aotHCGate, GetValueFromSupers(supers, level));
1342         builder_.Jump(&exit);
1343     }
1344     builder_.Bind(&exit);
1345 
1346     GateRef compare = builder_.BoolAnd(hclassCompare, *check);
1347     builder_.DeoptCheck(compare, frameState, DeoptType::INCONSISTENTHCLASS);
1348     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1349 }
1350 }  // namespace panda::ecmascript::kungfu
1351