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/argument_accessor.h" 17 18namespace panda::ecmascript::kungfu { 19void ArgumentAccessor::NewCommonArg(const CommonArgIdx argIndex, MachineType machineType, GateType gateType) 20{ 21 circuit_->NewArg(machineType, static_cast<size_t>(argIndex), gateType, argRoot_); 22} 23 24void ArgumentAccessor::NewArg(const size_t argIndex) 25{ 26 circuit_->NewArg(MachineType::I64, argIndex, GateType::TaggedValue(), argRoot_); 27} 28 29// method must be set 30size_t ArgumentAccessor::GetActualNumArgs() const 31{ 32 ASSERT(method_ != nullptr); 33 auto numArgs = method_->GetNumArgsWithCallField(); 34 return static_cast<size_t>(CommonArgIdx::NUM_OF_ARGS) + numArgs; 35} 36 37// method must be set 38GateRef ArgumentAccessor::GetArgGate(const size_t currentVreg) const 39{ 40 ASSERT(method_ != nullptr); 41 const size_t offsetArgs = method_->GetNumVregsWithCallField(); 42 ASSERT(currentVreg >= offsetArgs && currentVreg < offsetArgs + method_->GetNumArgs()); 43 auto reg = currentVreg - offsetArgs; 44 auto haveFunc = method_->HaveFuncWithCallField(); 45 auto haveNewTarget = method_->HaveNewTargetWithCallField(); 46 auto haveThis = method_->HaveThisWithCallField(); 47 auto index = GetFunctionArgIndex(reg, haveFunc, haveNewTarget, haveThis); 48 return args_.at(index); 49} 50 51bool ArgumentAccessor::ArgGateNotExisted(const size_t currentVreg) 52{ 53 const size_t offsetArgs = method_->GetNumVregsWithCallField(); 54 if (currentVreg < offsetArgs || currentVreg >= offsetArgs + method_->GetNumArgs()) { 55 return true; 56 } 57 return false; 58} 59 60GateRef ArgumentAccessor::GetCommonArgGate(const CommonArgIdx arg) const 61{ 62 return args_.at(static_cast<size_t>(arg)); 63} 64 65size_t ArgumentAccessor::GetFunctionArgIndex(const size_t currentVreg, const bool haveFunc, 66 const bool haveNewTarget, const bool haveThis) const 67{ 68 size_t numCommonArgs = haveFunc + haveNewTarget + haveThis; 69 // 2: number of common args 70 if (numCommonArgs == 2) { 71 if (!haveFunc && currentVreg == 0) { 72 return static_cast<size_t>(CommonArgIdx::NEW_TARGET); 73 } 74 if (!haveFunc && currentVreg == 1) { 75 return static_cast<size_t>(CommonArgIdx::THIS_OBJECT); 76 } 77 if (!haveNewTarget && currentVreg == 0) { 78 return static_cast<size_t>(CommonArgIdx::FUNC); 79 } 80 if (!haveNewTarget && currentVreg == 1) { 81 return static_cast<size_t>(CommonArgIdx::THIS_OBJECT); 82 } 83 if (!haveThis && currentVreg == 0) { 84 return static_cast<size_t>(CommonArgIdx::FUNC); 85 } 86 if (!haveThis && currentVreg == 1) { 87 return static_cast<size_t>(CommonArgIdx::NEW_TARGET); 88 } 89 } 90 // 1: number of common args, 0: the index of currentVreg 91 if (numCommonArgs == 1 && currentVreg == 0) { 92 if (haveFunc) { 93 return static_cast<size_t>(CommonArgIdx::FUNC); 94 } 95 if (haveNewTarget) { 96 return static_cast<size_t>(CommonArgIdx::NEW_TARGET); 97 } 98 if (haveThis) { 99 return static_cast<size_t>(CommonArgIdx::THIS_OBJECT); 100 } 101 } 102 103 size_t numOfArgs = static_cast<size_t>(CommonArgIdx::NUM_OF_ARGS); 104 ASSERT(currentVreg + numOfArgs >= numCommonArgs); 105 return currentVreg + numOfArgs - numCommonArgs; 106} 107 108void ArgumentAccessor::CollectArgs() 109{ 110 if (args_.size() == 0) { 111 GateAccessor(circuit_).GetArgsOuts(args_); 112 std::reverse(args_.begin(), args_.end()); 113 if (method_ == nullptr) { 114 return; 115 } 116 if (method_->IsFastCall() && args_.size() > 2) { // 2: mean have func and glue 117 GateRef actualArgcGate = circuit_->GetConstantGate(MachineType::I64, 0, GateType::NJSValue()); 118 GateRef actualArgvGate = circuit_->GetConstantGate(MachineType::ARCH, 0, GateType::NJSValue()); 119 GateRef newTargetGate = circuit_->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_UNDEFINED, 120 GateType::UndefinedType()); 121 if (method_->GetFunctionKind() == FunctionKind::CLASS_CONSTRUCTOR) { 122 newTargetGate = args_[1]; // 1: mean func index 123 } 124 args_.insert(args_.begin() + static_cast<size_t>(CommonArgIdx::ACTUAL_ARGC), actualArgcGate); 125 args_.insert(args_.begin() + static_cast<size_t>(CommonArgIdx::ACTUAL_ARGV), actualArgvGate); 126 args_.insert(args_.begin() + static_cast<size_t>(CommonArgIdx::NEW_TARGET), newTargetGate); 127 } 128 } 129} 130 131GateRef ArgumentAccessor::GetFrameArgsIn(GateRef gate, FrameArgIdx idx) 132{ 133 GateAccessor gateAcc(circuit_); 134 OpCode opCode = gateAcc.GetOpCode(gate); 135 ASSERT(opCode == OpCode::JS_BYTECODE || opCode == OpCode::FRAME_STATE); 136 GateRef frameArgs = Circuit::NullGate(); 137 if (opCode == OpCode::JS_BYTECODE) { 138 GateRef frameState = gateAcc.GetFrameState(gate); 139 OpCode op = gateAcc.GetOpCode(frameState); 140 if (op == OpCode::FRAME_STATE) { 141 frameArgs = gateAcc.GetValueIn(frameState, 0); // 0: frame args 142 } else { 143 ASSERT(op == OpCode::FRAME_ARGS); 144 frameArgs = frameState; 145 } 146 } else { 147 frameArgs = gateAcc.GetValueIn(gate, 0); // 0: frame args 148 } 149 return gateAcc.GetValueIn(frameArgs, static_cast<size_t>(idx)); 150} 151} // namespace panda::ecmascript::kungfu 152