• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "ecmascript/jit/jit.h"
18 
19 namespace panda::ecmascript::kungfu {
20 
VisitGate(GateRef gate)21 GateRef TSHCROptPass::VisitGate(GateRef gate)
22 {
23     AddProfiling(gate);
24     auto opcode = acc_.GetOpCode(gate);
25     switch (opcode) {
26         case OpCode::TYPED_BINARY_OP:
27             return VisitTypedBinaryOp(gate);
28         default:
29             break;
30     }
31     return Circuit::NullGate();
32 }
33 
AddProfiling(GateRef gate)34 void TSHCROptPass::AddProfiling(GateRef gate)
35 {
36     if (IsTypedOpProfiling() && acc_.UseForTypeOpProfilerGate(gate)) {
37         Environment env(gate, circuit_, &builder_);
38         OpCode opcode  = acc_.GetOpCode(gate);
39         auto opcodeGate = builder_.Int32(static_cast<uint32_t>(opcode));
40         GateRef constOpcode = builder_.Int32ToTaggedInt(opcodeGate);
41         GateRef traceGate = builder_.CallRuntime(glue_, RTSTUB_ID(ProfileTypedOp),
42                                                  acc_.GetDep(gate), { constOpcode }, gate);
43         acc_.SetDep(gate, traceGate);
44         builder_.SetDepend(acc_.GetDep(gate));
45     }
46 }
47 
VisitTypedBinaryOp(GateRef gate)48 GateRef TSHCROptPass::VisitTypedBinaryOp(GateRef gate)
49 {
50     if (acc_.HasStringType(gate)) {
51         return VisitStringBinOp(gate);
52     }
53     return Circuit::NullGate();
54 }
55 
VisitStringBinOp(GateRef gate)56 GateRef TSHCROptPass::VisitStringBinOp(GateRef gate)
57 {
58     TypedBinOp op = acc_.GetTypedBinaryOp(gate);
59     switch (op) {
60         case TypedBinOp::TYPED_EQ: {
61             Jit::JitLockHolder lock(compilationEnv_, "VisitStringEqual");
62             return VisitStringEqual(gate);
63         }
64         default:
65             return Circuit::NullGate();
66     }
67 }
68 
VisitStringEqual(GateRef gate)69 GateRef TSHCROptPass::VisitStringEqual(GateRef gate)
70 {
71     Environment env(gate, circuit_, &builder_);
72     GateRef left = acc_.GetValueIn(gate, 0);
73     GateRef right = acc_.GetValueIn(gate, 1);
74     if (acc_.IsConstString(left) && acc_.IsConstString(right)) {
75         return ConvertStringEqualToConst(left, right);
76     }
77 
78     if (IsSingleCharString(left) && IsSingleCharString(right)) {
79         return ConvertToSingleCharComparison(left, right);
80     }
81 
82     if (IsNotLoadStrOrStringLoadElement(left) || IsNotLoadStrOrStringLoadElement(right)) {
83         return Circuit::NullGate();
84     }
85 
86     if (IsSingleCharString(left) || IsSingleCharString(right)) {
87         return builder_.Boolean(false);
88     }
89 
90     return Circuit::NullGate();
91 }
92 
ConvertStringEqualToConst(GateRef left,GateRef right)93 GateRef TSHCROptPass::ConvertStringEqualToConst(GateRef left, GateRef right)
94 {
95     uint32_t leftId = acc_.GetStringIdFromLdaStrGate(left);
96     uint32_t rightId = acc_.GetStringIdFromLdaStrGate(right);
97 
98     auto leftMethodOffset = acc_.TryGetMethodOffset(left);
99     auto rightMethodOffset = acc_.TryGetMethodOffset(right);
100     JSHandle<JSTaggedValue> leftStr =
101         compilationEnv_->NewJSHandle(GetStringFromConstantPool(leftMethodOffset, leftId));
102     JSHandle<JSTaggedValue> rightStr =
103         compilationEnv_->NewJSHandle(GetStringFromConstantPool(rightMethodOffset, rightId));
104     if (leftStr->IsUndefined() || rightStr->IsUndefined()) {
105         return Circuit::NullGate();
106     }
107     if (leftStr == rightStr) {
108         return builder_.Boolean(true);
109     }
110     return builder_.Boolean(false);
111 }
112 
IsSingleCharString(GateRef gate)113 bool TSHCROptPass::IsSingleCharString(GateRef gate)
114 {
115     if (acc_.IsConstString(gate)) {
116         uint32_t strId = acc_.GetStringIdFromLdaStrGate(gate);
117         auto methodOffset = acc_.TryGetMethodOffset(gate);
118         JSTaggedValue str = GetStringFromConstantPool(methodOffset, strId);
119         if (str.IsUndefined()) {
120             return false;
121         }
122         return EcmaStringAccessor(str).GetLength() == 1;
123     }
124     return acc_.IsSingleCharGate(gate);
125 }
126 
IsNotLoadStrOrStringLoadElement(GateRef gate)127 bool TSHCROptPass::IsNotLoadStrOrStringLoadElement(GateRef gate)
128 {
129     OpCode op = acc_.GetOpCode(gate);
130     if (op == OpCode::JS_BYTECODE) {
131         EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
132         return ecmaOpcode != EcmaOpcode::LDA_STR_ID16;
133     }
134     if (op == OpCode::LOAD_ELEMENT) {
135         return acc_.GetTypedLoadOp(gate) != TypedLoadOp::STRING_LOAD_ELEMENT;
136     }
137     return true;
138 }
139 
ConvertConstSingleCharToInt32(GateRef gate)140 GateRef TSHCROptPass::ConvertConstSingleCharToInt32(GateRef gate)
141 {
142     ASSERT(acc_.IsConstString(gate));
143     uint32_t strId = acc_.GetStringIdFromLdaStrGate(gate);
144     auto methodOffset = acc_.TryGetMethodOffset(gate);
145     JSTaggedValue str = GetStringFromConstantPool(methodOffset, strId);
146     if (str == JSTaggedValue::Undefined()) {
147         return Circuit::NullGate();
148     }
149     ASSERT(EcmaStringAccessor(str).GetLength() == 1);
150     uint16_t strToInt = EcmaStringAccessor(str).Get(compilationEnv_->GetJSThread(), 0);
151     return builder_.Int32(strToInt);
152 }
153 
ConvertToSingleCharComparison(GateRef left,GateRef right)154 GateRef TSHCROptPass::ConvertToSingleCharComparison(GateRef left, GateRef right)
155 {
156     ASSERT(!acc_.IsConstString(left) || !acc_.IsConstString(right));
157     if (acc_.IsConstString(left)) {
158         left = ConvertConstSingleCharToInt32(left);
159     } else if (acc_.IsConstString(right)) {
160         right = ConvertConstSingleCharToInt32(right);
161     }
162     // change string binary operator to int binary operator
163     return builder_.TypedBinaryOp<TypedBinOp::TYPED_EQ>(left, right, ParamType::IntType());
164 }
165 }  // namespace panda::ecmascript::kungfu
166