• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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