• 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_helper.h"
20 #include "ecmascript/mem/region.h"
21 #include "ecmascript/js_function.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 glue,GateRef obj)33 inline GateRef CircuitBuilder::IsJSHClass(GateRef glue, GateRef obj)
34 {
35     return Int32Equal(GetObjectType(LoadHClass(glue, obj)), Int32(static_cast<int32_t>(JSType::HCLASS)));
36 }
37 
IsJSFunction(GateRef glue,GateRef obj)38 inline GateRef CircuitBuilder::IsJSFunction(GateRef glue, GateRef obj)
39 {
40     GateRef objectType = GetObjectType(LoadHClass(glue, 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 BitAnd(greater, less);
46 }
47 
IsJsType(GateRef glue,GateRef obj,JSType type)48 GateRef CircuitBuilder::IsJsType(GateRef glue, GateRef obj, JSType type)
49 {
50     GateRef objectType = GetObjectType(LoadHClass(glue, obj));
51     return Equal(objectType, Int32(static_cast<int32_t>(type)));
52 }
53 
IsJSObject(GateRef glue,GateRef obj)54 GateRef CircuitBuilder::IsJSObject(GateRef glue, GateRef obj)
55 {
56     Label entryPass(env_);
57     SubCfgEntry(&entryPass);
58     DEFVALUE(result, env_, VariableType::BOOL(), False());
59     Label heapObj(env_);
60     Label exit(env_);
61     GateRef isHeapObject = TaggedIsHeapObject(obj);
62     BRANCH(isHeapObject, &heapObj, &exit);
63     Bind(&heapObj);
64     {
65         GateRef objectType = GetObjectType(LoadHClass(glue, obj));
66         result = BitAnd(
67             Int32LessThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT_LAST))),
68             Int32GreaterThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::JS_OBJECT_FIRST))));
69         Jump(&exit);
70     }
71     Bind(&exit);
72     auto ret = *result;
73     SubCfgExit();
74     return ret;
75 }
76 
IsCallableFromBitField(GateRef bitfield)77 GateRef CircuitBuilder::IsCallableFromBitField(GateRef bitfield)
78 {
79     return NotEqual(
80         Int32And(Int32LSR(bitfield, Int32(JSHClass::CallableBit::START_BIT)),
81             Int32((1LU << JSHClass::CallableBit::SIZE) - 1)),
82         Int32(0));
83 }
84 
IsCallable(GateRef glue,GateRef obj)85 GateRef CircuitBuilder::IsCallable(GateRef glue, GateRef obj)
86 {
87     GateRef hClass = LoadHClass(glue, obj);
88     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
89     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset);
90     return IsCallableFromBitField(bitfield);
91 }
92 
AlreadyDeopt(GateRef method)93 GateRef CircuitBuilder::AlreadyDeopt(GateRef method)
94 {
95     GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
96     GateRef extraLiteralInfo = LoadWithoutBarrier(VariableType::INT64(), method, extraLiteralInfoOffset);
97     return AlreadyDeoptFromExtraLiteralInfo(extraLiteralInfo);
98 }
99 
AlreadyDeoptFromExtraLiteralInfo(GateRef callfield)100 GateRef CircuitBuilder::AlreadyDeoptFromExtraLiteralInfo(GateRef callfield)
101 {
102     return NotEqual(Int64And(Int64LSR(callfield, Int64(Method::DeoptTypeBits::START_BIT)),
103                              Int64((1LU << Method::DeoptTypeBits::SIZE) - 1)),
104                     Int64(0));
105 }
106 
IsPrototypeHClass(GateRef hClass)107 GateRef CircuitBuilder::IsPrototypeHClass(GateRef hClass)
108 {
109     GateRef bitfield = LoadConstOffset(VariableType::INT32(), hClass, JSHClass::BIT_FIELD_OFFSET);
110     return TruncInt32ToInt1(Int32And(Int32LSR(bitfield,
111         Int32(JSHClass::IsPrototypeBit::START_BIT)),
112         Int32((1LU << JSHClass::IsPrototypeBit::SIZE) - 1)));
113 }
114 
IsJsProxy(GateRef glue,GateRef obj)115 GateRef CircuitBuilder::IsJsProxy(GateRef glue, GateRef obj)
116 {
117     GateRef objectType = GetObjectType(LoadHClass(glue, obj));
118     return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_PROXY)));
119 }
120 
IsTreeString(GateRef glue,GateRef obj)121 GateRef CircuitBuilder::IsTreeString(GateRef glue, GateRef obj)
122 {
123     GateRef objectType = GetObjectType(LoadHClass(glue, obj));
124     return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::TREE_STRING)));
125 }
126 
IsSlicedString(GateRef glue,GateRef obj)127 GateRef CircuitBuilder::IsSlicedString(GateRef glue, GateRef obj)
128 {
129     GateRef objectType = GetObjectType(LoadHClass(glue, obj));
130     return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::SLICED_STRING)));
131 }
132 
IsLineString(GateRef glue,GateRef obj)133 GateRef CircuitBuilder::IsLineString(GateRef glue, GateRef obj)
134 {
135     GateRef objectType = GetObjectType(LoadHClass(glue, obj));
136     return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::LINE_STRING)));
137 }
138 
ComputeSizeUtf8(GateRef length)139 GateRef CircuitBuilder::ComputeSizeUtf8(GateRef length)
140 {
141     return PtrAdd(IntPtr(LineString::DATA_OFFSET), length);
142 }
143 
ComputeSizeUtf16(GateRef length)144 GateRef CircuitBuilder::ComputeSizeUtf16(GateRef length)
145 {
146     return PtrAdd(IntPtr(LineString::DATA_OFFSET), PtrMul(length, IntPtr(sizeof(uint16_t))));
147 }
148 
AlignUp(GateRef x,GateRef alignment)149 GateRef CircuitBuilder::AlignUp(GateRef x, GateRef alignment)
150 {
151     GateRef x1 = PtrAdd(x, PtrSub(alignment, IntPtr(1)));
152     return IntPtrAnd(x1, IntPtrNot(PtrSub(alignment, IntPtr(1))));
153 }
154 
IsDictionaryMode(GateRef glue,GateRef object)155 inline GateRef CircuitBuilder::IsDictionaryMode(GateRef glue, GateRef object)
156 {
157     GateRef type = GetObjectType(LoadHClass(glue, object));
158     return Int32Equal(type, Int32(static_cast<int32_t>(JSType::TAGGED_DICTIONARY)));
159 }
160 
IsStableArguments(GateRef hClass)161 GateRef CircuitBuilder::IsStableArguments(GateRef hClass)
162 {
163     GateRef objectType = GetObjectType(hClass);
164     GateRef isJsArguments = Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_ARGUMENTS)));
165     GateRef isStableElements = IsStableElements(hClass);
166     return BitAnd(isStableElements, isJsArguments);
167 }
168 
IsStableArray(GateRef hClass)169 GateRef CircuitBuilder::IsStableArray(GateRef hClass)
170 {
171     GateRef objectType = GetObjectType(hClass);
172     GateRef isJsArray = Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_ARRAY)));
173     GateRef isStableElements = IsStableElements(hClass);
174     return BitAnd(isStableElements, isJsArray);
175 }
176 
IsAOTLiteralInfo(GateRef glue,GateRef x)177 GateRef CircuitBuilder::IsAOTLiteralInfo(GateRef glue, GateRef x)
178 {
179     GateRef objType = GetObjectType(LoadHClass(glue, x));
180     GateRef isAOTLiteralInfoObj = Equal(objType,
181         Int32(static_cast<int32_t>(JSType::AOT_LITERAL_INFO)));
182     return isAOTLiteralInfoObj;
183 }
184 
LoadHclassImpl(GateRef glue,GateRef object,int line)185 GateRef CircuitBuilder::LoadHclassImpl([[maybe_unused]] GateRef glue, GateRef object, [[maybe_unused]] int line)
186 {
187     // ReadBarrier is not need for loading hClass as long as it is non-movable
188     GateRef offset = IntPtr(TaggedObject::HCLASS_OFFSET);
189     GateRef addr = PtrAdd(object, offset);
190     VariableType type = VariableType::JS_POINTER();
191     auto label = env_->GetCurrentLabel();
192     auto depend = label->GetDepend();
193     auto bits = LoadStoreAccessor::ToValue(MemoryAttribute::NoBarrier());
194     GateRef result = GetCircuit()->NewGate(GetCircuit()->LoadHClassOpcode(bits), type.GetMachineType(),
195                                            {depend, glue, addr}, type.GetGateType());
196     label->SetDepend(result);
197     return result;
198 }
199 
LoadHClassByConstOffset(GateRef glue,GateRef object)200 GateRef CircuitBuilder::LoadHClassByConstOffset([[maybe_unused]] GateRef glue, GateRef object)
201 {
202     return LoadHClassByConstOffset(VariableType::JS_POINTER(), object);
203 }
204 
LoadPrototype(GateRef glue,GateRef hclass)205 GateRef CircuitBuilder::LoadPrototype(GateRef glue, GateRef hclass)
206 {
207     CheckHClassFieldInvalidAccess(glue, hclass);
208     return LoadConstOffset(VariableType::JS_POINTER(), hclass, JSHClass::PROTOTYPE_OFFSET);
209 }
210 
LoadProtoChangeMarker(GateRef glue,GateRef hclass)211 GateRef CircuitBuilder::LoadProtoChangeMarker(GateRef glue, GateRef hclass)
212 {
213     CheckHClassFieldInvalidAccess(glue, hclass);
214     return LoadConstOffset(VariableType::JS_POINTER(), hclass, JSHClass::PROTO_CHANGE_MARKER_OFFSET);
215 }
216 
LoadPrototypeHClass(GateRef glue,GateRef object)217 GateRef CircuitBuilder::LoadPrototypeHClass(GateRef glue, GateRef object)
218 {
219     GateRef objectHClass = LoadHClassByConstOffset(glue, object);
220     GateRef objectPrototype = LoadPrototype(glue, objectHClass);
221     return LoadHClass(glue, objectPrototype);
222 }
223 
LoadPrototypeOfPrototypeHClass(GateRef glue,GateRef object)224 GateRef CircuitBuilder::LoadPrototypeOfPrototypeHClass(GateRef glue, GateRef object)
225 {
226     GateRef objectHClass = LoadHClassByConstOffset(glue, object);
227     GateRef objectPrototype = LoadPrototype(glue, objectHClass);
228     GateRef objectPrototypeHClass = LoadHClassByConstOffset(glue, objectPrototype);
229     GateRef objectPrototypeOfPrototype = LoadPrototype(glue, objectPrototypeHClass);
230     return LoadHClass(glue, objectPrototypeOfPrototype);
231 }
232 
GetEnumCacheKindFromEnumCache(GateRef enumCache)233 GateRef CircuitBuilder::GetEnumCacheKindFromEnumCache(GateRef enumCache)
234 {
235     GateRef enumCacheKind = LoadWithoutBarrier(VariableType::INT32(), enumCache,
236                                                IntPtr(EnumCache::ENUM_CACHE_KIND_OFFSET));
237     return enumCacheKind;
238 }
239 
GetEnumCacheOwnFromEnumCache(GateRef glue,GateRef enumCache)240 GateRef CircuitBuilder::GetEnumCacheOwnFromEnumCache(GateRef glue, GateRef enumCache)
241 {
242     GateRef enumCacheOwn = Load(VariableType::JS_ANY(), glue, enumCache,
243         IntPtr(EnumCache::ENUM_CACHE_OWN_OFFSET));
244     return enumCacheOwn;
245 }
246 
GetEnumCacheAllFromEnumCache(GateRef glue,GateRef enumCache)247 GateRef CircuitBuilder::GetEnumCacheAllFromEnumCache(GateRef glue, GateRef enumCache)
248 {
249     GateRef enumCacheAll = Load(VariableType::JS_ANY(), glue, enumCache, IntPtr(EnumCache::ENUM_CACHE_ALL_OFFSET));
250     return enumCacheAll;
251 }
252 
GetProtoChainInfoEnumCacheFromEnumCache(GateRef glue,GateRef enumCache)253 GateRef CircuitBuilder::GetProtoChainInfoEnumCacheFromEnumCache(GateRef glue, GateRef enumCache)
254 {
255     GateRef protoChainInfoEnumCache = Load(VariableType::JS_ANY(), glue, enumCache,
256         IntPtr(EnumCache::PROTO_CHAIN_INFO_ENUM_CACHE_OFFSET));
257     return protoChainInfoEnumCache;
258 }
259 
GetObjectSizeFromHClass(GateRef hClass)260 GateRef CircuitBuilder::GetObjectSizeFromHClass(GateRef hClass)
261 {
262     // NOTE: check for special case of string and TAGGED_ARRAY
263     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, IntPtr(JSHClass::BIT_FIELD1_OFFSET));
264     GateRef objectSizeInWords = Int32And(Int32LSR(bitfield,
265         Int32(JSHClass::ObjectSizeInWordsBits::START_BIT)),
266         Int32((1LU << JSHClass::ObjectSizeInWordsBits::SIZE) - 1));
267     return PtrMul(ZExtInt32ToPtr(objectSizeInWords), IntPtr(JSTaggedValue::TaggedTypeSize()));
268 }
269 
IsDictionaryModeByHClass(GateRef hClass)270 GateRef CircuitBuilder::IsDictionaryModeByHClass(GateRef hClass)
271 {
272     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
273     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset);
274     return NotEqual(Int32And(Int32LSR(bitfield,
275         Int32(JSHClass::IsDictionaryBit::START_BIT)),
276         Int32((1LU << JSHClass::IsDictionaryBit::SIZE) - 1)),
277         Int32(0));
278 }
279 
StoreHClass(GateRef glue,GateRef object,GateRef hClass,MemoryAttribute mAttr)280 void CircuitBuilder::StoreHClass(GateRef glue, GateRef object, GateRef hClass, MemoryAttribute mAttr)
281 {
282     Store(VariableType::JS_POINTER(), glue, object, IntPtr(TaggedObject::HCLASS_OFFSET), hClass, mAttr);
283 }
284 
TransitionHClass(GateRef glue,GateRef object,GateRef hClass,MemoryAttribute mAttr)285 void CircuitBuilder::TransitionHClass(GateRef glue, GateRef object, GateRef hClass, MemoryAttribute mAttr)
286 {
287     CheckHClassAddrInvalid(glue, hClass);
288     GateRef compValue = TruncInt64ToInt32(TaggedPointerToInt64(hClass));
289     StoreHClass(VariableType::JS_POINTER(), glue, object, IntPtr(TaggedObject::HCLASS_OFFSET), hClass,
290         compValue, mAttr);
291 }
292 
TransitionHClassByConstOffset(GateRef glue,GateRef object,GateRef hClass,MemoryAttribute mAttr)293 void CircuitBuilder::TransitionHClassByConstOffset(GateRef glue, GateRef object, GateRef hClass, MemoryAttribute mAttr)
294 {
295     CheckHClassAddrInvalid(glue, hClass);
296     GateRef compValue = TruncInt64ToInt32(TaggedPointerToInt64(hClass));
297     StoreHClassConstOffset(VariableType::JS_POINTER(), object, hClass, compValue, mAttr);
298 }
299 
StorePrototype(GateRef glue,GateRef hclass,GateRef prototype)300 void CircuitBuilder::StorePrototype(GateRef glue, GateRef hclass, GateRef prototype)
301 {
302     CheckHClassFieldInvalidAccess(glue, hclass);
303     Store(VariableType::JS_POINTER(), glue, hclass, IntPtr(JSHClass::PROTOTYPE_OFFSET), prototype);
304 }
305 
GetObjectType(GateRef hClass)306 GateRef CircuitBuilder::GetObjectType(GateRef hClass)
307 {
308     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
309     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset);
310     return Int32And(bitfield, Int32((1LU << JSHClass::ObjectTypeBits::SIZE) - 1));
311 }
312 
CanFastCall(GateRef jsFunc)313 inline GateRef CircuitBuilder::CanFastCall(GateRef jsFunc)
314 {
315     GateRef bitFieldOffset = IntPtr(JSFunctionBase::BIT_FIELD_OFFSET);
316     GateRef bitField = LoadWithoutBarrier(VariableType::INT32(), jsFunc, bitFieldOffset);
317     return Int32NotEqual(
318         Int32And(
319             Int32LSR(bitField, Int32(JSFunctionBase::IsFastCallBit::START_BIT)),
320             Int32((1LU << JSFunctionBase::IsFastCallBit::SIZE) - 1)),
321         Int32(0));
322 }
323 
GetElementsKindByHClass(GateRef hClass)324 GateRef CircuitBuilder::GetElementsKindByHClass(GateRef hClass)
325 {
326     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
327     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset);
328     return Int32And(Int32LSR(bitfield,
329         Int32(JSHClass::ElementsKindBits::START_BIT)),
330         Int32((1LLU << JSHClass::ElementsKindBits::SIZE) - 1));
331 }
332 
HasConstructorByHClass(GateRef hClass)333 GateRef CircuitBuilder::HasConstructorByHClass(GateRef hClass)
334 {
335     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
336     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset);
337     return NotEqual(Int32And(Int32LSR(bitfield,
338         Int32(JSHClass::HasConstructorBits::START_BIT)),
339         Int32((1LU << JSHClass::HasConstructorBits::SIZE) - 1)),
340         Int32(0));
341 }
342 
IsDictionaryElement(GateRef hClass)343 GateRef CircuitBuilder::IsDictionaryElement(GateRef hClass)
344 {
345     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
346     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset);
347     return NotEqual(Int32And(Int32LSR(bitfield,
348         Int32(JSHClass::DictionaryElementBits::START_BIT)),
349         Int32((1LU << JSHClass::DictionaryElementBits::SIZE) - 1)),
350         Int32(0));
351 }
352 
IsStableElements(GateRef hClass)353 GateRef CircuitBuilder::IsStableElements(GateRef hClass)
354 {
355     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
356     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset);
357     return NotEqual(Int32And(Int32LSR(bitfield,
358         Int32(JSHClass::IsStableElementsBit::START_BIT)),
359         Int32((1LU << JSHClass::IsStableElementsBit::SIZE) - 1)),
360         Int32(0));
361 }
362 
IsStableElements(GateRef hClass,CompilationEnv * compilationEnv)363 GateRef CircuitBuilder::IsStableElements(GateRef hClass, CompilationEnv *compilationEnv)
364 {
365     if (compilationEnv != nullptr && compilationEnv->SupportIntrinsic() && !acc_.IsConstant(hClass)) {
366         auto currentLabel = env_->GetCurrentLabel();
367         auto currentDepend = currentLabel->GetDepend();
368         GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
369         GateRef stableElementsBit = Int32(JSHClass::IsStableElementsBit::START_BIT);
370         GateRef isStableElements = GetCircuit()->NewGate(circuit_->IsStableElementsIntrinsic(),
371             MachineType::I1, { currentDepend, hClass, bitfieldOffset, stableElementsBit }, GateType::NJSValue());
372         currentLabel->SetDepend(isStableElements);
373         return isStableElements;
374     }
375     return IsStableElements(hClass);
376 }
377 
IsJSArrayPrototypeModified(GateRef hClass)378 GateRef CircuitBuilder::IsJSArrayPrototypeModified(GateRef hClass)
379 {
380     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
381     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset);
382     return NotEqual(Int32And(Int32LSR(bitfield,
383         Int32(JSHClass::IsJSArrayPrototypeModifiedBit::START_BIT)),
384         Int32((1LU << JSHClass::IsJSArrayPrototypeModifiedBit::SIZE) - 1)),
385         Int32(0));
386 }
387 
HasConstructor(GateRef glue,GateRef object)388 GateRef CircuitBuilder::HasConstructor(GateRef glue, GateRef object)
389 {
390     GateRef hClass = LoadHClass(glue, object);
391     return HasConstructorByHClass(hClass);
392 }
393 
IsConstructor(GateRef glue,GateRef object)394 GateRef CircuitBuilder::IsConstructor(GateRef glue, GateRef object)
395 {
396     GateRef hClass = LoadHClass(glue, object);
397     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
398     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset);
399     // decode
400     return Int32NotEqual(
401         Int32And(Int32LSR(bitfield, Int32(JSHClass::ConstructorBit::START_BIT)),
402                  Int32((1LU << JSHClass::ConstructorBit::SIZE) - 1)),
403         Int32(0));
404 }
405 
IsClassConstructor(GateRef glue,GateRef object)406 GateRef CircuitBuilder::IsClassConstructor(GateRef glue, GateRef object)
407 {
408     GateRef hClass = LoadHClass(glue, object);
409     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
410     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset);
411     return IsClassConstructorWithBitField(bitfield);
412 }
413 
IsClassConstructorWithBitField(GateRef bitfield)414 GateRef CircuitBuilder::IsClassConstructorWithBitField(GateRef bitfield)
415 {
416     auto classBitMask = 1LU << JSHClass::IsClassConstructorOrPrototypeBit::START_BIT;
417     auto ctorBitMask = 1LU << JSHClass::ConstructorBit::START_BIT;
418     auto mask = Int32(classBitMask | ctorBitMask);
419     auto classCtor = Int32And(bitfield, mask);
420     return Int32Equal(classCtor, mask);
421 }
422 
IsExtensible(GateRef glue,GateRef object)423 GateRef CircuitBuilder::IsExtensible(GateRef glue, GateRef object)
424 {
425     GateRef hClass = LoadHClass(glue, object);
426     GateRef bitfieldOffset = Int32(JSHClass::BIT_FIELD_OFFSET);
427     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset);
428     return NotEqual(Int32And(Int32LSR(bitfield,
429         Int32(JSHClass::ExtensibleBit::START_BIT)),
430         Int32((1LU << JSHClass::ExtensibleBit::SIZE) - 1)),
431         Int32(0));
432 }
433 
IsClassPrototype(GateRef glue,GateRef object)434 GateRef CircuitBuilder::IsClassPrototype(GateRef glue, GateRef object)
435 {
436     GateRef hClass = LoadHClass(glue, object);
437     GateRef bitfieldOffset = IntPtr(JSHClass::BIT_FIELD_OFFSET);
438     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, bitfieldOffset);
439     // decode
440     return IsClassPrototypeWithBitField(bitfield);
441 }
442 
IsClassPrototypeWithBitField(GateRef bitfield)443 GateRef CircuitBuilder::IsClassPrototypeWithBitField(GateRef bitfield)
444 {
445     auto classBitMask = 1LU << JSHClass::IsClassConstructorOrPrototypeBit::START_BIT;
446     auto ptBitMask = 1LU << JSHClass::IsPrototypeBit::START_BIT;
447     auto mask = Int32(classBitMask | ptBitMask);
448     auto classPt = Int32And(bitfield, mask);
449     return Int32Equal(classPt, mask);
450 }
451 
CreateWeakRef(GateRef x)452 GateRef CircuitBuilder::CreateWeakRef(GateRef x)
453 {
454     return PtrAdd(x, IntPtr(JSTaggedValue::TAG_WEAK));
455 }
456 
LoadObjectFromWeakRef(GateRef x)457 GateRef CircuitBuilder::LoadObjectFromWeakRef(GateRef x)
458 {
459     return PtrAdd(x, IntPtr(-JSTaggedValue::TAG_WEAK));
460 }
461 
462 // ctor is base but not builtin
IsBase(GateRef glue,GateRef ctor)463 inline GateRef CircuitBuilder::IsBase(GateRef glue, GateRef ctor)
464 {
465     GateRef method = GetMethodFromFunction(glue, ctor);
466     GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
467     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), method, extraLiteralInfoOffset);
468 
469     GateRef kind = Int32And(Int32LSR(bitfield, Int32(MethodLiteral::FunctionKindBits::START_BIT)),
470                             Int32((1LU << MethodLiteral::FunctionKindBits::SIZE) - 1));
471     return Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(FunctionKind::CLASS_CONSTRUCTOR)));
472 }
473 
IsDerived(GateRef glue,GateRef ctor)474 inline GateRef CircuitBuilder::IsDerived(GateRef glue, GateRef ctor)
475 {
476     GateRef method = GetMethodFromFunction(glue, ctor);
477     GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
478     GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), method, extraLiteralInfoOffset);
479 
480     GateRef kind = Int32And(Int32LSR(bitfield, Int32(MethodLiteral::FunctionKindBits::START_BIT)),
481                             Int32((1LU << MethodLiteral::FunctionKindBits::SIZE) - 1));
482     return Int32Equal(kind, Int32(static_cast<int32_t>(FunctionKind::DERIVED_CONSTRUCTOR)));
483 }
484 
GetMethodId(GateRef glue,GateRef func)485 inline GateRef CircuitBuilder::GetMethodId(GateRef glue, GateRef func)
486 {
487     GateRef method = GetMethodFromFunction(glue, func);
488     GateRef literalInfoOffset = IntPtr(Method::LITERAL_INFO_OFFSET);
489     GateRef literalInfo = LoadWithoutBarrier(VariableType::INT64(), method, literalInfoOffset);
490     GateRef methodId = Int64And(Int64LSR(literalInfo, Int64(MethodLiteral::MethodIdBits::START_BIT)),
491         Int64((1LLU << MethodLiteral::MethodIdBits::SIZE) - 1));
492     return methodId;
493 }
494 
GetBuiltinsId(GateRef glue,GateRef func)495 inline GateRef CircuitBuilder::GetBuiltinsId(GateRef glue, GateRef func)
496 {
497     GateRef method = GetMethodFromFunction(glue, func);
498     GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
499     GateRef extraLiteralInfo = LoadWithoutBarrier(VariableType::INT64(), method, extraLiteralInfoOffset);
500     GateRef builtinsId = Int64And(Int64LSR(extraLiteralInfo, Int64(MethodLiteral::BuiltinIdBits::START_BIT)),
501         Int64((1LLU << MethodLiteral::BuiltinIdBits::SIZE) - 1));
502     return builtinsId;
503 }
504 }
505 #endif  // ECMASCRIPT_COMPILER_HCR_CIRCUIT_BUILDER_H
506