• 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/ntype_mcr_lowering.h"
17 #include "ecmascript/dfx/vmstat/opt_code_profiler.h"
18 #include "ecmascript/compiler/new_object_stub_builder.h"
19 
20 namespace panda::ecmascript::kungfu {
RunNTypeMCRLowering()21 void NTypeMCRLowering::RunNTypeMCRLowering()
22 {
23     std::vector<GateRef> gateList;
24     circuit_->GetAllGates(gateList);
25 
26     for (const auto &gate : gateList) {
27         Lower(gate);
28     }
29 
30     if (IsLogEnabled()) {
31         LOG_COMPILER(INFO) << "";
32         LOG_COMPILER(INFO) << "\033[34m" << "=================="
33                            << " after NTypeMCRlowering "
34                            << "[" << GetMethodName() << "] "
35                            << "==================" << "\033[0m";
36         circuit_->PrintAllGatesWithBytecode();
37         LOG_COMPILER(INFO) << "\033[34m" << "=========================== End =========================" << "\033[0m";
38     }
39 }
40 
Lower(GateRef gate)41 void NTypeMCRLowering::Lower(GateRef gate)
42 {
43     GateRef glue = acc_.GetGlueFromArgList();
44     auto op = acc_.GetOpCode(gate);
45     switch (op) {
46         case OpCode::CREATE_ARRAY:
47             LowerCreateArray(gate, glue);
48             break;
49         case OpCode::CREATE_ARRAY_WITH_BUFFER:
50             LowerCreateArrayWithBuffer(gate);
51             break;
52         default:
53             break;
54     }
55 }
56 
LowerCreateArray(GateRef gate,GateRef glue)57 void NTypeMCRLowering::LowerCreateArray(GateRef gate, GateRef glue)
58 {
59     Environment env(gate, circuit_, &builder_);
60     if (acc_.GetArraySize(gate) == 0) {
61         LowerCreateEmptyArray(gate);
62     } else {
63         LowerCreateArrayWithOwn(gate, glue);
64     }
65 }
66 
LowerCreateEmptyArray(GateRef gate)67 void NTypeMCRLowering::LowerCreateEmptyArray(GateRef gate)
68 {
69     GateRef length = builder_.Int32(0);
70     GateRef elements = builder_.GetGlobalConstantValue(ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
71 
72     auto array = NewJSArrayLiteral(elements, length);
73     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), array);
74 }
75 
LowerCreateArrayWithOwn(GateRef gate,GateRef glue)76 void NTypeMCRLowering::LowerCreateArrayWithOwn(GateRef gate, GateRef glue)
77 {
78     size_t elementsLength = acc_.GetArraySize(gate);
79     GateRef length = builder_.IntPtr(elementsLength);
80     GateRef elements = Circuit::NullGate();
81     if (elementsLength < MAX_TAGGED_ARRAY_LENGTH) {
82         elements = NewTaggedArray(elementsLength);
83     } else {
84         elements = LowerCallRuntime(glue, gate, RTSTUB_ID(NewTaggedArray), { builder_.Int32ToTaggedInt(length) }, true);
85     }
86 
87     auto array = NewJSArrayLiteral(elements, length);
88     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), array);
89 }
90 
LowerCreateArrayWithBuffer(GateRef gate)91 void NTypeMCRLowering::LowerCreateArrayWithBuffer(GateRef gate)
92 {
93     Environment env(gate, circuit_, &builder_);
94     // 2: number of value inputs
95     ASSERT(acc_.GetNumValueIn(gate) == 2);
96     GateRef index = acc_.GetValueIn(gate, 0);
97     GateRef aotElmIndex = acc_.GetValueIn(gate, 1);
98     auto elementIndex = acc_.GetConstantValue(aotElmIndex);
99     uint32_t elementLength = static_cast<uint32_t>(acc_.GetArraySize(gate));
100     uint32_t constPoolIndex = static_cast<uint32_t>(acc_.GetConstantValue(index));
101     ArgumentAccessor argAcc(circuit_);
102     GateRef frameState = GetFrameState(gate);
103     GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC);
104     GateRef elements = LoadFromConstPool(jsFunc, elementIndex);
105     auto thread = tsManager_->GetEcmaVM()->GetJSThread();
106     JSHandle<ConstantPool> constpoolHandle(tsManager_->GetConstantPool());
107     JSTaggedValue arr = ConstantPool::GetLiteralFromCache<ConstPoolType::ARRAY_LITERAL>(
108         thread, constpoolHandle.GetTaggedValue(), constPoolIndex, recordName_);
109     JSHandle<JSArray> arrayHandle(thread, arr);
110     TaggedArray *arrayLiteral = TaggedArray::Cast(arrayHandle->GetElements());
111     uint32_t literialLength = arrayLiteral->GetLength();
112     uint32_t arrayLength = std::max(literialLength, elementLength);
113     GateRef length = builder_.IntPtr(arrayLength);
114 
115     auto array = NewJSArrayLiteral(elements, length);
116     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), array);
117 }
118 
LoadFromConstPool(GateRef jsFunc,size_t index)119 GateRef NTypeMCRLowering::LoadFromConstPool(GateRef jsFunc, size_t index)
120 {
121     GateRef constPool = builder_.GetConstPool(jsFunc);
122     return builder_.LoadFromTaggedArray(constPool, index);
123 }
124 
NewJSArrayLiteral(GateRef elements,GateRef length)125 GateRef NTypeMCRLowering::NewJSArrayLiteral(GateRef elements, GateRef length)
126 {
127     JSHandle<JSFunction> arrayFunc(tsManager_->GetEcmaVM()->GetGlobalEnv()->GetArrayFunction());
128     JSTaggedValue protoOrHClass = arrayFunc->GetProtoOrHClass();
129     JSHClass *arrayHC = JSHClass::Cast(protoOrHClass.GetTaggedObject());
130     size_t arraySize = arrayHC->GetObjectSize();
131     size_t lengthAccessorOffset = arrayHC->GetInlinedPropertiesOffset(JSArray::LENGTH_INLINE_PROPERTY_INDEX);
132 
133     GateRef emptyArray = builder_.GetGlobalConstantValue(ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
134     GateRef globalEnv = builder_.GetGlobalEnv();
135     GateRef accessor = builder_.GetGlobalConstantValue(ConstantIndex::ARRAY_LENGTH_ACCESSOR);
136     GateRef hclass = builder_.GetGlobalEnvObjHClass(globalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
137     GateRef size = builder_.IntPtr(arrayHC->GetObjectSize());
138 
139     builder_.StartAllocate();
140     GateRef array = builder_.HeapAlloc(size, GateType::TaggedValue(), RegionSpaceFlag::IN_YOUNG_SPACE);
141     // initialization
142     for (size_t offset = JSArray::SIZE; offset < arraySize; offset += JSTaggedValue::TaggedTypeSize()) {
143         builder_.StoreConstOffset(VariableType::INT64(), array, offset, builder_.Undefined());
144     }
145     builder_.StoreConstOffset(VariableType::JS_POINTER(), array, 0, hclass);
146     builder_.StoreConstOffset(VariableType::INT64(), array, ECMAObject::HASH_OFFSET,
147                               builder_.Int64(JSTaggedValue(0).GetRawData()));
148     builder_.StoreConstOffset(VariableType::JS_POINTER(), array, JSObject::PROPERTIES_OFFSET, emptyArray);
149     builder_.StoreConstOffset(VariableType::JS_POINTER(), array, JSObject::ELEMENTS_OFFSET, elements);
150     builder_.StoreConstOffset(VariableType::INT32(), array, JSArray::LENGTH_OFFSET, length);
151     builder_.StoreConstOffset(VariableType::JS_POINTER(), array, lengthAccessorOffset, accessor);
152     builder_.FinishAllocate();
153     return array;
154 }
155 
NewTaggedArray(size_t length)156 GateRef NTypeMCRLowering::NewTaggedArray(size_t length)
157 {
158     GateRef elementsHclass = builder_.GetGlobalConstantValue(ConstantIndex::ARRAY_CLASS_INDEX);
159     GateRef elementsSize = builder_.ComputeTaggedArraySize(builder_.IntPtr(length));
160 
161     builder_.StartAllocate();
162     GateRef elements = builder_.HeapAlloc(elementsSize, GateType::TaggedValue(), RegionSpaceFlag::IN_YOUNG_SPACE);
163     builder_.StoreConstOffset(VariableType::JS_POINTER(), elements, 0, elementsHclass);
164     builder_.StoreConstOffset(VariableType::JS_ANY(), elements, TaggedArray::LENGTH_OFFSET,
165         builder_.Int32ToTaggedInt(builder_.IntPtr(length)));
166     size_t endOffset = TaggedArray::DATA_OFFSET + length * JSTaggedValue::TaggedTypeSize();
167     // initialization
168     for (size_t offset = TaggedArray::DATA_OFFSET; offset < endOffset; offset += JSTaggedValue::TaggedTypeSize()) {
169         builder_.StoreConstOffset(VariableType::INT64(), elements, offset, builder_.Hole());
170     }
171     builder_.FinishAllocate();
172 
173     return elements;
174 }
175 
LowerCallRuntime(GateRef glue,GateRef hirGate,int index,const std::vector<GateRef> & args,bool useLabel)176 GateRef NTypeMCRLowering::LowerCallRuntime(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args,
177     bool useLabel)
178 {
179     if (useLabel) {
180         GateRef result = builder_.CallRuntime(glue, index, Gate::InvalidGateRef, args, hirGate);
181         return result;
182     } else {
183         const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
184         GateRef target = builder_.IntPtr(index);
185         GateRef result = builder_.Call(cs, glue, target, dependEntry_, args, hirGate);
186         return result;
187     }
188 }
189 }
190