• 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 #ifndef ECMASCRIPT_COMPILER_HCR_CIRCUIT_BUILDER_H
17 #define ECMASCRIPT_COMPILER_HCR_CIRCUIT_BUILDER_H
18 
19 #include "ecmascript/compiler/circuit_builder.h"
20 #include "ecmascript/mem/region.h"
21 #include "ecmascript/method.h"
22 
23 namespace panda::ecmascript::kungfu {
24 
IsSpecial(GateRef x,JSTaggedType type)25 GateRef CircuitBuilder::IsSpecial(GateRef x, JSTaggedType type)
26 {
27     auto specialValue = circuit_->GetConstantGate(
28         MachineType::I64, type, GateType::TaggedValue());
29 
30     return Equal(x, specialValue);
31 }
32 
IsJSHClass(GateRef obj)33 inline GateRef CircuitBuilder::IsJSHClass(GateRef obj)
34 {
35     return Int32Equal(GetObjectType(LoadHClass(obj)), Int32(static_cast<int32_t>(JSType::HCLASS)));
36 }
37 
IsJSFunction(GateRef obj)38 inline GateRef CircuitBuilder::IsJSFunction(GateRef obj)
39 {
40     GateRef objectType = GetObjectType(LoadHClass(obj));
41     GateRef greater = Int32GreaterThanOrEqual(objectType,
42         Int32(static_cast<int32_t>(JSType::JS_FUNCTION_FIRST)));
43     GateRef less = Int32LessThanOrEqual(objectType,
44         Int32(static_cast<int32_t>(JSType::JS_FUNCTION_LAST)));
45     return BoolAnd(greater, less);
46 }
47 
IsJsType(GateRef obj,JSType type)48 GateRef CircuitBuilder::IsJsType(GateRef obj, JSType type)
49 {
50     GateRef objectType = GetObjectType(LoadHClass(obj));
51     return Equal(objectType, Int32(static_cast<int32_t>(type)));
52 }
53 
IsJSObject(GateRef obj)54 GateRef CircuitBuilder::IsJSObject(GateRef obj)
55 {
56     GateRef objectType = GetObjectType(LoadHClass(obj));
57     auto ret = BoolAnd(
58         Int32LessThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT_LAST))),
59         Int32GreaterThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT_FIRST))));
60     return LogicAnd(TaggedIsHeapObject(obj), ret);
61 }
62 
IsCallableFromBitField(GateRef bitfield)63 GateRef CircuitBuilder::IsCallableFromBitField(GateRef bitfield)
64 {
65     return NotEqual(
66         Int32And(Int32LSR(bitfield, Int32(JSHClass::CallableBit::START_BIT)),
67             Int32((1LU << JSHClass::CallableBit::SIZE) - 1)),
68         Int32(0));
69 }
70 
IsCallable(GateRef obj)71 GateRef CircuitBuilder::IsCallable(GateRef obj)
72 {
73     GateRef hClass = LoadHClass(obj);
74     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
75     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
76     return IsCallableFromBitField(bitfield);
77 }
78 
IsProtoTypeHClass(GateRef hClass)79 GateRef CircuitBuilder::IsProtoTypeHClass(GateRef hClass)
80 {
81     GateRef bitfield = LoadConstOffset(VariableType::INT32(), hClass, JSHClass::BIT_FIELD_OFFSET);
82     return TruncInt32ToInt1(Int32And(Int32LSR(bitfield,
83         Int32(JSHClass::IsPrototypeBit::START_BIT)),
84         Int32((1LU << JSHClass::IsPrototypeBit::SIZE) - 1)));
85 }
86 
IsJsProxy(GateRef obj)87 GateRef CircuitBuilder::IsJsProxy(GateRef obj)
88 {
89     GateRef objectType = GetObjectType(LoadHClass(obj));
90     return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_PROXY)));
91 }
92 
IsTreeString(GateRef obj)93 GateRef CircuitBuilder::IsTreeString(GateRef obj)
94 {
95     GateRef objectType = GetObjectType(LoadHClass(obj));
96     return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::TREE_STRING)));
97 }
98 
IsSlicedString(GateRef obj)99 GateRef CircuitBuilder::IsSlicedString(GateRef obj)
100 {
101     GateRef objectType = GetObjectType(LoadHClass(obj));
102     return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::SLICED_STRING)));
103 }
104 
IsLineString(GateRef obj)105 GateRef CircuitBuilder::IsLineString(GateRef obj)
106 {
107     GateRef objectType = GetObjectType(LoadHClass(obj));
108     return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::LINE_STRING)));
109 }
110 
IsConstantString(GateRef obj)111 GateRef CircuitBuilder::IsConstantString(GateRef obj)
112 {
113     GateRef objectType = GetObjectType(LoadHClass(obj));
114     return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::CONSTANT_STRING)));
115 }
116 
ComputeSizeUtf8(GateRef length)117 GateRef CircuitBuilder::ComputeSizeUtf8(GateRef length)
118 {
119     return PtrAdd(IntPtr(LineEcmaString::DATA_OFFSET), length);
120 }
121 
ComputeSizeUtf16(GateRef length)122 GateRef CircuitBuilder::ComputeSizeUtf16(GateRef length)
123 {
124     return PtrAdd(IntPtr(LineEcmaString::DATA_OFFSET), PtrMul(length, IntPtr(sizeof(uint16_t))));
125 }
126 
AlignUp(GateRef x,GateRef alignment)127 GateRef CircuitBuilder::AlignUp(GateRef x, GateRef alignment)
128 {
129     GateRef x1 = PtrAdd(x, PtrSub(alignment, IntPtr(1)));
130     return IntPtrAnd(x1, IntPtrNot(PtrSub(alignment, IntPtr(1))));
131 }
132 
IsDictionaryMode(GateRef object)133 inline GateRef CircuitBuilder::IsDictionaryMode(GateRef object)
134 {
135     GateRef type = GetObjectType(LoadHClass(object));
136     return Int32Equal(type, Int32(static_cast<int32_t>(JSType::TAGGED_DICTIONARY)));
137 }
138 
IsStableArguments(GateRef hClass)139 GateRef CircuitBuilder::IsStableArguments(GateRef hClass)
140 {
141     GateRef objectType = GetObjectType(hClass);
142     GateRef isJsArguments = Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_ARGUMENTS)));
143     GateRef isStableElements = IsStableElements(hClass);
144     return BoolAnd(isStableElements, isJsArguments);
145 }
146 
IsStableArray(GateRef hClass)147 GateRef CircuitBuilder::IsStableArray(GateRef hClass)
148 {
149     GateRef objectType = GetObjectType(hClass);
150     GateRef isJsArray = Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_ARRAY)));
151     GateRef isStableElements = IsStableElements(hClass);
152     return BoolAnd(isStableElements, isJsArray);
153 }
154 
IsAOTLiteralInfo(GateRef x)155 GateRef CircuitBuilder::IsAOTLiteralInfo(GateRef x)
156 {
157     GateRef isHeapObj = TaggedIsHeapObject(x);
158     GateRef objType = GetObjectType(LoadHClass(x));
159     GateRef isAOTLiteralInfoObj = Equal(objType,
160         Int32(static_cast<int32_t>(JSType::AOT_LITERAL_INFO)));
161     return LogicAnd(isHeapObj, isAOTLiteralInfoObj);
162 }
163 
LoadHClass(GateRef object)164 GateRef CircuitBuilder::LoadHClass(GateRef object)
165 {
166     GateRef offset = IntPtr(TaggedObject::HCLASS_OFFSET);
167     return Load(VariableType::JS_POINTER(), object, offset);
168 }
169 
LoadHClassByConstOffset(GateRef object)170 GateRef CircuitBuilder::LoadHClassByConstOffset(GateRef object)
171 {
172     return LoadConstOffset(VariableType::JS_POINTER(), object, TaggedObject::HCLASS_OFFSET);
173 }
174 
LoadPrototype(GateRef hclass)175 GateRef CircuitBuilder::LoadPrototype(GateRef hclass)
176 {
177     return LoadConstOffset(VariableType::JS_POINTER(), hclass, JSHClass::PROTOTYPE_OFFSET);
178 }
179 
LoadPrototypeHClass(GateRef object)180 GateRef CircuitBuilder::LoadPrototypeHClass(GateRef object)
181 {
182     GateRef objectHClass = LoadHClassByConstOffset(object);
183     GateRef objectPrototype = LoadPrototype(objectHClass);
184     return LoadHClass(objectPrototype);
185 }
186 
GetObjectSizeFromHClass(GateRef hClass)187 GateRef CircuitBuilder::GetObjectSizeFromHClass(GateRef hClass)
188 {
189     // NOTE: check for special case of string and TAGGED_ARRAY
190     GateRef bitfield = Load(VariableType::INT32(), hClass, IntPtr(JSHClass::BIT_FIELD1_OFFSET));
191     GateRef objectSizeInWords = Int32And(Int32LSR(bitfield,
192         Int32(JSHClass::ObjectSizeInWordsBits::START_BIT)),
193         Int32((1LU << JSHClass::ObjectSizeInWordsBits::SIZE) - 1));
194     return PtrMul(ZExtInt32ToPtr(objectSizeInWords), IntPtr(JSTaggedValue::TaggedTypeSize()));
195 }
196 
IsDictionaryModeByHClass(GateRef hClass)197 GateRef CircuitBuilder::IsDictionaryModeByHClass(GateRef hClass)
198 {
199     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
200     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
201     return NotEqual(Int32And(Int32LSR(bitfield,
202         Int32(JSHClass::IsDictionaryBit::START_BIT)),
203         Int32((1LU << JSHClass::IsDictionaryBit::SIZE) - 1)),
204         Int32(0));
205 }
206 
StoreHClass(GateRef glue,GateRef object,GateRef hClass)207 void CircuitBuilder::StoreHClass(GateRef glue, GateRef object, GateRef hClass)
208 {
209     Store(VariableType::JS_POINTER(), glue, object, IntPtr(TaggedObject::HCLASS_OFFSET), hClass);
210 }
211 
StorePrototype(GateRef glue,GateRef hclass,GateRef prototype)212 void CircuitBuilder::StorePrototype(GateRef glue, GateRef hclass, GateRef prototype)
213 {
214     Store(VariableType::JS_POINTER(), glue, hclass, IntPtr(JSHClass::PROTOTYPE_OFFSET), prototype);
215 }
216 
GetObjectType(GateRef hClass)217 GateRef CircuitBuilder::GetObjectType(GateRef hClass)
218 {
219     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
220     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
221     return Int32And(bitfield, Int32((1LU << JSHClass::ObjectTypeBits::SIZE) - 1));
222 }
223 
CanFastCall(GateRef jsFunc)224 inline GateRef CircuitBuilder::CanFastCall(GateRef jsFunc)
225 {
226     GateRef method = GetMethodFromFunction(jsFunc);
227     return CanFastCallWithMethod(method);
228 }
229 
CanFastCallWithMethod(GateRef method)230 inline GateRef CircuitBuilder::CanFastCallWithMethod(GateRef method)
231 {
232     GateRef callFieldOffset = IntPtr(Method::CALL_FIELD_OFFSET);
233     GateRef callfield = Load(VariableType::INT64(), method, callFieldOffset);
234     return Int64NotEqual(
235         Int64And(
236             Int64LSR(callfield, Int64(MethodLiteral::IsFastCallBit::START_BIT)),
237             Int64((1LU << MethodLiteral::IsFastCallBit::SIZE) - 1)),
238         Int64(0));
239 }
240 
GetElementsKindByHClass(GateRef hClass)241 GateRef CircuitBuilder::GetElementsKindByHClass(GateRef hClass)
242 {
243     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
244     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
245     return Int32And(Int32LSR(bitfield,
246         Int32(JSHClass::ElementsKindBits::START_BIT)),
247         Int32((1LLU << JSHClass::ElementsKindBits::SIZE) - 1));
248 }
249 
HasConstructorByHClass(GateRef hClass)250 GateRef CircuitBuilder::HasConstructorByHClass(GateRef hClass)
251 {
252     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
253     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
254     return NotEqual(Int32And(Int32LSR(bitfield,
255         Int32(JSHClass::HasConstructorBits::START_BIT)),
256         Int32((1LU << JSHClass::HasConstructorBits::SIZE) - 1)),
257         Int32(0));
258 }
259 
IsDictionaryElement(GateRef hClass)260 GateRef CircuitBuilder::IsDictionaryElement(GateRef hClass)
261 {
262     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
263     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
264     return NotEqual(Int32And(Int32LSR(bitfield,
265         Int32(JSHClass::DictionaryElementBits::START_BIT)),
266         Int32((1LU << JSHClass::DictionaryElementBits::SIZE) - 1)),
267         Int32(0));
268 }
269 
IsStableElements(GateRef hClass)270 GateRef CircuitBuilder::IsStableElements(GateRef hClass)
271 {
272     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
273     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
274     return NotEqual(Int32And(Int32LSR(bitfield,
275         Int32(JSHClass::IsStableElementsBit::START_BIT)),
276         Int32((1LU << JSHClass::IsStableElementsBit::SIZE) - 1)),
277         Int32(0));
278 }
279 
HasConstructor(GateRef object)280 GateRef CircuitBuilder::HasConstructor(GateRef object)
281 {
282     GateRef hClass = LoadHClass(object);
283     return HasConstructorByHClass(hClass);
284 }
285 
IsConstructor(GateRef object)286 GateRef CircuitBuilder::IsConstructor(GateRef object)
287 {
288     GateRef hClass = LoadHClass(object);
289     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
290     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
291     // decode
292     return Int32NotEqual(
293         Int32And(Int32LSR(bitfield, Int32(JSHClass::ConstructorBit::START_BIT)),
294                  Int32((1LU << JSHClass::ConstructorBit::SIZE) - 1)),
295         Int32(0));
296 }
297 
IsClassConstructor(GateRef object)298 GateRef CircuitBuilder::IsClassConstructor(GateRef object)
299 {
300     GateRef hClass = LoadHClass(object);
301     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
302     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
303     return IsClassConstructorWithBitField(bitfield);
304 }
305 
IsClassConstructorWithBitField(GateRef bitfield)306 GateRef CircuitBuilder::IsClassConstructorWithBitField(GateRef bitfield)
307 {
308     auto classBitMask = 1LU << JSHClass::IsClassConstructorOrPrototypeBit::START_BIT;
309     auto ctorBitMask = 1LU << JSHClass::ConstructorBit::START_BIT;
310     auto mask = Int32(classBitMask | ctorBitMask);
311     auto classCtor = Int32And(bitfield, mask);
312     return Int32Equal(classCtor, mask);
313 }
314 
IsExtensible(GateRef object)315 GateRef CircuitBuilder::IsExtensible(GateRef object)
316 {
317     GateRef hClass = LoadHClass(object);
318     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
319     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
320     return NotEqual(Int32And(Int32LSR(bitfield,
321         Int32(JSHClass::ExtensibleBit::START_BIT)),
322         Int32((1LU << JSHClass::ExtensibleBit::SIZE) - 1)),
323         Int32(0));
324 }
325 
IsClassPrototype(GateRef object)326 GateRef CircuitBuilder::IsClassPrototype(GateRef object)
327 {
328     GateRef hClass = LoadHClass(object);
329     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
330     GateRef bitfield = Load(VariableType::INT32(), hClass, bitfieldOffset);
331     // decode
332     return IsClassPrototypeWithBitField(bitfield);
333 }
334 
IsClassPrototypeWithBitField(GateRef bitfield)335 GateRef CircuitBuilder::IsClassPrototypeWithBitField(GateRef bitfield)
336 {
337     auto classBitMask = 1LU << JSHClass::IsClassConstructorOrPrototypeBit::START_BIT;
338     auto ptBitMask = 1LU << JSHClass::IsPrototypeBit::START_BIT;
339     auto mask = Int32(classBitMask | ptBitMask);
340     auto classPt = Int32And(bitfield, mask);
341     return Int32Equal(classPt, mask);
342 }
343 
CreateWeakRef(GateRef x)344 GateRef CircuitBuilder::CreateWeakRef(GateRef x)
345 {
346     return PtrAdd(x, IntPtr(JSTaggedValue::TAG_WEAK));
347 }
348 
LoadObjectFromWeakRef(GateRef x)349 GateRef CircuitBuilder::LoadObjectFromWeakRef(GateRef x)
350 {
351     return PtrAdd(x, IntPtr(-JSTaggedValue::TAG_WEAK));
352 }
353 
354 // ctor is base but not builtin
IsBase(GateRef ctor)355 inline GateRef CircuitBuilder::IsBase(GateRef ctor)
356 {
357     GateRef method = GetMethodFromFunction(ctor);
358     GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
359     GateRef bitfield = Load(VariableType::INT32(), method, extraLiteralInfoOffset);
360 
361     GateRef kind = Int32And(Int32LSR(bitfield, Int32(MethodLiteral::FunctionKindBits::START_BIT)),
362                             Int32((1LU << MethodLiteral::FunctionKindBits::SIZE) - 1));
363     return Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(FunctionKind::CLASS_CONSTRUCTOR)));
364 }
365 
GetMethodId(GateRef func)366 inline GateRef CircuitBuilder::GetMethodId(GateRef func)
367 {
368     GateRef method = GetMethodFromFunction(func);
369     GateRef literalInfoOffset = IntPtr(Method::LITERAL_INFO_OFFSET);
370     GateRef literalInfo = Load(VariableType::INT64(), method, literalInfoOffset);
371     GateRef methodId = Int64And(Int64LSR(literalInfo, Int64(MethodLiteral::MethodIdBits::START_BIT)),
372         Int64((1LLU << MethodLiteral::MethodIdBits::SIZE) - 1));
373     return methodId;
374 }
375 
GetBuiltinsId(GateRef func)376 inline GateRef CircuitBuilder::GetBuiltinsId(GateRef func)
377 {
378     GateRef method = GetMethodFromFunction(func);
379     GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
380     GateRef extraLiteralInfo = Load(VariableType::INT64(), method, extraLiteralInfoOffset);
381     GateRef builtinsId = Int64And(Int64LSR(extraLiteralInfo, Int64(MethodLiteral::BuiltinIdBits::START_BIT)),
382         Int64((1LLU << MethodLiteral::BuiltinIdBits::SIZE) - 1));
383     return builtinsId;
384 }
385 }
386 #endif  // ECMASCRIPT_COMPILER_HCR_CIRCUIT_BUILDER_H
387