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