• 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/ts_type_lowering.h"
17 #include "ecmascript/compiler/builtins_lowering.h"
18 #include "ecmascript/dfx/vmstat/opt_code_profiler.h"
19 #include "ecmascript/stackmap/llvm_stackmap_parser.h"
20 #include "ecmascript/ts_types/ts_type.h"
21 
22 namespace panda::ecmascript::kungfu {
RunTSTypeLowering()23 void TSTypeLowering::RunTSTypeLowering()
24 {
25     std::vector<GateRef> gateList;
26     circuit_->GetAllGates(gateList);
27     for (const auto &gate : gateList) {
28         auto op = acc_.GetOpCode(gate);
29         if (op == OpCode::JS_BYTECODE) {
30             Lower(gate);
31         }
32     }
33 
34     VerifyGuard();
35 
36     if (IsLogEnabled()) {
37         LOG_COMPILER(INFO) << "";
38         LOG_COMPILER(INFO) << "\033[34m"
39                            << "===================="
40                            << " After ts type lowering "
41                            << "[" << GetMethodName() << "]"
42                            << "===================="
43                            << "\033[0m";
44         circuit_->PrintAllGatesWithBytecode();
45         LOG_COMPILER(INFO) << "\033[34m" << "========================= End ==========================" << "\033[0m";
46     }
47 }
48 
VerifyGuard() const49 void TSTypeLowering::VerifyGuard() const
50 {
51     std::vector<GateRef> gateList;
52     circuit_->GetAllGates(gateList);
53     for (const auto &gate : gateList) {
54         auto op = acc_.GetOpCode(gate);
55         if (op == OpCode::JS_BYTECODE) {
56             auto depend = acc_.GetDep(gate);
57             if (acc_.GetOpCode(depend) == OpCode::STATE_SPLIT) {
58                 auto opcode = acc_.GetByteCodeOpcode(gate);
59                 std::string bytecodeStr = GetEcmaOpcodeStr(opcode);
60                 LOG_COMPILER(ERROR) << "[ts_type_lowering][Error] the depend of ["
61                                     << "id: " << acc_.GetId(gate) << ", JS_BYTECODE: " << bytecodeStr
62                                     << "] should not be STATE_SPLIT after ts type lowring";
63             }
64         }
65     }
66 }
67 
IsTrustedType(GateRef gate) const68 bool TSTypeLowering::IsTrustedType(GateRef gate) const
69 {
70     if (acc_.IsConstant(gate)) {
71         return true;
72     }
73     auto op = acc_.GetOpCode(gate);
74     if (acc_.IsTypedOperator(gate)) {
75         if (op == OpCode::TYPED_BINARY_OP) {
76             return !acc_.GetGateType(gate).IsIntType();
77         } else {
78             return true;
79         }
80     }
81     if (op == OpCode::JS_BYTECODE) {
82         EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
83         switch (ecmaOpcode) {
84             case EcmaOpcode::ADD2_IMM8_V8:
85             case EcmaOpcode::SUB2_IMM8_V8:
86             case EcmaOpcode::MUL2_IMM8_V8:
87                 return !acc_.GetGateType(gate).IsIntType();
88             case EcmaOpcode::INC_IMM8:
89             case EcmaOpcode::DEC_IMM8:
90             case EcmaOpcode::LESS_IMM8_V8:
91             case EcmaOpcode::LESSEQ_IMM8_V8:
92                 return true;
93             default:
94                 break;
95         }
96     }
97     return false;
98 }
99 
Lower(GateRef gate)100 void TSTypeLowering::Lower(GateRef gate)
101 {
102     auto argAcc = ArgumentAccessor(circuit_);
103     GateRef jsFunc = argAcc.GetCommonArgGate(CommonArgIdx::FUNC);
104     GateRef newTarget = argAcc.GetCommonArgGate(CommonArgIdx::NEW_TARGET);
105 
106     EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
107     // initialize label manager
108     Environment env(gate, circuit_, &builder_);
109     switch (ecmaOpcode) {
110         case EcmaOpcode::ADD2_IMM8_V8:
111             LowerTypedAdd(gate);
112             break;
113         case EcmaOpcode::SUB2_IMM8_V8:
114             LowerTypedSub(gate);
115             break;
116         case EcmaOpcode::MUL2_IMM8_V8:
117             LowerTypedMul(gate);
118             break;
119         case EcmaOpcode::DIV2_IMM8_V8:
120             LowerTypedDiv(gate);
121             break;
122         case EcmaOpcode::MOD2_IMM8_V8:
123             LowerTypedMod(gate);
124             break;
125         case EcmaOpcode::LESS_IMM8_V8:
126             LowerTypedLess(gate);
127             break;
128         case EcmaOpcode::LESSEQ_IMM8_V8:
129             LowerTypedLessEq(gate);
130             break;
131         case EcmaOpcode::GREATER_IMM8_V8:
132             LowerTypedGreater(gate);
133             break;
134         case EcmaOpcode::GREATEREQ_IMM8_V8:
135             LowerTypedGreaterEq(gate);
136             break;
137         case EcmaOpcode::EQ_IMM8_V8:
138             LowerTypedEq(gate);
139             break;
140         case EcmaOpcode::NOTEQ_IMM8_V8:
141             LowerTypedNotEq(gate);
142             break;
143         case EcmaOpcode::SHL2_IMM8_V8:
144             LowerTypedShl(gate);
145             break;
146         case EcmaOpcode::SHR2_IMM8_V8:
147             LowerTypedShr(gate);
148             break;
149         case EcmaOpcode::ASHR2_IMM8_V8:
150             LowerTypedAshr(gate);
151             break;
152         case EcmaOpcode::AND2_IMM8_V8:
153             LowerTypedAnd(gate);
154             break;
155         case EcmaOpcode::OR2_IMM8_V8:
156             LowerTypedOr(gate);
157             break;
158         case EcmaOpcode::XOR2_IMM8_V8:
159             LowerTypedXor(gate);
160             break;
161         case EcmaOpcode::EXP_IMM8_V8:
162             // lower JS_EXP
163             break;
164         case EcmaOpcode::TONUMERIC_IMM8:
165             LowerTypeToNumeric(gate);
166             break;
167         case EcmaOpcode::NEG_IMM8:
168             LowerTypedNeg(gate);
169             break;
170         case EcmaOpcode::NOT_IMM8:
171             LowerTypedNot(gate);
172             break;
173         case EcmaOpcode::INC_IMM8:
174             LowerTypedInc(gate);
175             break;
176         case EcmaOpcode::DEC_IMM8:
177             LowerTypedDec(gate);
178             break;
179         case EcmaOpcode::ISTRUE:
180             LowerTypedIsTrueOrFalse(gate, true);
181             break;
182         case EcmaOpcode::ISFALSE:
183             LowerTypedIsTrueOrFalse(gate, false);
184             break;
185         case EcmaOpcode::JEQZ_IMM8:
186         case EcmaOpcode::JEQZ_IMM16:
187         case EcmaOpcode::JEQZ_IMM32:
188             LowerConditionJump(gate);
189             break;
190         case EcmaOpcode::LDOBJBYNAME_IMM8_ID16:
191         case EcmaOpcode::LDOBJBYNAME_IMM16_ID16:
192         case EcmaOpcode::LDTHISBYNAME_IMM8_ID16:
193         case EcmaOpcode::LDTHISBYNAME_IMM16_ID16:
194             LowerTypedLdObjByName(gate);
195             break;
196         case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
197         case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
198             LowerTypedStObjByName(gate, false);
199             break;
200         case EcmaOpcode::STTHISBYNAME_IMM8_ID16:
201         case EcmaOpcode::STTHISBYNAME_IMM16_ID16:
202             LowerTypedStObjByName(gate, true);
203             break;
204         case EcmaOpcode::LDOBJBYINDEX_IMM8_IMM16:
205         case EcmaOpcode::LDOBJBYINDEX_IMM16_IMM16:
206         case EcmaOpcode::WIDE_LDOBJBYINDEX_PREF_IMM32:
207             LowerTypedLdObjByIndex(gate);
208             break;
209         case EcmaOpcode::STOBJBYINDEX_IMM8_V8_IMM16:
210         case EcmaOpcode::STOBJBYINDEX_IMM16_V8_IMM16:
211         case EcmaOpcode::WIDE_STOBJBYINDEX_PREF_V8_IMM32:
212             LowerTypedStObjByIndex(gate);
213             break;
214         case EcmaOpcode::LDOBJBYVALUE_IMM8_V8:
215         case EcmaOpcode::LDOBJBYVALUE_IMM16_V8:
216             LowerTypedLdObjByValue(gate, false);
217             break;
218         case EcmaOpcode::LDTHISBYVALUE_IMM8:
219         case EcmaOpcode::LDTHISBYVALUE_IMM16:
220             LowerTypedLdObjByValue(gate, true);
221             break;
222         case EcmaOpcode::NEWOBJRANGE_IMM8_IMM8_V8:
223         case EcmaOpcode::NEWOBJRANGE_IMM16_IMM8_V8:
224         case EcmaOpcode::WIDE_NEWOBJRANGE_PREF_IMM16_V8:
225             LowerTypedNewObjRange(gate);
226             break;
227         case EcmaOpcode::SUPERCALLTHISRANGE_IMM8_IMM8_V8:
228         case EcmaOpcode::WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8:
229             LowerTypedSuperCall(gate, jsFunc, newTarget);
230             break;
231         case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
232             LowerCallThis1Imm8V8V8(gate);
233             break;
234         default:
235             break;
236     }
237 }
238 
DeleteGates(GateRef hir,std::vector<GateRef> & unusedGate)239 void TSTypeLowering::DeleteGates(GateRef hir, std::vector<GateRef> &unusedGate)
240 {
241     for (auto &gate : unusedGate) {
242         auto uses = acc_.Uses(gate);
243         for (auto useIt = uses.begin(); useIt != uses.end(); ++useIt) {
244             if (acc_.GetOpCode(gate) == OpCode::IF_EXCEPTION && acc_.GetOpCode(*useIt) == OpCode::MERGE) {
245                 // handle exception merge has only one input, using state entry and depend entry to replace merge and
246                 // dependselector.
247                 if (acc_.GetNumIns(*useIt) == 1) {
248                     GateRef stateEntry = circuit_->GetStateRoot();
249                     GateRef dependEntry = circuit_->GetDependRoot();
250                     auto mergeUses = acc_.Uses(*useIt);
251                     for (auto mergeUseIt = mergeUses.begin(); mergeUseIt != uses.end(); ++mergeUseIt) {
252                         if (acc_.GetOpCode(*mergeUseIt) == OpCode::DEPEND_SELECTOR) {
253                             auto dependSelectorUses = acc_.Uses(*mergeUseIt);
254                             acc_.ReplaceIn(*dependSelectorUses.begin(), 0, dependEntry);
255                             acc_.DeleteGate(*mergeUseIt);
256                             break;
257                         }
258                     }
259                     acc_.ReplaceIn(*useIt, 0, stateEntry);
260                 } else {
261                     acc_.DecreaseIn(useIt);
262                 }
263             }
264         }
265         acc_.DeleteGate(gate);
266     }
267     acc_.DeleteGate(hir);
268 }
269 
ReplaceHIRGate(GateRef hir,GateRef outir,GateRef state,GateRef depend,std::vector<GateRef> & unusedGate)270 void TSTypeLowering::ReplaceHIRGate(GateRef hir, GateRef outir, GateRef state, GateRef depend,
271                                     std::vector<GateRef> &unusedGate)
272 {
273     if (outir != Circuit::NullGate()) {
274         auto type = acc_.GetGateType(hir);
275         if (!type.IsAnyType()) {
276             acc_.SetGateType(outir, type);
277         }
278     }
279 
280     std::map<GateRef, size_t> deleteMap;
281     auto uses = acc_.Uses(hir);
282     bool expFound = false;
283     for (auto tmpUseIt = uses.begin(); tmpUseIt != uses.end(); tmpUseIt++) {
284         if (acc_.GetOpCode(*tmpUseIt) == OpCode::IF_EXCEPTION) {
285             auto expUses = acc_.Uses(*tmpUseIt);
286             for (auto expUseIt = expUses.begin(); expUseIt != expUses.end(); ++expUseIt) {
287                 if (acc_.GetOpCode(*expUseIt) == OpCode::MERGE && acc_.GetNumIns(*expUseIt) == 1) {
288                     expFound = true;
289                     break;
290                 }
291             }
292         }
293     }
294     if (expFound) {
295         GateRef ifBranch = builder_.Branch(state, builder_.Boolean(false));
296         for (auto it = uses.begin(); it != uses.end();) {
297             if (acc_.GetOpCode(*it) == OpCode::IF_SUCCESS) {
298                 acc_.SetMetaData(*it, circuit_->IfFalse());
299                 it = acc_.ReplaceIn(it, ifBranch);
300             } else {
301                 if (acc_.GetOpCode(*it) == OpCode::IF_EXCEPTION) {
302                     acc_.SetMetaData(*it, circuit_->IfTrue());
303                     it = acc_.ReplaceIn(it, ifBranch);
304                 } else {
305                     it++;
306                 }
307             }
308         }
309     }
310 
311     for (auto useIt = uses.begin(); useIt != uses.end();) {
312         const OpCode op = acc_.GetOpCode(*useIt);
313         if (op == OpCode::IF_SUCCESS) {
314             // success path use fastpath state
315             unusedGate.emplace_back(*useIt);
316             auto successUse = acc_.Uses(*useIt).begin();
317             acc_.ReplaceIn(successUse, state);
318             ++useIt;
319         } else if (op == OpCode::IF_EXCEPTION) {
320             // exception path needs to delete all related nodes
321             unusedGate.emplace_back(*useIt);
322             auto exceptionUse = acc_.Uses(*useIt);
323             auto exceptionUseIt = exceptionUse.begin();
324             if (acc_.GetOpCode(*exceptionUseIt) == OpCode::MERGE) {
325                 auto mergeUse = acc_.Uses(*exceptionUseIt);
326                 // handle exception->merge->value_selector/depend_selector
327                 for (auto mergeUseIt = mergeUse.begin(); mergeUseIt != mergeUse.end();) {
328                     if (acc_.GetOpCode(*mergeUseIt) == OpCode::VALUE_SELECTOR ||
329                         acc_.GetOpCode(*mergeUseIt) == OpCode::DEPEND_SELECTOR) {
330                         deleteMap[*mergeUseIt] = exceptionUseIt.GetIndex() + 1;
331                     }
332                     ++mergeUseIt;
333                 }
334             } else if (acc_.GetOpCode(*exceptionUseIt) == OpCode::RETURN) {
335                 unusedGate.emplace_back(*exceptionUseIt);
336             }
337             ++useIt;
338         } else if (op == OpCode::DEPEND_SELECTOR) {
339             if (acc_.GetOpCode(acc_.GetIn(acc_.GetIn(*useIt, 0), useIt.GetIndex() - 1)) == OpCode::IF_EXCEPTION) {
340                 ++useIt;
341             } else {
342                 useIt = acc_.ReplaceIn(useIt, depend);
343             }
344         } else {
345             if (acc_.IsValueIn(useIt)) {
346                 useIt = acc_.ReplaceIn(useIt, outir);
347             } else if (acc_.IsDependIn(useIt)) {
348                 useIt = acc_.ReplaceIn(useIt, depend);
349             } else {
350                 useIt = acc_.ReplaceIn(useIt, state);
351             }
352         }
353     }
354 
355     for (auto it = deleteMap.begin(); it != deleteMap.end(); it++) {
356         acc_.DecreaseIn(it->first, it->second);
357     }
358 }
359 
LowerTypedAdd(GateRef gate)360 void TSTypeLowering::LowerTypedAdd(GateRef gate)
361 {
362     GateRef left = acc_.GetValueIn(gate, 0);
363     GateRef right = acc_.GetValueIn(gate, 1);
364     GateType leftType = acc_.GetGateType(left);
365     GateType rightType = acc_.GetGateType(right);
366     if (leftType.IsNumberType() && rightType.IsNumberType()) {
367         SpeculateNumbers<TypedBinOp::TYPED_ADD>(gate);
368     } else {
369         acc_.DeleteStateSplitAndFrameState(gate);
370     }
371 }
372 
LowerTypedSub(GateRef gate)373 void TSTypeLowering::LowerTypedSub(GateRef gate)
374 {
375     GateRef left = acc_.GetValueIn(gate, 0);
376     GateRef right = acc_.GetValueIn(gate, 1);
377     GateType leftType = acc_.GetGateType(left);
378     GateType rightType = acc_.GetGateType(right);
379     if (leftType.IsNumberType() && rightType.IsNumberType()) {
380         SpeculateNumbers<TypedBinOp::TYPED_SUB>(gate);
381     } else {
382         acc_.DeleteStateSplitAndFrameState(gate);
383     }
384 }
385 
LowerTypedMul(GateRef gate)386 void TSTypeLowering::LowerTypedMul(GateRef gate)
387 {
388     GateRef left = acc_.GetValueIn(gate, 0);
389     GateRef right = acc_.GetValueIn(gate, 1);
390     GateType leftType = acc_.GetGateType(left);
391     GateType rightType = acc_.GetGateType(right);
392     if (leftType.IsNumberType() && rightType.IsNumberType()) {
393         SpeculateNumbers<TypedBinOp::TYPED_MUL>(gate);
394     } else {
395         acc_.DeleteStateSplitAndFrameState(gate);
396     }
397 }
398 
LowerTypedMod(GateRef gate)399 void TSTypeLowering::LowerTypedMod(GateRef gate)
400 {
401     GateRef left = acc_.GetValueIn(gate, 0);
402     GateRef right = acc_.GetValueIn(gate, 1);
403     GateType leftType = acc_.GetGateType(left);
404     GateType rightType = acc_.GetGateType(right);
405     if (leftType.IsNumberType() && rightType.IsNumberType()) {
406         SpeculateNumbers<TypedBinOp::TYPED_MOD>(gate);
407     } else {
408         acc_.DeleteStateSplitAndFrameState(gate);
409     }
410 }
411 
LowerTypedLess(GateRef gate)412 void TSTypeLowering::LowerTypedLess(GateRef gate)
413 {
414     GateRef left = acc_.GetValueIn(gate, 0);
415     GateRef right = acc_.GetValueIn(gate, 1);
416     GateType leftType = acc_.GetGateType(left);
417     GateType rightType = acc_.GetGateType(right);
418     if (leftType.IsNumberType() && rightType.IsNumberType()) {
419         SpeculateNumbers<TypedBinOp::TYPED_LESS>(gate);
420     } else {
421         acc_.DeleteStateSplitAndFrameState(gate);
422     }
423 }
424 
LowerTypedLessEq(GateRef gate)425 void TSTypeLowering::LowerTypedLessEq(GateRef gate)
426 {
427     GateRef left = acc_.GetValueIn(gate, 0);
428     GateRef right = acc_.GetValueIn(gate, 1);
429     GateType leftType = acc_.GetGateType(left);
430     GateType rightType = acc_.GetGateType(right);
431     if (leftType.IsNumberType() && rightType.IsNumberType()) {
432         SpeculateNumbers<TypedBinOp::TYPED_LESSEQ>(gate);
433     } else {
434         acc_.DeleteStateSplitAndFrameState(gate);
435     }
436 }
437 
LowerTypedGreater(GateRef gate)438 void TSTypeLowering::LowerTypedGreater(GateRef gate)
439 {
440     GateRef left = acc_.GetValueIn(gate, 0);
441     GateRef right = acc_.GetValueIn(gate, 1);
442     GateType leftType = acc_.GetGateType(left);
443     GateType rightType = acc_.GetGateType(right);
444     if (leftType.IsNumberType() && rightType.IsNumberType()) {
445         SpeculateNumbers<TypedBinOp::TYPED_GREATER>(gate);
446     } else {
447         acc_.DeleteStateSplitAndFrameState(gate);
448     }
449 }
450 
LowerTypedGreaterEq(GateRef gate)451 void TSTypeLowering::LowerTypedGreaterEq(GateRef gate)
452 {
453     GateRef left = acc_.GetValueIn(gate, 0);
454     GateRef right = acc_.GetValueIn(gate, 1);
455     GateType leftType = acc_.GetGateType(left);
456     GateType rightType = acc_.GetGateType(right);
457     if (leftType.IsNumberType() && rightType.IsNumberType()) {
458         SpeculateNumbers<TypedBinOp::TYPED_GREATEREQ>(gate);
459     } else {
460         acc_.DeleteStateSplitAndFrameState(gate);
461     }
462 }
463 
LowerTypedDiv(GateRef gate)464 void TSTypeLowering::LowerTypedDiv(GateRef gate)
465 {
466     GateRef left = acc_.GetValueIn(gate, 0);
467     GateRef right = acc_.GetValueIn(gate, 1);
468     GateType leftType = acc_.GetGateType(left);
469     GateType rightType = acc_.GetGateType(right);
470     if (leftType.IsNumberType() && rightType.IsNumberType()) {
471         SpeculateNumbers<TypedBinOp::TYPED_DIV>(gate);
472     } else {
473         acc_.DeleteStateSplitAndFrameState(gate);
474     }
475 }
476 
LowerTypedEq(GateRef gate)477 void TSTypeLowering::LowerTypedEq(GateRef gate)
478 {
479     GateRef left = acc_.GetValueIn(gate, 0);
480     GateRef right = acc_.GetValueIn(gate, 1);
481     GateType leftType = acc_.GetGateType(left);
482     GateType rightType = acc_.GetGateType(right);
483     if (leftType.IsNumberType() && rightType.IsNumberType()) {
484         SpeculateNumbers<TypedBinOp::TYPED_EQ>(gate);
485     } else {
486         acc_.DeleteStateSplitAndFrameState(gate);
487     }
488 }
489 
LowerTypedNotEq(GateRef gate)490 void TSTypeLowering::LowerTypedNotEq(GateRef gate)
491 {
492     GateRef left = acc_.GetValueIn(gate, 0);
493     GateRef right = acc_.GetValueIn(gate, 1);
494     GateType leftType = acc_.GetGateType(left);
495     GateType rightType = acc_.GetGateType(right);
496     if (leftType.IsNumberType() && rightType.IsNumberType()) {
497         SpeculateNumbers<TypedBinOp::TYPED_NOTEQ>(gate);
498     } else {
499         acc_.DeleteStateSplitAndFrameState(gate);
500     }
501 }
502 
LowerTypedShl(GateRef gate)503 void TSTypeLowering::LowerTypedShl(GateRef gate)
504 {
505     GateRef left = acc_.GetValueIn(gate, 0);
506     GateRef right = acc_.GetValueIn(gate, 1);
507     GateType leftType = acc_.GetGateType(left);
508     GateType rightType = acc_.GetGateType(right);
509     if (leftType.IsNumberType() && rightType.IsNumberType()) {
510         SpeculateNumbers<TypedBinOp::TYPED_SHL>(gate);
511     } else {
512         acc_.DeleteStateSplitAndFrameState(gate);
513     }
514 }
515 
LowerTypedShr(GateRef gate)516 void TSTypeLowering::LowerTypedShr(GateRef gate)
517 {
518     GateRef left = acc_.GetValueIn(gate, 0);
519     GateRef right = acc_.GetValueIn(gate, 1);
520     GateType leftType = acc_.GetGateType(left);
521     GateType rightType = acc_.GetGateType(right);
522     if (leftType.IsNumberType() && rightType.IsNumberType()) {
523         SpeculateNumbers<TypedBinOp::TYPED_SHR>(gate);
524     } else {
525         acc_.DeleteStateSplitAndFrameState(gate);
526     }
527 }
528 
LowerTypedAshr(GateRef gate)529 void TSTypeLowering::LowerTypedAshr(GateRef gate)
530 {
531     GateRef left = acc_.GetValueIn(gate, 0);
532     GateRef right = acc_.GetValueIn(gate, 1);
533     GateType leftType = acc_.GetGateType(left);
534     GateType rightType = acc_.GetGateType(right);
535     if (leftType.IsNumberType() && rightType.IsNumberType()) {
536         SpeculateNumbers<TypedBinOp::TYPED_ASHR>(gate);
537     } else {
538         acc_.DeleteStateSplitAndFrameState(gate);
539     }
540 }
541 
LowerTypedAnd(GateRef gate)542 void TSTypeLowering::LowerTypedAnd(GateRef gate)
543 {
544     GateRef left = acc_.GetValueIn(gate, 0);
545     GateRef right = acc_.GetValueIn(gate, 1);
546     GateType leftType = acc_.GetGateType(left);
547     GateType rightType = acc_.GetGateType(right);
548     if (leftType.IsNumberType() && rightType.IsNumberType()) {
549         SpeculateNumbers<TypedBinOp::TYPED_AND>(gate);
550     } else {
551         acc_.DeleteStateSplitAndFrameState(gate);
552     }
553 }
554 
LowerTypedOr(GateRef gate)555 void TSTypeLowering::LowerTypedOr(GateRef gate)
556 {
557     GateRef left = acc_.GetValueIn(gate, 0);
558     GateRef right = acc_.GetValueIn(gate, 1);
559     GateType leftType = acc_.GetGateType(left);
560     GateType rightType = acc_.GetGateType(right);
561     if (leftType.IsNumberType() && rightType.IsNumberType()) {
562         SpeculateNumbers<TypedBinOp::TYPED_OR>(gate);
563     } else {
564         acc_.DeleteStateSplitAndFrameState(gate);
565     }
566 }
567 
LowerTypedXor(GateRef gate)568 void TSTypeLowering::LowerTypedXor(GateRef gate)
569 {
570     GateRef left = acc_.GetValueIn(gate, 0);
571     GateRef right = acc_.GetValueIn(gate, 1);
572     GateType leftType = acc_.GetGateType(left);
573     GateType rightType = acc_.GetGateType(right);
574     if (leftType.IsNumberType() && rightType.IsNumberType()) {
575         SpeculateNumbers<TypedBinOp::TYPED_XOR>(gate);
576     } else {
577         acc_.DeleteStateSplitAndFrameState(gate);
578     }
579 }
580 
LowerTypedInc(GateRef gate)581 void TSTypeLowering::LowerTypedInc(GateRef gate)
582 {
583     GateRef value = acc_.GetValueIn(gate, 0);
584     GateType valueType = acc_.GetGateType(value);
585     if (valueType.IsNumberType()) {
586         SpeculateNumber<TypedUnOp::TYPED_INC>(gate);
587     } else {
588         acc_.DeleteStateSplitAndFrameState(gate);
589     }
590 }
591 
LowerTypedDec(GateRef gate)592 void TSTypeLowering::LowerTypedDec(GateRef gate)
593 {
594     GateRef value = acc_.GetValueIn(gate, 0);
595     GateType valueType = acc_.GetGateType(value);
596     if (valueType.IsNumberType()) {
597         SpeculateNumber<TypedUnOp::TYPED_DEC>(gate);
598     } else {
599         acc_.DeleteStateSplitAndFrameState(gate);
600     }
601 }
602 
603 template<TypedBinOp Op>
SpeculateNumbers(GateRef gate)604 void TSTypeLowering::SpeculateNumbers(GateRef gate)
605 {
606     AddProfiling(gate);
607     GateRef left = acc_.GetValueIn(gate, 0);
608     GateRef right = acc_.GetValueIn(gate, 1);
609     GateType leftType = acc_.GetGateType(left);
610     GateType rightType = acc_.GetGateType(right);
611     GateType gateType = acc_.GetGateType(gate);
612     builder_.PrimitiveTypeCheck(leftType, left);
613     builder_.PrimitiveTypeCheck(rightType, right);
614 
615     ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
616     GateRef result = builder_.TypedBinaryOp<Op>(left, right, leftType, rightType, gateType);
617 
618     std::vector<GateRef> removedGate;
619     ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
620     DeleteGates(gate, removedGate);
621 }
622 
NeedInt32OverflowCheck(TypedUnOp op) const623 bool TSTypeLowering::NeedInt32OverflowCheck(TypedUnOp op) const
624 {
625     if (op == TypedUnOp::TYPED_INC || op == TypedUnOp::TYPED_DEC ||
626         op == TypedUnOp::TYPED_NEG) {
627         return true;
628     }
629     return false;
630 }
631 
632 template<TypedUnOp Op>
SpeculateNumber(GateRef gate)633 void TSTypeLowering::SpeculateNumber(GateRef gate)
634 {
635     GateRef value = acc_.GetValueIn(gate, 0);
636     GateType valueType = acc_.GetGateType(value);
637     GateType gateType = acc_.GetGateType(gate);
638 
639     builder_.PrimitiveTypeCheck(valueType, value);
640     if (valueType.IsIntType() && NeedInt32OverflowCheck(Op)) {
641         builder_.Int32OverflowCheck<Op>(value);
642     }
643 
644     ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
645     GateRef result = builder_.TypedUnaryOp<Op>(value, valueType, gateType);
646 
647     std::vector<GateRef> removedGate;
648     ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
649     DeleteGates(gate, removedGate);
650 }
651 
LowerTypeToNumeric(GateRef gate)652 void TSTypeLowering::LowerTypeToNumeric(GateRef gate)
653 {
654     GateRef src = acc_.GetValueIn(gate, 0);
655     GateType srcType = acc_.GetGateType(src);
656     if (srcType.IsDigitablePrimitiveType()) {
657         AddProfiling(gate);
658         LowerPrimitiveTypeToNumber(gate);
659     } else {
660         acc_.DeleteStateSplitAndFrameState(gate);
661     }
662 }
663 
LowerPrimitiveTypeToNumber(GateRef gate)664 void TSTypeLowering::LowerPrimitiveTypeToNumber(GateRef gate)
665 {
666     GateRef src = acc_.GetValueIn(gate, 0);
667     GateType srcType = acc_.GetGateType(src);
668     builder_.PrimitiveTypeCheck(srcType, src);
669 
670     ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
671     GateRef result = builder_.PrimitiveToNumber(src, VariableType(MachineType::I64, srcType));
672 
673     std::vector<GateRef> removedGate;
674     ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
675     DeleteGates(gate, removedGate);
676 }
677 
LowerConditionJump(GateRef gate)678 void TSTypeLowering::LowerConditionJump(GateRef gate)
679 {
680     GateRef condition = acc_.GetValueIn(gate, 0);
681     GateType conditionType = acc_.GetGateType(condition);
682     if (conditionType.IsBooleanType() && IsTrustedType(condition)) {
683         AddProfiling(gate);
684         SpeculateConditionJump(gate);
685     }
686 }
687 
SpeculateConditionJump(GateRef gate)688 void TSTypeLowering::SpeculateConditionJump(GateRef gate)
689 {
690     GateRef value = acc_.GetValueIn(gate, 0);
691     GateRef condition = builder_.IsSpecial(value, JSTaggedValue::VALUE_FALSE);
692     GateRef ifBranch = builder_.Branch(acc_.GetState(gate), condition);
693     acc_.ReplaceGate(gate, ifBranch, builder_.GetDepend(), Circuit::NullGate());
694 }
695 
LowerTypedNeg(GateRef gate)696 void TSTypeLowering::LowerTypedNeg(GateRef gate)
697 {
698     GateRef value = acc_.GetValueIn(gate, 0);
699     GateType valueType = acc_.GetGateType(value);
700     if (valueType.IsNumberType()) {
701         SpeculateNumber<TypedUnOp::TYPED_NEG>(gate);
702     } else {
703         acc_.DeleteStateSplitAndFrameState(gate);
704     }
705 }
706 
LowerTypedNot(GateRef gate)707 void TSTypeLowering::LowerTypedNot(GateRef gate)
708 {
709     GateRef value = acc_.GetValueIn(gate, 0);
710     GateType valueType = acc_.GetGateType(value);
711     if (valueType.IsNumberType()) {
712         SpeculateNumber<TypedUnOp::TYPED_NOT>(gate);
713     } else {
714         acc_.DeleteStateSplitAndFrameState(gate);
715     }
716 }
717 
LowerTypedLdArrayLength(GateRef gate)718 void TSTypeLowering::LowerTypedLdArrayLength(GateRef gate)
719 {
720     AddProfiling(gate);
721     GateRef array = acc_.GetValueIn(gate, 2);
722     builder_.ArrayCheck(array);
723 
724     ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
725     GateRef loadLength = builder_.LoadArrayLength(array);
726 
727     std::vector<GateRef> removedGate;
728     ReplaceHIRGate(gate, loadLength, builder_.GetState(), builder_.GetDepend(), removedGate);
729     DeleteGates(gate, removedGate);
730 }
731 
LowerTypedLdObjByName(GateRef gate)732 void TSTypeLowering::LowerTypedLdObjByName(GateRef gate)
733 {
734     DISALLOW_GARBAGE_COLLECTION;
735     uint16_t propIndex = acc_.GetConstDataId(acc_.GetValueIn(gate, 1)).GetId();
736     auto thread = tsManager_->GetEcmaVM()->GetJSThread();
737     JSHandle<ConstantPool> constantPool(tsManager_->GetConstantPool());
738     auto prop = ConstantPool::GetStringFromCache(thread, constantPool.GetTaggedValue(), propIndex);
739 
740     // 3: number of value inputs
741     ASSERT(acc_.GetNumValueIn(gate) == 3);
742     GateRef receiver = acc_.GetValueIn(gate, 2); // 2: acc or this object
743     GateType receiverType = acc_.GetGateType(receiver);
744     if (tsManager_->IsArrayTypeKind(receiverType)) {
745         EcmaString *propString = EcmaString::Cast(prop.GetTaggedObject());
746         EcmaString *lengthString = EcmaString::Cast(thread->GlobalConstants()->GetLengthString().GetTaggedObject());
747         if (propString == lengthString) {
748             LowerTypedLdArrayLength(gate);
749             return;
750         }
751     }
752 
753     int hclassIndex = tsManager_->GetHClassIndexByInstanceGateType(receiverType);
754     if (hclassIndex == -1) { // slowpath
755         acc_.DeleteStateSplitAndFrameState(gate);
756         return;
757     }
758     JSTaggedValue hclass = tsManager_->GetHClassFromCache(hclassIndex);
759 
760     auto propertyOffset = tsManager_->GetPropertyOffset(hclass, prop);
761     if (propertyOffset == -1) { // slowpath
762         acc_.DeleteStateSplitAndFrameState(gate);
763         return;
764     }
765 
766     AddProfiling(gate);
767 
768     GateRef hclassIndexGate = builder_.IntPtr(hclassIndex);
769     GateRef propertyOffsetGate = builder_.IntPtr(propertyOffset);
770     builder_.ObjectTypeCheck(receiverType, receiver, hclassIndexGate);
771 
772     ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
773     GateRef result = builder_.LoadProperty(receiver, propertyOffsetGate);
774 
775     std::vector<GateRef> removedGate;
776     ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
777     DeleteGates(gate, removedGate);
778 }
779 
LowerTypedStObjByName(GateRef gate,bool isThis)780 void TSTypeLowering::LowerTypedStObjByName(GateRef gate, bool isThis)
781 {
782     DISALLOW_GARBAGE_COLLECTION;
783     uint16_t propIndex = acc_.GetConstDataId(acc_.GetValueIn(gate, 1)).GetId();
784     auto thread = tsManager_->GetEcmaVM()->GetJSThread();
785     JSHandle<ConstantPool> constantPool(tsManager_->GetConstantPool());
786     auto prop = ConstantPool::GetStringFromCache(thread, constantPool.GetTaggedValue(), propIndex);
787 
788     GateRef receiver = Circuit::NullGate();
789     GateRef value = Circuit::NullGate();
790     if (isThis) {
791         // 4: number of value inputs
792         ASSERT(acc_.GetNumValueIn(gate) == 4);
793         receiver = acc_.GetValueIn(gate, 3); // 3: this object
794         value = acc_.GetValueIn(gate, 2); // 2: acc
795     } else {
796         // 4: number of value inputs
797         ASSERT(acc_.GetNumValueIn(gate) == 4);
798         receiver = acc_.GetValueIn(gate, 2); // 2: receiver
799         value = acc_.GetValueIn(gate, 3); // 3: acc
800     }
801     GateType receiverType = acc_.GetGateType(receiver);
802     int hclassIndex = tsManager_->GetHClassIndexByInstanceGateType(receiverType);
803     if (hclassIndex == -1) { // slowpath
804         acc_.DeleteStateSplitAndFrameState(gate);
805         return;
806     }
807     JSTaggedValue hclass = tsManager_->GetHClassFromCache(hclassIndex);
808 
809     auto propertyOffset = tsManager_->GetPropertyOffset(hclass, prop);
810     if (propertyOffset == -1) { // slowpath
811         acc_.DeleteStateSplitAndFrameState(gate);
812         return;
813     }
814 
815     AddProfiling(gate);
816 
817     GateRef hclassIndexGate = builder_.IntPtr(hclassIndex);
818     GateRef propertyOffsetGate = builder_.IntPtr(propertyOffset);
819     builder_.ObjectTypeCheck(receiverType, receiver, hclassIndexGate);
820 
821     ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
822     builder_.StoreProperty(receiver, propertyOffsetGate, value);
823 
824     std::vector<GateRef> removedGate;
825     ReplaceHIRGate(gate, Circuit::NullGate(), builder_.GetState(), builder_.GetDepend(), removedGate);
826     DeleteGates(gate, removedGate);
827 }
828 
LowerTypedLdObjByIndex(GateRef gate)829 void TSTypeLowering::LowerTypedLdObjByIndex(GateRef gate)
830 {
831     // 2: number of value inputs
832     ASSERT(acc_.GetNumValueIn(gate) == 2);
833     GateRef receiver = acc_.GetValueIn(gate, 1);
834     GateType receiverType = acc_.GetGateType(receiver);
835     if (!tsManager_->IsFloat32ArrayType(receiverType)) { // slowpath
836         acc_.DeleteStateSplitAndFrameState(gate);
837         return;
838     }
839 
840     AddProfiling(gate);
841 
842     if (tsManager_->IsFloat32ArrayType(receiverType)) {
843         builder_.TypedArrayCheck(receiverType, receiver);
844     } else {
845         LOG_ECMA(FATAL) << "this branch is unreachable";
846         UNREACHABLE();
847     }
848     GateRef index = acc_.GetValueIn(gate, 0);
849     builder_.IndexCheck(receiverType, receiver, index);
850 
851     ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
852     GateRef result = Circuit::NullGate();
853     if (tsManager_->IsFloat32ArrayType(receiverType)) {
854         result = builder_.LoadElement<TypedLoadOp::FLOAT32ARRAY_LOAD_ELEMENT>(receiver, index);
855     } else {
856         UNREACHABLE();
857     }
858 
859     std::vector<GateRef> removedGate;
860     ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
861     DeleteGates(gate, removedGate);
862 }
863 
LowerTypedStObjByIndex(GateRef gate)864 void TSTypeLowering::LowerTypedStObjByIndex(GateRef gate)
865 {
866     // 3: number of value inputs
867     ASSERT(acc_.GetNumValueIn(gate) == 3);
868     GateRef receiver = acc_.GetValueIn(gate, 0);
869     GateRef value = acc_.GetValueIn(gate, 2);
870     GateType receiverType = acc_.GetGateType(receiver);
871     GateType valueType = acc_.GetGateType(value);
872     if ((!tsManager_->IsFloat32ArrayType(receiverType)) || (!valueType.IsNumberType())) { // slowpath
873         acc_.DeleteStateSplitAndFrameState(gate);
874         return;
875     }
876 
877     AddProfiling(gate);
878 
879     if (tsManager_->IsFloat32ArrayType(receiverType)) {
880         builder_.TypedArrayCheck(receiverType, receiver);
881     } else {
882         LOG_ECMA(FATAL) << "this branch is unreachable";
883         UNREACHABLE();
884     }
885     GateRef index = acc_.GetValueIn(gate, 1);
886     builder_.IndexCheck(receiverType, receiver, index);
887     builder_.PrimitiveTypeCheck(valueType, value);
888 
889     ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
890     if (tsManager_->IsFloat32ArrayType(receiverType)) {
891         builder_.StoreElement<TypedStoreOp::FLOAT32ARRAY_STORE_ELEMENT>(receiver, index, value);
892     } else {
893         UNREACHABLE();
894     }
895 
896     std::vector<GateRef> removedGate;
897     ReplaceHIRGate(gate, Circuit::NullGate(), builder_.GetState(), builder_.GetDepend(), removedGate);
898     DeleteGates(gate, removedGate);
899 }
900 
LowerTypedLdObjByValue(GateRef gate,bool isThis)901 void TSTypeLowering::LowerTypedLdObjByValue(GateRef gate, bool isThis)
902 {
903     GateRef receiver = Circuit::NullGate();
904     GateRef propKey = Circuit::NullGate();
905     if (isThis) {
906         // 3: number of value inputs
907         ASSERT(acc_.GetNumValueIn(gate) == 3);
908         receiver = acc_.GetValueIn(gate, 2); // 2: this object
909         propKey = acc_.GetValueIn(gate, 1);
910     } else {
911         // 3: number of value inputs
912         ASSERT(acc_.GetNumValueIn(gate) == 3);
913         receiver = acc_.GetValueIn(gate, 1);
914         propKey = acc_.GetValueIn(gate, 2);  // 2: the third parameter
915     }
916     GateType receiverType = acc_.GetGateType(receiver);
917     GateType propKeyType = acc_.GetGateType(propKey);
918     if (!tsManager_->IsArrayTypeKind(receiverType) || !propKeyType.IsIntType()) { // slowpath
919         acc_.DeleteStateSplitAndFrameState(gate);
920         return;
921     }
922 
923     AddProfiling(gate);
924 
925     builder_.PrimitiveTypeCheck(propKeyType, propKey);
926     builder_.StableArrayCheck(receiver);
927     builder_.IndexCheck(receiverType, receiver, propKey);
928 
929     ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
930     GateRef result = builder_.LoadElement<TypedLoadOp::ARRAY_LOAD_ELEMENT>(receiver, propKey);
931 
932     std::vector<GateRef> removedGate;
933     ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
934     DeleteGates(gate, removedGate);
935 }
936 
LowerTypedIsTrueOrFalse(GateRef gate,bool flag)937 void TSTypeLowering::LowerTypedIsTrueOrFalse(GateRef gate, bool flag)
938 {
939     ASSERT(acc_.GetNumValueIn(gate) == 1);
940     auto value = acc_.GetValueIn(gate, 0);
941     auto valueType = acc_.GetGateType(value);
942     if ((!valueType.IsNumberType()) && (!valueType.IsBooleanType())) {
943         acc_.DeleteStateSplitAndFrameState(gate);
944         return;
945     }
946 
947     AddProfiling(gate);
948 
949     builder_.PrimitiveTypeCheck(valueType, value);
950 
951     ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
952     auto toBool = builder_.TypedUnaryOp<TypedUnOp::TYPED_TOBOOL>(value, valueType, GateType::NJSValue());
953     if (!flag) {
954         toBool = builder_.BoolNot(toBool);
955     }
956     auto result = builder_.BooleanToTaggedBooleanPtr(toBool);
957 
958     std::vector<GateRef> removedGate;
959     ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
960     DeleteGates(gate, removedGate);
961 }
962 
LowerTypedNewObjRange(GateRef gate)963 void TSTypeLowering::LowerTypedNewObjRange(GateRef gate)
964 {
965     GateRef ctor = acc_.GetValueIn(gate, 0);
966     GateType ctorType = acc_.GetGateType(ctor);
967     if (!tsManager_->IsClassTypeKind(ctorType)) {
968         acc_.DeleteStateSplitAndFrameState(gate);
969         return;
970     }
971 
972     AddProfiling(gate);
973 
974     int hclassIndex = tsManager_->GetHClassIndexByClassGateType(ctorType);
975     GateRef stateSplit = acc_.GetDep(gate);
976     ASSERT(acc_.GetOpCode(stateSplit) == OpCode::STATE_SPLIT);
977 
978     GateRef frameState = acc_.GetFrameState(stateSplit);
979     GateRef thisObj = builder_.TypedNewAllocateThis(ctor, builder_.IntPtr(hclassIndex), frameState);
980 
981     // call constructor
982     size_t range = acc_.GetNumValueIn(gate);
983     GateRef envArg = builder_.Undefined();
984     GateRef actualArgc = builder_.Int64(range + 2);  // 2:newTaget, this
985     std::vector<GateRef> args { glue_, envArg, actualArgc, ctor, ctor, thisObj };
986     for (size_t i = 1; i < range; ++i) {  // 1:skip ctor
987         args.emplace_back(acc_.GetValueIn(gate, i));
988     }
989     GateRef bcIndex = builder_.Int64(acc_.GetBytecodeIndex(gate));
990     args.emplace_back(bcIndex);
991 
992     GateRef constructGate = builder_.Construct(args);
993 
994     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), constructGate);
995 }
996 
LowerTypedSuperCall(GateRef gate,GateRef ctor,GateRef newTarget)997 void TSTypeLowering::LowerTypedSuperCall(GateRef gate, GateRef ctor, GateRef newTarget)
998 {
999     GateType ctorType = acc_.GetGateType(ctor);  // ldfunction in derived constructor get function type
1000     if (!tsManager_->IsClassTypeKind(ctorType) && !tsManager_->IsFunctionTypeKind(ctorType)) {
1001         acc_.DeleteStateSplitAndFrameState(gate);
1002         return;
1003     }
1004 
1005     AddProfiling(gate);
1006 
1007     // stateSplit maybe not a STATE_SPLIT
1008     GateRef stateSplit = acc_.GetDep(gate);
1009     ASSERT(acc_.GetOpCode(stateSplit) == OpCode::STATE_SPLIT);
1010 
1011     GateRef frameState = acc_.GetFrameState(stateSplit);
1012     GateRef superCtor = builder_.GetSuperConstructor(ctor);
1013     GateRef thisObj = builder_.TypedSuperAllocateThis(superCtor, newTarget, frameState);
1014 
1015 
1016     // call constructor
1017     size_t range = acc_.GetNumValueIn(gate);
1018     GateRef envArg = builder_.Undefined();
1019     GateRef actualArgc = builder_.Int64(range + 3);  // 3: ctor, newTaget, this
1020     std::vector<GateRef> args { glue_, envArg, actualArgc, superCtor, newTarget, thisObj };
1021     for (size_t i = 0; i < range; ++i) {
1022         args.emplace_back(acc_.GetValueIn(gate, i));
1023     }
1024     GateRef bcIndex = builder_.Int64(acc_.GetBytecodeIndex(gate));
1025     args.emplace_back(bcIndex);
1026 
1027     GateRef constructGate = builder_.Construct(args);
1028 
1029     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), constructGate);
1030 }
1031 
SpeculateCallBuiltin(GateRef gate,BuiltinsStubCSigns::ID id)1032 void TSTypeLowering::SpeculateCallBuiltin(GateRef gate, BuiltinsStubCSigns::ID id)
1033 {
1034     GateRef function = acc_.GetValueIn(gate, 2); // 2:function
1035     GateRef a0 = acc_.GetValueIn(gate, 1);
1036     builder_.CallTargetCheck(function, builder_.IntPtr(static_cast<int64_t>(id)), a0);
1037 
1038     ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
1039     GateRef result = builder_.TypedCallBuiltin(a0, id);
1040 
1041     std::vector<GateRef> removedGate;
1042     ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
1043     DeleteGates(gate, removedGate);
1044 }
1045 
GetBuiltinId(GateRef func,GateRef receiver)1046 BuiltinsStubCSigns::ID TSTypeLowering::GetBuiltinId(GateRef func, GateRef receiver)
1047 {
1048     GateType receiverType = acc_.GetGateType(receiver);
1049     if (!tsManager_->IsBuiltinMath(receiverType)) {
1050         return BuiltinsStubCSigns::ID::NONE;
1051     }
1052     GateType funcType = acc_.GetGateType(func);
1053     if (!tsManager_->IsBuiltin(funcType)) {
1054         return BuiltinsStubCSigns::ID::NONE;
1055     }
1056     std::string name = tsManager_->GetFuncName(funcType);
1057     BuiltinsStubCSigns::ID id = BuiltinLowering::GetBuiltinId(name);
1058     return id;
1059 }
1060 
LowerCallThis1Imm8V8V8(GateRef gate)1061 void TSTypeLowering::LowerCallThis1Imm8V8V8(GateRef gate)
1062 {
1063     GateRef thisObj = acc_.GetValueIn(gate, 0);
1064     GateRef a0 = acc_.GetValueIn(gate, 1); // 1:parameter index
1065     GateType a0Type = acc_.GetGateType(a0);
1066     GateRef func = acc_.GetValueIn(gate, 2); // 2:function
1067     BuiltinsStubCSigns::ID id = GetBuiltinId(func, thisObj);
1068     if (id != BuiltinsStubCSigns::ID::NONE && a0Type.IsNumberType()) {
1069         AddProfiling(gate);
1070         SpeculateCallBuiltin(gate, id);
1071     } else {
1072         acc_.DeleteStateSplitAndFrameState(gate);
1073     }
1074 }
1075 
AddProfiling(GateRef gate)1076 void TSTypeLowering::AddProfiling(GateRef gate)
1077 {
1078     if (IsProfiling()) {
1079         // see stateSplit as a part of JSByteCode if exists
1080         GateRef maybeStateSplit = acc_.GetDep(gate);
1081         GateRef current = Circuit::NullGate();
1082         if (acc_.GetOpCode(maybeStateSplit) == OpCode::STATE_SPLIT) {
1083             current = maybeStateSplit;
1084         } else {
1085             current = gate;
1086         }
1087 
1088         EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
1089         auto ecmaOpcodeGate = builder_.Int32(static_cast<uint32_t>(ecmaOpcode));
1090         GateRef constOpcode = builder_.Int32ToTaggedInt(ecmaOpcodeGate);
1091         GateRef mode =
1092             builder_.Int32ToTaggedInt(builder_.Int32(static_cast<int32_t>(OptCodeProfiler::Mode::TYPED_PATH)));
1093         GateRef profiling = builder_.CallRuntime(glue_, RTSTUB_ID(ProfileOptimizedCode), acc_.GetDep(current),
1094                                                  {constOpcode, mode});
1095         acc_.SetDep(current, profiling);
1096         builder_.SetDepend(acc_.GetDep(gate));  // set gate depend: profiling or STATE_SPLIT
1097     }
1098 }
1099 }  // namespace panda::ecmascript
1100