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
18 namespace panda::ecmascript::kungfu {
NewCommonArg(const CommonArgIdx argIndex,MachineType machineType,GateType gateType)19 void ArgumentAccessor::NewCommonArg(const CommonArgIdx argIndex, MachineType machineType, GateType gateType)
20 {
21 circuit_->NewArg(machineType, static_cast<size_t>(argIndex), gateType, argRoot_);
22 }
23
NewArg(const size_t argIndex)24 void ArgumentAccessor::NewArg(const size_t argIndex)
25 {
26 circuit_->NewArg(MachineType::I64, argIndex, GateType::TaggedValue(), argRoot_);
27 }
28
29 // method must be set
GetActualNumArgs() const30 size_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
GetArgGate(const size_t currentVreg) const38 GateRef 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
ArgGateNotExisted(const size_t currentVreg)51 bool 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
GetTypedArgGate(const size_t argIndex) const60 GateRef ArgumentAccessor::GetTypedArgGate(const size_t argIndex) const
61 {
62 if (argIndex == static_cast<size_t>(TypedArgIdx::FUNC)) {
63 return GetCommonArgGate(CommonArgIdx::FUNC);
64 }
65 if (argIndex == static_cast<size_t>(TypedArgIdx::NEW_TARGET)) {
66 return GetCommonArgGate(CommonArgIdx::NEW_TARGET);
67 }
68 if (argIndex == static_cast<size_t>(TypedArgIdx::THIS_OBJECT)) {
69 return GetCommonArgGate(CommonArgIdx::THIS_OBJECT);
70 }
71 return args_.at(argIndex - static_cast<size_t>(TypedArgIdx::NUM_OF_TYPED_ARGS) +
72 static_cast<size_t>(CommonArgIdx::NUM_OF_ARGS));
73 }
74
GetCommonArgGate(const CommonArgIdx arg) const75 GateRef ArgumentAccessor::GetCommonArgGate(const CommonArgIdx arg) const
76 {
77 return args_.at(static_cast<size_t>(arg));
78 }
79
GetFunctionArgIndex(const size_t currentVreg,const bool haveFunc,const bool haveNewTarget,const bool haveThis) const80 size_t ArgumentAccessor::GetFunctionArgIndex(const size_t currentVreg, const bool haveFunc,
81 const bool haveNewTarget, const bool haveThis) const
82 {
83 size_t numCommonArgs = haveFunc + haveNewTarget + haveThis;
84 // 2: number of common args
85 if (numCommonArgs == 2) {
86 if (!haveFunc && currentVreg == 0) {
87 return static_cast<size_t>(CommonArgIdx::NEW_TARGET);
88 }
89 if (!haveFunc && currentVreg == 1) {
90 return static_cast<size_t>(CommonArgIdx::THIS_OBJECT);
91 }
92 if (!haveNewTarget && currentVreg == 0) {
93 return static_cast<size_t>(CommonArgIdx::FUNC);
94 }
95 if (!haveNewTarget && currentVreg == 1) {
96 return static_cast<size_t>(CommonArgIdx::THIS_OBJECT);
97 }
98 if (!haveThis && currentVreg == 0) {
99 return static_cast<size_t>(CommonArgIdx::FUNC);
100 }
101 if (!haveThis && currentVreg == 1) {
102 return static_cast<size_t>(CommonArgIdx::NEW_TARGET);
103 }
104 }
105 // 1: number of common args, 0: the index of currentVreg
106 if (numCommonArgs == 1 && currentVreg == 0) {
107 if (haveFunc) {
108 return static_cast<size_t>(CommonArgIdx::FUNC);
109 }
110 if (haveNewTarget) {
111 return static_cast<size_t>(CommonArgIdx::NEW_TARGET);
112 }
113 if (haveThis) {
114 return static_cast<size_t>(CommonArgIdx::THIS_OBJECT);
115 }
116 }
117 return currentVreg - numCommonArgs + static_cast<size_t>(CommonArgIdx::NUM_OF_ARGS);
118 }
119
FillArgsGateType(const TypeRecorder * typeRecorder)120 void ArgumentAccessor::FillArgsGateType(const TypeRecorder *typeRecorder)
121 {
122 ASSERT(method_ != nullptr);
123 GateAccessor gateAcc(circuit_);
124 const size_t numOfTypedArgs = method_->GetNumArgsWithCallField() +
125 static_cast<size_t>(TypedArgIdx::NUM_OF_TYPED_ARGS);
126 for (uint32_t argIndex = 0; argIndex < numOfTypedArgs; argIndex++) {
127 auto argType = typeRecorder->GetArgType(argIndex);
128 if (!argType.IsAnyType()) {
129 auto gate = GetTypedArgGate(argIndex);
130 gateAcc.SetGateType(gate, argType);
131 }
132 }
133 }
134
CollectArgs()135 void ArgumentAccessor::CollectArgs()
136 {
137 if (args_.size() == 0) {
138 GateAccessor(circuit_).GetArgsOuts(args_);
139 std::reverse(args_.begin(), args_.end());
140 if (method_ == nullptr) {
141 return;
142 }
143 if (method_->IsFastCall() && args_.size() > 2) { // 2: mean have func and glue
144 GateRef actualArgcGate = circuit_->GetConstantGate(MachineType::I64, 0, GateType::NJSValue());
145 GateRef newTargetGate = circuit_->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_UNDEFINED,
146 GateType::UndefinedType());
147 args_.insert(args_.begin() + 1, actualArgcGate);
148 args_.insert(args_.begin() + 3, newTargetGate); // 3: newtarget index
149 }
150 }
151 }
152
GetFrameArgsIn(GateRef gate,FrameArgIdx idx)153 GateRef ArgumentAccessor::GetFrameArgsIn(GateRef gate, FrameArgIdx idx)
154 {
155 GateAccessor gateAcc(circuit_);
156 ASSERT(gateAcc.GetOpCode(gate) == OpCode::JS_BYTECODE || gateAcc.GetOpCode(gate) == OpCode::FRAME_STATE);
157 GateRef frameArgs = Circuit::NullGate();
158 if (gateAcc.GetOpCode(gate) == OpCode::JS_BYTECODE) {
159 frameArgs = gateAcc.GetFrameState(gate);
160 ASSERT(gateAcc.GetOpCode(frameArgs) == OpCode::FRAME_ARGS);
161 } else {
162 frameArgs = gateAcc.GetValueIn(gate, 0); // 0: frame args
163 }
164 return gateAcc.GetValueIn(frameArgs, static_cast<size_t>(idx));
165 }
166 } // namespace panda::ecmascript::kungfu
167