14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/compiler/ts_hcr_opt_pass.h" 174514f5e3Sopenharmony_ci#include "ecmascript/jit/jit.h" 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu { 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_ciGateRef TSHCROptPass::VisitGate(GateRef gate) 224514f5e3Sopenharmony_ci{ 234514f5e3Sopenharmony_ci AddProfiling(gate); 244514f5e3Sopenharmony_ci auto opcode = acc_.GetOpCode(gate); 254514f5e3Sopenharmony_ci switch (opcode) { 264514f5e3Sopenharmony_ci case OpCode::TYPED_BINARY_OP: 274514f5e3Sopenharmony_ci return VisitTypedBinaryOp(gate); 284514f5e3Sopenharmony_ci default: 294514f5e3Sopenharmony_ci break; 304514f5e3Sopenharmony_ci } 314514f5e3Sopenharmony_ci return Circuit::NullGate(); 324514f5e3Sopenharmony_ci} 334514f5e3Sopenharmony_ci 344514f5e3Sopenharmony_civoid TSHCROptPass::AddProfiling(GateRef gate) 354514f5e3Sopenharmony_ci{ 364514f5e3Sopenharmony_ci if (IsTypedOpProfiling() && acc_.UseForTypeOpProfilerGate(gate)) { 374514f5e3Sopenharmony_ci Environment env(gate, circuit_, &builder_); 384514f5e3Sopenharmony_ci OpCode opcode = acc_.GetOpCode(gate); 394514f5e3Sopenharmony_ci auto opcodeGate = builder_.Int32(static_cast<uint32_t>(opcode)); 404514f5e3Sopenharmony_ci GateRef constOpcode = builder_.Int32ToTaggedInt(opcodeGate); 414514f5e3Sopenharmony_ci GateRef traceGate = builder_.CallRuntime(acc_.GetGlueFromArgList(), RTSTUB_ID(ProfileTypedOp), 424514f5e3Sopenharmony_ci acc_.GetDep(gate), { constOpcode }, gate); 434514f5e3Sopenharmony_ci acc_.SetDep(gate, traceGate); 444514f5e3Sopenharmony_ci builder_.SetDepend(acc_.GetDep(gate)); 454514f5e3Sopenharmony_ci } 464514f5e3Sopenharmony_ci} 474514f5e3Sopenharmony_ci 484514f5e3Sopenharmony_ciGateRef TSHCROptPass::VisitTypedBinaryOp(GateRef gate) 494514f5e3Sopenharmony_ci{ 504514f5e3Sopenharmony_ci if (acc_.HasStringType(gate)) { 514514f5e3Sopenharmony_ci return VisitStringBinOp(gate); 524514f5e3Sopenharmony_ci } 534514f5e3Sopenharmony_ci return Circuit::NullGate(); 544514f5e3Sopenharmony_ci} 554514f5e3Sopenharmony_ci 564514f5e3Sopenharmony_ciGateRef TSHCROptPass::VisitStringBinOp(GateRef gate) 574514f5e3Sopenharmony_ci{ 584514f5e3Sopenharmony_ci TypedBinOp op = acc_.GetTypedBinaryOp(gate); 594514f5e3Sopenharmony_ci switch (op) { 604514f5e3Sopenharmony_ci case TypedBinOp::TYPED_EQ: { 614514f5e3Sopenharmony_ci Jit::JitLockHolder lock(compilationEnv_, "VisitStringEqual"); 624514f5e3Sopenharmony_ci return VisitStringEqual(gate); 634514f5e3Sopenharmony_ci } 644514f5e3Sopenharmony_ci default: 654514f5e3Sopenharmony_ci return Circuit::NullGate(); 664514f5e3Sopenharmony_ci } 674514f5e3Sopenharmony_ci} 684514f5e3Sopenharmony_ci 694514f5e3Sopenharmony_ciGateRef TSHCROptPass::VisitStringEqual(GateRef gate) 704514f5e3Sopenharmony_ci{ 714514f5e3Sopenharmony_ci Environment env(gate, circuit_, &builder_); 724514f5e3Sopenharmony_ci GateRef left = acc_.GetValueIn(gate, 0); 734514f5e3Sopenharmony_ci GateRef right = acc_.GetValueIn(gate, 1); 744514f5e3Sopenharmony_ci if (acc_.IsConstString(left) && acc_.IsConstString(right)) { 754514f5e3Sopenharmony_ci return ConvertStringEqualToConst(left, right); 764514f5e3Sopenharmony_ci } 774514f5e3Sopenharmony_ci 784514f5e3Sopenharmony_ci if (IsSingleCharString(left) && IsSingleCharString(right)) { 794514f5e3Sopenharmony_ci return ConvertToSingleCharComparison(left, right); 804514f5e3Sopenharmony_ci } 814514f5e3Sopenharmony_ci 824514f5e3Sopenharmony_ci if (IsNotLoadStrOrStringLoadElement(left) || IsNotLoadStrOrStringLoadElement(right)) { 834514f5e3Sopenharmony_ci return Circuit::NullGate(); 844514f5e3Sopenharmony_ci } 854514f5e3Sopenharmony_ci 864514f5e3Sopenharmony_ci if (IsSingleCharString(left) || IsSingleCharString(right)) { 874514f5e3Sopenharmony_ci return builder_.Boolean(false); 884514f5e3Sopenharmony_ci } 894514f5e3Sopenharmony_ci 904514f5e3Sopenharmony_ci return Circuit::NullGate(); 914514f5e3Sopenharmony_ci} 924514f5e3Sopenharmony_ci 934514f5e3Sopenharmony_ciGateRef TSHCROptPass::ConvertStringEqualToConst(GateRef left, GateRef right) 944514f5e3Sopenharmony_ci{ 954514f5e3Sopenharmony_ci uint32_t leftId = acc_.GetStringIdFromLdaStrGate(left); 964514f5e3Sopenharmony_ci uint32_t rightId = acc_.GetStringIdFromLdaStrGate(right); 974514f5e3Sopenharmony_ci 984514f5e3Sopenharmony_ci auto leftMethodOffset = acc_.TryGetMethodOffset(left); 994514f5e3Sopenharmony_ci auto rightMethodOffset = acc_.TryGetMethodOffset(right); 1004514f5e3Sopenharmony_ci JSTaggedValue leftStr = GetStringFromConstantPool(leftMethodOffset, leftId); 1014514f5e3Sopenharmony_ci // jit: disallow alloc jsstring, across gc point 1024514f5e3Sopenharmony_ci JSTaggedValue rightStr = GetStringFromConstantPool(rightMethodOffset, rightId, false); 1034514f5e3Sopenharmony_ci if (leftStr == JSTaggedValue::Undefined() || rightStr == JSTaggedValue::Undefined()) { 1044514f5e3Sopenharmony_ci return Circuit::NullGate(); 1054514f5e3Sopenharmony_ci } 1064514f5e3Sopenharmony_ci if (leftStr == rightStr) { 1074514f5e3Sopenharmony_ci return builder_.Boolean(true); 1084514f5e3Sopenharmony_ci } 1094514f5e3Sopenharmony_ci return builder_.Boolean(false); 1104514f5e3Sopenharmony_ci} 1114514f5e3Sopenharmony_ci 1124514f5e3Sopenharmony_cibool TSHCROptPass::IsSingleCharString(GateRef gate) 1134514f5e3Sopenharmony_ci{ 1144514f5e3Sopenharmony_ci if (acc_.IsConstString(gate)) { 1154514f5e3Sopenharmony_ci uint32_t strId = acc_.GetStringIdFromLdaStrGate(gate); 1164514f5e3Sopenharmony_ci auto methodOffset = acc_.TryGetMethodOffset(gate); 1174514f5e3Sopenharmony_ci JSTaggedValue str = GetStringFromConstantPool(methodOffset, strId); 1184514f5e3Sopenharmony_ci if (str.IsUndefined()) { 1194514f5e3Sopenharmony_ci return false; 1204514f5e3Sopenharmony_ci } 1214514f5e3Sopenharmony_ci return EcmaStringAccessor(str).GetLength() == 1; 1224514f5e3Sopenharmony_ci } 1234514f5e3Sopenharmony_ci return acc_.IsSingleCharGate(gate); 1244514f5e3Sopenharmony_ci} 1254514f5e3Sopenharmony_ci 1264514f5e3Sopenharmony_cibool TSHCROptPass::IsNotLoadStrOrStringLoadElement(GateRef gate) 1274514f5e3Sopenharmony_ci{ 1284514f5e3Sopenharmony_ci OpCode op = acc_.GetOpCode(gate); 1294514f5e3Sopenharmony_ci if (op == OpCode::JS_BYTECODE) { 1304514f5e3Sopenharmony_ci EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate); 1314514f5e3Sopenharmony_ci return ecmaOpcode != EcmaOpcode::LDA_STR_ID16; 1324514f5e3Sopenharmony_ci } 1334514f5e3Sopenharmony_ci if (op == OpCode::LOAD_ELEMENT) { 1344514f5e3Sopenharmony_ci return acc_.GetTypedLoadOp(gate) != TypedLoadOp::STRING_LOAD_ELEMENT; 1354514f5e3Sopenharmony_ci } 1364514f5e3Sopenharmony_ci return true; 1374514f5e3Sopenharmony_ci} 1384514f5e3Sopenharmony_ci 1394514f5e3Sopenharmony_ciGateRef TSHCROptPass::ConvertConstSingleCharToInt32(GateRef gate) 1404514f5e3Sopenharmony_ci{ 1414514f5e3Sopenharmony_ci ASSERT(acc_.IsConstString(gate)); 1424514f5e3Sopenharmony_ci uint32_t strId = acc_.GetStringIdFromLdaStrGate(gate); 1434514f5e3Sopenharmony_ci auto methodOffset = acc_.TryGetMethodOffset(gate); 1444514f5e3Sopenharmony_ci JSTaggedValue str = GetStringFromConstantPool(methodOffset, strId); 1454514f5e3Sopenharmony_ci if (str == JSTaggedValue::Undefined()) { 1464514f5e3Sopenharmony_ci return Circuit::NullGate(); 1474514f5e3Sopenharmony_ci } 1484514f5e3Sopenharmony_ci ASSERT(EcmaStringAccessor(str).GetLength() == 1); 1494514f5e3Sopenharmony_ci uint16_t strToInt = EcmaStringAccessor(str).Get(0); 1504514f5e3Sopenharmony_ci return builder_.Int32(strToInt); 1514514f5e3Sopenharmony_ci} 1524514f5e3Sopenharmony_ci 1534514f5e3Sopenharmony_ciGateRef TSHCROptPass::ConvertToSingleCharComparison(GateRef left, GateRef right) 1544514f5e3Sopenharmony_ci{ 1554514f5e3Sopenharmony_ci ASSERT(!acc_.IsConstString(left) || !acc_.IsConstString(right)); 1564514f5e3Sopenharmony_ci if (acc_.IsConstString(left)) { 1574514f5e3Sopenharmony_ci left = ConvertConstSingleCharToInt32(left); 1584514f5e3Sopenharmony_ci } else if (acc_.IsConstString(right)) { 1594514f5e3Sopenharmony_ci right = ConvertConstSingleCharToInt32(right); 1604514f5e3Sopenharmony_ci } 1614514f5e3Sopenharmony_ci // change string binary operator to int binary operator 1624514f5e3Sopenharmony_ci return builder_.TypedBinaryOp<TypedBinOp::TYPED_EQ>(left, right, ParamType::IntType()); 1634514f5e3Sopenharmony_ci} 1644514f5e3Sopenharmony_ci} // namespace panda::ecmascript::kungfu 165