1 /*
2 * Copyright (c) 2023 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_hcr_opt_pass.h"
17
18 namespace panda::ecmascript::kungfu {
19
VisitGate(GateRef gate)20 GateRef TSHCROptPass::VisitGate(GateRef gate)
21 {
22 auto opcode = acc_.GetOpCode(gate);
23 switch (opcode) {
24 case OpCode::TYPED_BINARY_OP:
25 return VisitTypedBinaryOp(gate);
26 default:
27 break;
28 }
29 return Circuit::NullGate();
30 }
31
VisitTypedBinaryOp(GateRef gate)32 GateRef TSHCROptPass::VisitTypedBinaryOp(GateRef gate)
33 {
34 if (acc_.HasStringType(gate)) {
35 return VisitStringBinOp(gate);
36 }
37 return Circuit::NullGate();
38 }
39
VisitStringBinOp(GateRef gate)40 GateRef TSHCROptPass::VisitStringBinOp(GateRef gate)
41 {
42 TypedBinOp op = acc_.GetTypedBinaryOp(gate);
43 switch (op) {
44 case TypedBinOp::TYPED_EQ:
45 return VisitStringEqual(gate);
46 default:
47 return Circuit::NullGate();
48 }
49 }
50
VisitStringEqual(GateRef gate)51 GateRef TSHCROptPass::VisitStringEqual(GateRef gate)
52 {
53 Environment env(gate, circuit_, &builder_);
54 GateRef left = acc_.GetValueIn(gate, 0);
55 GateRef right = acc_.GetValueIn(gate, 1);
56 if (acc_.IsConstString(left) && acc_.IsConstString(right)) {
57 return ConvertStringEqualToConst(left, right);
58 }
59
60 if (IsSingleCharString(left) && IsSingleCharString(right)) {
61 return ConvertToSingleCharComparison(left, right);
62 }
63
64 if (IsNotLoadStrOrStringLoadElement(left) || IsNotLoadStrOrStringLoadElement(right)) {
65 return Circuit::NullGate();
66 }
67
68 if (IsSingleCharString(left) || IsSingleCharString(right)) {
69 return builder_.Boolean(false);
70 }
71
72 return Circuit::NullGate();
73 }
74
ConvertStringEqualToConst(GateRef left,GateRef right)75 GateRef TSHCROptPass::ConvertStringEqualToConst(GateRef left, GateRef right)
76 {
77 uint32_t leftId = acc_.GetStringIdFromLdaStrGate(left);
78 uint32_t rightId = acc_.GetStringIdFromLdaStrGate(right);
79
80 auto leftMethodOffset = acc_.TryGetMethodOffset(left);
81 auto rightMethodOffset = acc_.TryGetMethodOffset(right);
82 JSHandle<EcmaString> leftStr(thread_, GetStringFromCP(leftMethodOffset, leftId));
83 JSHandle<EcmaString> rightStr(thread_, GetStringFromCP(rightMethodOffset, rightId));
84 bool isEqual = EcmaStringAccessor::StringsAreEqual(thread_->GetEcmaVM(), leftStr, rightStr);
85 if (isEqual) {
86 return builder_.Boolean(true);
87 }
88 return builder_.Boolean(false);
89 }
90
IsSingleCharString(GateRef gate)91 bool TSHCROptPass::IsSingleCharString(GateRef gate)
92 {
93 if (acc_.IsConstString(gate)) {
94 uint32_t strId = acc_.GetStringIdFromLdaStrGate(gate);
95 auto methodOffset = acc_.TryGetMethodOffset(gate);
96 JSTaggedValue str = GetStringFromCP(methodOffset, strId);
97 return EcmaStringAccessor(str).GetLength() == 1;
98 }
99 return acc_.IsSingleCharGate(gate);
100 }
101
IsNotLoadStrOrStringLoadElement(GateRef gate)102 bool TSHCROptPass::IsNotLoadStrOrStringLoadElement(GateRef gate)
103 {
104 OpCode op = acc_.GetOpCode(gate);
105 if (op == OpCode::JS_BYTECODE) {
106 EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
107 return ecmaOpcode != EcmaOpcode::LDA_STR_ID16;
108 }
109 if (op == OpCode::LOAD_ELEMENT) {
110 return acc_.GetTypedLoadOp(gate) != TypedLoadOp::STRING_LOAD_ELEMENT;
111 }
112 return true;
113 }
114
ConvertConstSingleCharToInt32(GateRef gate)115 GateRef TSHCROptPass::ConvertConstSingleCharToInt32(GateRef gate)
116 {
117 ASSERT(acc_.IsConstString(gate));
118 uint32_t strId = acc_.GetStringIdFromLdaStrGate(gate);
119 auto methodOffset = acc_.TryGetMethodOffset(gate);
120 JSTaggedValue str = tsManager_->GetStringFromConstantPool(methodOffset, strId);
121 ASSERT(EcmaStringAccessor(str).GetLength() == 1);
122 uint16_t strToInt = EcmaStringAccessor(str).Get(0);
123 return builder_.Int32(strToInt);
124 }
125
ConvertToSingleCharComparison(GateRef left,GateRef right)126 GateRef TSHCROptPass::ConvertToSingleCharComparison(GateRef left, GateRef right)
127 {
128 ASSERT(!acc_.IsConstString(left) || !acc_.IsConstString(right));
129 if (acc_.IsConstString(left)) {
130 left = ConvertConstSingleCharToInt32(left);
131 } else if (acc_.IsConstString(right)) {
132 right = ConvertConstSingleCharToInt32(right);
133 }
134 return builder_.TypedBinaryOp<TypedBinOp::TYPED_EQ>(left, right, GateType::IntType(),
135 GateType::IntType(), GateType::BooleanType(),
136 PGOTypeRef::NoneType());
137 }
138 } // namespace panda::ecmascript::kungfu
139