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 #include "ecmascript/compiler/ic_stub_builder.h"
16 #include "ecmascript/compiler/stub_builder-inl.h"
17
18 namespace panda::ecmascript::kungfu {
NamedICAccessor(Variable * cachedHandler,Label * tryICHandler)19 void ICStubBuilder::NamedICAccessor(Variable* cachedHandler, Label *tryICHandler)
20 {
21 auto env = GetEnvironment();
22 Label receiverIsHeapObject(env);
23 Label tryIC(env);
24
25 Branch(TaggedIsHeapObject(receiver_), &receiverIsHeapObject, slowPath_);
26 Bind(&receiverIsHeapObject);
27 {
28 Branch(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC);
29 Bind(&tryIC);
30 {
31 Label isHeapObject(env);
32 Label notHeapObject(env);
33 GateRef firstValue = GetValueFromTaggedArray(
34 profileTypeInfo_, slotId_);
35 Branch(TaggedIsHeapObject(firstValue), &isHeapObject, ¬HeapObject);
36 Bind(&isHeapObject);
37 {
38 Label tryPoly(env);
39 GateRef hclass = LoadHClass(receiver_);
40 Branch(Equal(LoadObjectFromWeakRef(firstValue), hclass),
41 tryICHandler,
42 &tryPoly);
43 Bind(&tryPoly);
44 {
45 cachedHandler->WriteVariable(CheckPolyHClass(firstValue, hclass));
46 Branch(TaggedIsHole(cachedHandler->ReadVariable()), slowPath_, tryICHandler);
47 }
48 }
49 Bind(¬HeapObject);
50 {
51 Branch(TaggedIsUndefined(firstValue), slowPath_, tryFastPath_);
52 }
53 }
54 }
55 }
56
ValuedICAccessor(Variable * cachedHandler,Label * tryICHandler,Label * tryElementIC)57 void ICStubBuilder::ValuedICAccessor(Variable* cachedHandler, Label *tryICHandler, Label* tryElementIC)
58 {
59 auto env = GetEnvironment();
60 Label receiverIsHeapObject(env);
61
62 Branch(TaggedIsHeapObject(receiver_), &receiverIsHeapObject, slowPath_);
63 Bind(&receiverIsHeapObject);
64 {
65 Label tryIC(env);
66 Branch(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC);
67 Bind(&tryIC);
68 {
69 Label isHeapObject(env);
70 Label notHeapObject(env);
71 GateRef firstValue = GetValueFromTaggedArray(
72 profileTypeInfo_, slotId_);
73 Branch(TaggedIsHeapObject(firstValue), &isHeapObject, ¬HeapObject);
74 Bind(&isHeapObject);
75 {
76 Label tryPoly(env);
77 GateRef hclass = LoadHClass(receiver_);
78 Branch(Equal(LoadObjectFromWeakRef(firstValue), hclass),
79 tryElementIC,
80 &tryPoly);
81 Bind(&tryPoly);
82 {
83 Label firstIsKey(env);
84 Branch(Int64Equal(firstValue, propKey_), &firstIsKey, slowPath_);
85 Bind(&firstIsKey);
86 GateRef handler = CheckPolyHClass(cachedHandler->ReadVariable(), hclass);
87 cachedHandler->WriteVariable(handler);
88 Branch(TaggedIsHole(cachedHandler->ReadVariable()), slowPath_, tryICHandler);
89 }
90 }
91 Bind(¬HeapObject);
92 {
93 Branch(TaggedIsUndefined(firstValue), slowPath_, tryFastPath_);
94 }
95 }
96 }
97 }
98
LoadICByName(Variable * result,Label * tryFastPath,Label * slowPath,Label * success)99 void ICStubBuilder::LoadICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success)
100 {
101 auto env = GetEnvironment();
102 Label loadWithHandler(env);
103
104 SetLabels(tryFastPath, slowPath, success);
105 GateRef secondValue = GetValueFromTaggedArray(
106 profileTypeInfo_, Int32Add(slotId_, Int32(1)));
107 DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue);
108 NamedICAccessor(&cachedHandler, &loadWithHandler);
109 Bind(&loadWithHandler);
110 {
111 GateRef ret = LoadICWithHandler(glue_, receiver_, receiver_, *cachedHandler);
112 result->WriteVariable(ret);
113 Branch(TaggedIsHole(ret), slowPath_, success_);
114 }
115 }
116
StoreICByName(Variable * result,Label * tryFastPath,Label * slowPath,Label * success)117 void ICStubBuilder::StoreICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success)
118 {
119 auto env = GetEnvironment();
120 Label storeWithHandler(env);
121
122 SetLabels(tryFastPath, slowPath, success);
123 GateRef secondValue = GetValueFromTaggedArray(
124 profileTypeInfo_, Int32Add(slotId_, Int32(1)));
125 DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue);
126 NamedICAccessor(&cachedHandler, &storeWithHandler);
127 Bind(&storeWithHandler);
128 {
129 GateRef ret = StoreICWithHandler(glue_, receiver_, receiver_, value_, *cachedHandler);
130 result->WriteVariable(ret);
131 Branch(TaggedIsHole(ret), slowPath_, success_);
132 }
133 }
134
LoadICByValue(Variable * result,Label * tryFastPath,Label * slowPath,Label * success)135 void ICStubBuilder::LoadICByValue(Variable* result, Label* tryFastPath, Label *slowPath, Label *success)
136 {
137 auto env = GetEnvironment();
138 Label loadWithHandler(env);
139 Label loadElement(env);
140
141 SetLabels(tryFastPath, slowPath, success);
142 GateRef secondValue = GetValueFromTaggedArray(
143 profileTypeInfo_, Int32Add(slotId_, Int32(1)));
144 DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue);
145 ValuedICAccessor(&cachedHandler, &loadWithHandler, &loadElement);
146 Bind(&loadElement);
147 {
148 GateRef ret = LoadElement(receiver_, propKey_);
149 result->WriteVariable(ret);
150 Branch(TaggedIsHole(ret), slowPath_, success_);
151 }
152 Bind(&loadWithHandler);
153 {
154 GateRef ret = LoadICWithHandler(glue_, receiver_, receiver_, *cachedHandler);
155 result->WriteVariable(ret);
156 Branch(TaggedIsHole(ret), slowPath_, success_);
157 }
158 }
159
StoreICByValue(Variable * result,Label * tryFastPath,Label * slowPath,Label * success)160 void ICStubBuilder::StoreICByValue(Variable* result, Label* tryFastPath, Label *slowPath, Label *success)
161 {
162 auto env = GetEnvironment();
163 Label storeWithHandler(env);
164 Label storeElement(env);
165
166 SetLabels(tryFastPath, slowPath, success);
167 GateRef secondValue = GetValueFromTaggedArray(
168 profileTypeInfo_, Int32Add(slotId_, Int32(1)));
169 DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue);
170 ValuedICAccessor(&cachedHandler, &storeWithHandler, &storeElement);
171 Bind(&storeElement);
172 {
173 GateRef ret = ICStoreElement(glue_, receiver_, propKey_, value_, secondValue);
174 result->WriteVariable(ret);
175 Branch(TaggedIsHole(ret), slowPath_, success_);
176 }
177 Bind(&storeWithHandler);
178 {
179 GateRef ret = StoreICWithHandler(glue_, receiver_, receiver_, value_, *cachedHandler);
180 result->WriteVariable(ret);
181 Branch(TaggedIsHole(ret), slowPath_, success_);
182 }
183 }
184
TryLoadGlobalICByName(Variable * result,Label * tryFastPath,Label * slowPath,Label * success)185 void ICStubBuilder::TryLoadGlobalICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success)
186 {
187 auto env = GetEnvironment();
188 Label tryIC(env);
189
190 SetLabels(tryFastPath, slowPath, success);
191 Branch(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC);
192 Bind(&tryIC);
193 {
194 GateRef handler = GetValueFromTaggedArray(profileTypeInfo_, slotId_);
195 Label isHeapObject(env);
196 Branch(TaggedIsHeapObject(handler), &isHeapObject, slowPath_);
197 Bind(&isHeapObject);
198 {
199 GateRef ret = LoadGlobal(handler);
200 result->WriteVariable(ret);
201 Branch(TaggedIsHole(ret), slowPath_, success_);
202 }
203 }
204 }
205
TryStoreGlobalICByName(Variable * result,Label * tryFastPath,Label * slowPath,Label * success)206 void ICStubBuilder::TryStoreGlobalICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success)
207 {
208 auto env = GetEnvironment();
209 Label tryIC(env);
210
211 SetLabels(tryFastPath, slowPath, success);
212 Branch(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC);
213 Bind(&tryIC);
214 {
215 GateRef handler = GetValueFromTaggedArray(profileTypeInfo_, slotId_);
216 Label isHeapObject(env);
217 Branch(TaggedIsHeapObject(handler), &isHeapObject, slowPath_);
218 Bind(&isHeapObject);
219 {
220 GateRef ret = StoreGlobal(glue_, value_, handler);
221 result->WriteVariable(ret);
222 Branch(TaggedIsHole(ret), slowPath_, success_);
223 }
224 }
225 }
226 } // namespace panda::ecmascript::kungfu