• 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 
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