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