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,ProfileOperation callback)99 void ICStubBuilder::LoadICByName(
100 Variable *result, Label *tryFastPath, Label *slowPath, Label *success, ProfileOperation callback)
101 {
102 auto env = GetEnvironment();
103 Label loadWithHandler(env);
104
105 SetLabels(tryFastPath, slowPath, success);
106 GateRef secondValue = GetValueFromTaggedArray(
107 profileTypeInfo_, Int32Add(slotId_, Int32(1)));
108 DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue);
109 NamedICAccessor(&cachedHandler, &loadWithHandler);
110 Bind(&loadWithHandler);
111 {
112 GateRef ret = LoadICWithHandler(glue_, receiver_, receiver_, *cachedHandler, callback);
113 result->WriteVariable(ret);
114 Branch(TaggedIsHole(ret), slowPath_, success_);
115 }
116 }
117
StoreICByName(Variable * result,Label * tryFastPath,Label * slowPath,Label * success)118 void ICStubBuilder::StoreICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success)
119 {
120 auto env = GetEnvironment();
121 Label storeWithHandler(env);
122
123 SetLabels(tryFastPath, slowPath, success);
124 GateRef secondValue = GetValueFromTaggedArray(
125 profileTypeInfo_, Int32Add(slotId_, Int32(1)));
126 DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue);
127 NamedICAccessor(&cachedHandler, &storeWithHandler);
128 Bind(&storeWithHandler);
129 {
130 GateRef ret = StoreICWithHandler(glue_, receiver_, receiver_, value_, *cachedHandler, callback_);
131 result->WriteVariable(ret);
132 Branch(TaggedIsHole(ret), slowPath_, success_);
133 }
134 }
135
LoadICByValue(Variable * result,Label * tryFastPath,Label * slowPath,Label * success,ProfileOperation callback)136 void ICStubBuilder::LoadICByValue(
137 Variable *result, Label *tryFastPath, Label *slowPath, Label *success, ProfileOperation callback)
138 {
139 auto env = GetEnvironment();
140 Label loadWithHandler(env);
141 Label loadElement(env);
142
143 SetLabels(tryFastPath, slowPath, success);
144 GateRef secondValue = GetValueFromTaggedArray(
145 profileTypeInfo_, Int32Add(slotId_, Int32(1)));
146 DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue);
147 ValuedICAccessor(&cachedHandler, &loadWithHandler, &loadElement);
148 Bind(&loadElement);
149 {
150 GateRef ret = LoadElement(glue_, receiver_, propKey_, callback);
151 result->WriteVariable(ret);
152 Branch(TaggedIsHole(ret), slowPath_, success_);
153 }
154 Bind(&loadWithHandler);
155 {
156 GateRef ret = LoadICWithHandler(glue_, receiver_, receiver_, *cachedHandler, callback);
157 result->WriteVariable(ret);
158 Branch(TaggedIsHole(ret), slowPath_, success_);
159 }
160 }
161
StoreICByValue(Variable * result,Label * tryFastPath,Label * slowPath,Label * success)162 void ICStubBuilder::StoreICByValue(Variable* result, Label* tryFastPath, Label *slowPath, Label *success)
163 {
164 auto env = GetEnvironment();
165 Label storeWithHandler(env);
166 Label storeElement(env);
167
168 SetLabels(tryFastPath, slowPath, success);
169 GateRef secondValue = GetValueFromTaggedArray(
170 profileTypeInfo_, Int32Add(slotId_, Int32(1)));
171 DEFVARIABLE(cachedHandler, VariableType::JS_ANY(), secondValue);
172 ValuedICAccessor(&cachedHandler, &storeWithHandler, &storeElement);
173 Bind(&storeElement);
174 {
175 GateRef ret = ICStoreElement(glue_, receiver_, propKey_, value_, secondValue, callback_);
176 result->WriteVariable(ret);
177 Branch(TaggedIsHole(ret), slowPath_, success_);
178 }
179 Bind(&storeWithHandler);
180 {
181 GateRef ret = StoreICWithHandler(glue_, receiver_, receiver_, value_, *cachedHandler, callback_);
182 result->WriteVariable(ret);
183 Branch(TaggedIsHole(ret), slowPath_, success_);
184 }
185 }
186
TryLoadGlobalICByName(Variable * result,Label * tryFastPath,Label * slowPath,Label * success)187 void ICStubBuilder::TryLoadGlobalICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success)
188 {
189 auto env = GetEnvironment();
190 Label tryIC(env);
191
192 SetLabels(tryFastPath, slowPath, success);
193 Branch(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC);
194 Bind(&tryIC);
195 {
196 GateRef handler = GetValueFromTaggedArray(profileTypeInfo_, slotId_);
197 Label isHeapObject(env);
198 Branch(TaggedIsHeapObject(handler), &isHeapObject, slowPath_);
199 Bind(&isHeapObject);
200 {
201 GateRef ret = LoadGlobal(handler);
202 result->WriteVariable(ret);
203 Branch(TaggedIsHole(ret), slowPath_, success_);
204 }
205 }
206 }
207
TryStoreGlobalICByName(Variable * result,Label * tryFastPath,Label * slowPath,Label * success)208 void ICStubBuilder::TryStoreGlobalICByName(Variable* result, Label* tryFastPath, Label *slowPath, Label *success)
209 {
210 auto env = GetEnvironment();
211 Label tryIC(env);
212
213 SetLabels(tryFastPath, slowPath, success);
214 Branch(TaggedIsUndefined(profileTypeInfo_), tryFastPath_, &tryIC);
215 Bind(&tryIC);
216 {
217 GateRef handler = GetValueFromTaggedArray(profileTypeInfo_, slotId_);
218 Label isHeapObject(env);
219 Branch(TaggedIsHeapObject(handler), &isHeapObject, slowPath_);
220 Bind(&isHeapObject);
221 {
222 GateRef ret = StoreGlobal(glue_, value_, handler);
223 result->WriteVariable(ret);
224 Branch(TaggedIsHole(ret), slowPath_, success_);
225 }
226 }
227 }
228 } // namespace panda::ecmascript::kungfu
229