1 /*
2 * Copyright (c) 2021-2024 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 #include "ecmascript/compiler/circuit_builder.h"
17
18 #include "ecmascript/compiler/builtins/builtins_call_signature.h"
19 #include "ecmascript/compiler/circuit_builder-inl.h"
20 #include "ecmascript/compiler/hcr_circuit_builder.h"
21 #include "ecmascript/compiler/lcr_circuit_builder.h"
22 #include "ecmascript/compiler/mcr_circuit_builder.h"
23 #include "ecmascript/compiler/new_object_stub_builder.h"
24 #include "ecmascript/compiler/rt_call_signature.h"
25 #include "ecmascript/compiler/share_gate_meta_data.h"
26 #include "ecmascript/deoptimizer/deoptimizer.h"
27 #include "ecmascript/global_env.h"
28 #include "ecmascript/ic/proto_change_details.h"
29 #include "ecmascript/js_array_iterator.h"
30 #include "ecmascript/js_for_in_iterator.h"
31 #include "ecmascript/js_function.h"
32 #include "ecmascript/js_primitive_ref.h"
33 #include "ecmascript/js_thread.h"
34 #include "ecmascript/jspandafile/program_object.h"
35 #include "ecmascript/lexical_env.h"
36 #include "ecmascript/mem/region.h"
37 #include "ecmascript/message_string.h"
38 #include "ecmascript/method.h"
39 #include "ecmascript/sendable_env.h"
40
41 namespace panda::ecmascript::kungfu {
42
Merge(const std::vector<GateRef> & inList)43 GateRef CircuitBuilder::Merge(const std::vector<GateRef> &inList)
44 {
45 return circuit_->NewGate(circuit_->Merge(inList.size()), inList);
46 }
47
Selector(OpCode opcode,MachineType machineType,GateRef control,const std::vector<GateRef> & values,int valueCounts,VariableType type)48 GateRef CircuitBuilder::Selector(OpCode opcode, MachineType machineType, GateRef control,
49 const std::vector<GateRef> &values, int valueCounts, VariableType type)
50 {
51 std::vector<GateRef> inList;
52 inList.push_back(control);
53 if (values.size() == 0) {
54 for (int i = 0; i < valueCounts; i++) {
55 inList.push_back(Circuit::NullGate());
56 }
57 } else {
58 for (int i = 0; i < valueCounts; i++) {
59 inList.push_back(values[i]);
60 }
61 }
62 ASSERT((opcode == OpCode::VALUE_SELECTOR) || (opcode == OpCode::DEPEND_SELECTOR));
63 const GateMetaData* meta = (opcode == OpCode::DEPEND_SELECTOR) ?
64 circuit_->DependSelector(valueCounts) : circuit_->ValueSelector(valueCounts);
65 return circuit_->NewGate(meta, machineType, inList.size(), inList.data(), type.GetGateType());
66 }
67
Selector(OpCode opcode,GateRef control,const std::vector<GateRef> & values,int valueCounts,VariableType type)68 GateRef CircuitBuilder::Selector(OpCode opcode, GateRef control,
69 const std::vector<GateRef> &values, int valueCounts, VariableType type)
70 {
71 MachineType machineType = (opcode == OpCode::DEPEND_SELECTOR) ?
72 MachineType::NOVALUE : MachineType::FLEX;
73 return Selector(opcode, machineType, control, values, valueCounts, type);
74 }
75
Nop()76 GateRef CircuitBuilder::Nop()
77 {
78 return circuit_->NewGate(circuit_->Nop(), {});
79 }
80
UndefineConstant()81 GateRef CircuitBuilder::UndefineConstant()
82 {
83 auto type = GateType::TaggedValue();
84 return circuit_->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_UNDEFINED, type);
85 }
86
Branch(GateRef state,GateRef condition,uint32_t trueWeight,uint32_t falseWeight,const char * comment)87 GateRef CircuitBuilder::Branch(GateRef state, GateRef condition, uint32_t trueWeight, uint32_t falseWeight,
88 const char* comment)
89 {
90 auto value = BranchAccessor::ToValue(trueWeight, falseWeight);
91 return circuit_->NewGate(circuit_->IfBranch(value), { state, condition }, comment);
92 }
93
SwitchBranch(GateRef state,GateRef index,int caseCounts)94 GateRef CircuitBuilder::SwitchBranch(GateRef state, GateRef index, int caseCounts)
95 {
96 return circuit_->NewGate(circuit_->SwitchBranch(caseCounts), { state, index });
97 }
98
Return(GateRef state,GateRef depend,GateRef value)99 GateRef CircuitBuilder::Return(GateRef state, GateRef depend, GateRef value)
100 {
101 auto returnList = circuit_->GetReturnRoot();
102 return circuit_->NewGate(circuit_->Return(), { state, depend, value, returnList });
103 }
104
ReturnVoid(GateRef state,GateRef depend)105 GateRef CircuitBuilder::ReturnVoid(GateRef state, GateRef depend)
106 {
107 auto returnList = circuit_->GetReturnRoot();
108 return circuit_->NewGate(circuit_->ReturnVoid(), { state, depend, returnList });
109 }
110
Goto(GateRef state)111 GateRef CircuitBuilder::Goto(GateRef state)
112 {
113 return circuit_->NewGate(circuit_->OrdinaryBlock(), { state });
114 }
115
LoopBegin(GateRef state)116 GateRef CircuitBuilder::LoopBegin(GateRef state)
117 {
118 auto nullGate = Circuit::NullGate();
119 return circuit_->NewGate(circuit_->LoopBegin(2), { state, nullGate }); // 2: entry&back
120 }
121
LoopEnd(GateRef state)122 GateRef CircuitBuilder::LoopEnd(GateRef state)
123 {
124 return circuit_->NewGate(circuit_->LoopBack(), { state });
125 }
126
LoopExit(GateRef state)127 GateRef CircuitBuilder::LoopExit(GateRef state)
128 {
129 return circuit_->NewGate(circuit_->LoopExit(), { state });
130 }
131
LoopExitDepend(GateRef state,GateRef depend)132 GateRef CircuitBuilder::LoopExitDepend(GateRef state, GateRef depend)
133 {
134 return circuit_->NewGate(circuit_->LoopExitDepend(), { state, depend });
135 }
136
LoopExitValue(GateRef state,GateRef value)137 GateRef CircuitBuilder::LoopExitValue(GateRef state, GateRef value)
138 {
139 auto machineType = acc_.GetMachineType(value);
140 auto gateType = acc_.GetGateType(value);
141 return circuit_->NewGate(circuit_->LoopExitValue(), machineType, { state, value }, gateType);
142 }
143
IfTrue(GateRef ifBranch)144 GateRef CircuitBuilder::IfTrue(GateRef ifBranch)
145 {
146 return circuit_->NewGate(circuit_->IfTrue(), { ifBranch });
147 }
148
IfFalse(GateRef ifBranch)149 GateRef CircuitBuilder::IfFalse(GateRef ifBranch)
150 {
151 return circuit_->NewGate(circuit_->IfFalse(), { ifBranch });
152 }
153
SwitchCase(GateRef switchBranch,int64_t value)154 GateRef CircuitBuilder::SwitchCase(GateRef switchBranch, int64_t value)
155 {
156 return circuit_->NewGate(circuit_->SwitchCase(value), { switchBranch });
157 }
158
DefaultCase(GateRef switchBranch)159 GateRef CircuitBuilder::DefaultCase(GateRef switchBranch)
160 {
161 return circuit_->NewGate(circuit_->DefaultCase(), { switchBranch });
162 }
163
DependRelay(GateRef state,GateRef depend)164 GateRef CircuitBuilder::DependRelay(GateRef state, GateRef depend)
165 {
166 return circuit_->NewGate(circuit_->DependRelay(), { state, depend });
167 }
168
Arguments(size_t index)169 GateRef CircuitBuilder::Arguments(size_t index)
170 {
171 auto argListOfCircuit = circuit_->GetArgRoot();
172 return GetCircuit()->NewArg(MachineType::I64, index, GateType::NJSValue(), argListOfCircuit);
173 }
174
IsJsCOWArray(GateRef obj)175 GateRef CircuitBuilder::IsJsCOWArray(GateRef obj)
176 {
177 // Elements of JSArray are shared and properties are not yet.
178 GateRef elements = GetElementsArray(obj);
179 GateRef objectType = GetObjectType(LoadHClass(elements));
180 return IsCOWArray(objectType);
181 }
182
IsCOWArray(GateRef objectType)183 GateRef CircuitBuilder::IsCOWArray(GateRef objectType)
184 {
185 return BitOr(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::COW_TAGGED_ARRAY))),
186 Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::COW_MUTANT_TAGGED_ARRAY))));
187 }
188
IsTaggedArray(GateRef object)189 GateRef CircuitBuilder::IsTaggedArray(GateRef object)
190 {
191 GateRef objectType = GetObjectType(LoadHClass(object));
192 return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::TAGGED_ARRAY)));
193 }
194
IsMutantTaggedArray(GateRef objectType)195 GateRef CircuitBuilder::IsMutantTaggedArray(GateRef objectType)
196 {
197 return BitOr(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::MUTANT_TAGGED_ARRAY))),
198 Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::COW_MUTANT_TAGGED_ARRAY))));
199 }
200
GetElementsArray(GateRef object)201 GateRef CircuitBuilder::GetElementsArray(GateRef object)
202 {
203 GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
204 return Load(VariableType::JS_POINTER(), object, elementsOffset);
205 }
206
GetLengthOfTaggedArray(GateRef array)207 GateRef CircuitBuilder::GetLengthOfTaggedArray(GateRef array)
208 {
209 return Load(VariableType::INT32(), array, IntPtr(TaggedArray::LENGTH_OFFSET));
210 }
211
GetLengthOfJSTypedArray(GateRef array)212 GateRef CircuitBuilder::GetLengthOfJSTypedArray(GateRef array)
213 {
214 return Load(VariableType::INT32(), array, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET));
215 }
216
GetDataOfTaggedArray(GateRef array)217 GateRef CircuitBuilder::GetDataOfTaggedArray(GateRef array)
218 {
219 return PtrAdd(array, Int64(TaggedArray::DATA_OFFSET));
220 }
221
GetLengthOfJSArray(GateRef array)222 GateRef CircuitBuilder::GetLengthOfJSArray(GateRef array)
223 {
224 return Load(VariableType::INT32(), array, IntPtr(JSArray::LENGTH_OFFSET));
225 }
226
IsTypedArray(GateRef array)227 GateRef CircuitBuilder::IsTypedArray(GateRef array)
228 {
229 GateRef hclass = LoadHClass(array);
230 GateRef type = GetObjectType(hclass);
231 return BitAnd(Int32GreaterThan(type, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY_FIRST))),
232 Int32GreaterThanOrEqual(Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY_LAST)), type));
233 }
234
Jump(Label * label)235 void CircuitBuilder::Jump(Label *label)
236 {
237 ASSERT(label);
238 auto currentLabel = env_->GetCurrentLabel();
239 auto currentControl = currentLabel->GetControl();
240 auto jump = Goto(currentControl);
241 currentLabel->SetControl(jump);
242 label->AppendPredecessor(currentLabel);
243 label->MergeControl(currentLabel->GetControl());
244 env_->SetCurrentLabel(nullptr);
245 }
246
Branch(GateRef condition,Label * trueLabel,Label * falseLabel,uint32_t trueWeight,uint32_t falseWeight,const char * comment)247 void CircuitBuilder::Branch(GateRef condition, Label *trueLabel, Label *falseLabel,
248 uint32_t trueWeight, uint32_t falseWeight, const char* comment)
249 {
250 auto currentLabel = env_->GetCurrentLabel();
251 auto currentControl = currentLabel->GetControl();
252 GateRef ifBranch = Branch(currentControl, condition, trueWeight, falseWeight, comment);
253 currentLabel->SetControl(ifBranch);
254 GateRef ifTrue = IfTrue(ifBranch);
255 trueLabel->AppendPredecessor(GetCurrentLabel());
256 trueLabel->MergeControl(ifTrue);
257 GateRef ifFalse = IfFalse(ifBranch);
258 falseLabel->AppendPredecessor(GetCurrentLabel());
259 falseLabel->MergeControl(ifFalse);
260 env_->SetCurrentLabel(nullptr);
261 }
262
Switch(GateRef index,Label * defaultLabel,int64_t * keysValue,Label * keysLabel,int numberOfKeys)263 void CircuitBuilder::Switch(GateRef index, Label *defaultLabel, int64_t *keysValue, Label *keysLabel, int numberOfKeys)
264 {
265 auto currentLabel = env_->GetCurrentLabel();
266 auto currentControl = currentLabel->GetControl();
267 GateRef switchBranch = SwitchBranch(currentControl, index, numberOfKeys);
268 currentLabel->SetControl(switchBranch);
269 for (int i = 0; i < numberOfKeys; i++) {
270 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
271 GateRef switchCase = SwitchCase(switchBranch, keysValue[i]);
272 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
273 keysLabel[i].AppendPredecessor(currentLabel);
274 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
275 keysLabel[i].MergeControl(switchCase);
276 }
277
278 GateRef defaultCase = DefaultCase(switchBranch);
279 defaultLabel->AppendPredecessor(currentLabel);
280 defaultLabel->MergeControl(defaultCase);
281 env_->SetCurrentLabel(nullptr);
282 }
283
LoopBegin(Label * loopHead)284 void CircuitBuilder::LoopBegin(Label *loopHead)
285 {
286 ASSERT(loopHead);
287 auto loopControl = LoopBegin(loopHead->GetControl());
288 loopHead->SetControl(loopControl);
289 loopHead->SetPreControl(loopControl);
290 loopHead->Bind();
291 env_->SetCurrentLabel(loopHead);
292 }
293
LoopEnd(Label * loopHead)294 void CircuitBuilder::LoopEnd(Label *loopHead)
295 {
296 ASSERT(loopHead);
297 auto currentLabel = GetCurrentLabel();
298 auto currentControl = currentLabel->GetControl();
299 auto loopend = LoopEnd(currentControl);
300 currentLabel->SetControl(loopend);
301 loopHead->AppendPredecessor(currentLabel);
302 loopHead->MergeControl(loopend);
303 loopHead->Seal();
304 loopHead->MergeAllControl();
305 loopHead->MergeAllDepend();
306 env_->SetCurrentLabel(nullptr);
307 }
308
309 // add loop exit info at begin of label (only support not merge label)
LoopExit(const std::vector<Variable * > & vars,size_t diff)310 void CircuitBuilder::LoopExit(const std::vector<Variable *> &vars, size_t diff)
311 {
312 auto currentLabel = env_->GetCurrentLabel();
313 auto loopExit = currentLabel->GetControl();
314 auto loopExitDepend = currentLabel->GetDepend();
315 std::vector<GateRef> loopExitValues;
316 for (size_t i = 0; i < diff; ++i) {
317 loopExit = LoopExit(loopExit);
318 loopExitDepend = LoopExitDepend(loopExit, loopExitDepend);
319 for (const auto &var : vars) {
320 auto loopExitValue = LoopExitValue(loopExit, var->ReadVariable());
321 var->WriteVariable(loopExitValue);
322 }
323 }
324 currentLabel->SetControl(loopExit);
325 currentLabel->SetDepend(loopExitDepend);
326 }
327
ClearConstantCache(GateRef gate)328 void CircuitBuilder::ClearConstantCache(GateRef gate)
329 {
330 ASSERT(acc_.GetOpCode(gate) == OpCode::CONSTANT);
331 auto machineType = acc_.GetMachineType(gate);
332 auto value = acc_.GetConstantValue(gate);
333 auto gateType = acc_.GetGateType(gate);
334 GetCircuit()->ClearConstantCache(machineType, value, gateType);
335 }
336
DeoptCheck(GateRef condition,GateRef frameState,DeoptType type)337 void CircuitBuilder::DeoptCheck(GateRef condition, GateRef frameState, DeoptType type)
338 {
339 std::string comment = Deoptimizier::DisplayItems(type);
340 auto currentLabel = env_->GetCurrentLabel();
341 auto currentControl = currentLabel->GetControl();
342 auto currentDepend = currentLabel->GetDepend();
343 ASSERT(acc_.GetOpCode(frameState) == OpCode::FRAME_STATE);
344 GateRef deoptCheck = GetCircuit()->NewGate(circuit_->DeoptCheck(),
345 MachineType::I1, { currentControl, currentDepend, condition,
346 frameState, Int64(static_cast<int64_t>(type))}, GateType::NJSValue(), comment.c_str());
347 GateRef trueBB = circuit_->NewGate(circuit_->OrdinaryBlock(), { deoptCheck });
348 auto dependRelay = DependRelay(trueBB, currentDepend);
349 currentLabel->SetControl(trueBB);
350 currentLabel->SetDepend(dependRelay);
351 }
352
GetSuperConstructor(GateRef ctor)353 GateRef CircuitBuilder::GetSuperConstructor(GateRef ctor)
354 {
355 auto currentLabel = env_->GetCurrentLabel();
356 auto currentControl = currentLabel->GetControl();
357 auto currentDepend = currentLabel->GetDepend();
358 auto ret = GetCircuit()->NewGate(circuit_->GetSuperConstructor(), MachineType::ANYVALUE,
359 { currentControl, currentDepend, ctor }, GateType::TaggedValue());
360 currentLabel->SetControl(ret);
361 currentLabel->SetDepend(ret);
362 return ret;
363 }
364
Int8(int8_t val)365 GateRef CircuitBuilder::Int8(int8_t val)
366 {
367 return GetCircuit()->GetConstantGate(MachineType::I8, val, GateType::NJSValue());
368 }
369
Int16(int16_t val)370 GateRef CircuitBuilder::Int16(int16_t val)
371 {
372 return GetCircuit()->GetConstantGate(MachineType::I16, val, GateType::NJSValue());
373 }
374
Int32(int32_t val)375 GateRef CircuitBuilder::Int32(int32_t val)
376 {
377 return GetCircuit()->GetConstantGate(MachineType::I32, static_cast<BitField>(val), GateType::NJSValue());
378 }
379
Int64(int64_t val)380 GateRef CircuitBuilder::Int64(int64_t val)
381 {
382 return GetCircuit()->GetConstantGate(MachineType::I64, val, GateType::NJSValue());
383 }
384
IntPtr(int64_t val)385 GateRef CircuitBuilder::IntPtr(int64_t val)
386 {
387 return GetCircuit()->GetConstantGate(MachineType::ARCH, val, GateType::NJSValue());
388 }
389
StringPtr(std::string_view str)390 GateRef CircuitBuilder::StringPtr(std::string_view str)
391 {
392 return GetCircuit()->GetConstantStringGate(MachineType::ARCH, str, GateType::NJSValue());
393 }
394
RelocatableData(uint64_t val)395 GateRef CircuitBuilder::RelocatableData(uint64_t val)
396 {
397 return GetCircuit()->NewGate(circuit_->RelocatableData(val),
398 MachineType::ARCH, GateType::TaggedValue());
399 }
400
Boolean(bool val)401 GateRef CircuitBuilder::Boolean(bool val)
402 {
403 return GetCircuit()->GetConstantGate(MachineType::I1, val ? 1 : 0, GateType::NJSValue());
404 }
405
Double(double val)406 GateRef CircuitBuilder::Double(double val)
407 {
408 return GetCircuit()->GetConstantGate(MachineType::F64, base::bit_cast<int64_t>(val), GateType::NJSValue());
409 }
410
HoleConstant()411 GateRef CircuitBuilder::HoleConstant()
412 {
413 auto type = GateType::TaggedValue();
414 return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_HOLE, type);
415 }
416
SpecialHoleConstant()417 GateRef CircuitBuilder::SpecialHoleConstant()
418 {
419 auto type = GateType::NJSValue();
420 return GetCircuit()->GetConstantGate(MachineType::I64, base::SPECIAL_HOLE, type);
421 }
422
NullPtrConstant()423 GateRef CircuitBuilder::NullPtrConstant()
424 {
425 auto type = GateType::TaggedValue();
426 return GetCircuit()->GetConstantGate(MachineType::I64, 0u, type);
427 }
428
NullConstant()429 GateRef CircuitBuilder::NullConstant()
430 {
431 auto type = GateType::TaggedValue();
432 return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_NULL, type);
433 }
434
TaggedValueConstant(JSTaggedValue taggedValue)435 GateRef CircuitBuilder::TaggedValueConstant(JSTaggedValue taggedValue)
436 {
437 auto type = GateType::TaggedValue();
438 return GetCircuit()->GetConstantGate(MachineType::I64, taggedValue.GetRawData(), type);
439 }
440
ExceptionConstant()441 GateRef CircuitBuilder::ExceptionConstant()
442 {
443 auto type = GateType::TaggedValue();
444 return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_EXCEPTION, type);
445 }
446
NanValue()447 GateRef CircuitBuilder::NanValue()
448 {
449 return Double(std::numeric_limits<double>::quiet_NaN());
450 }
451
LoadObjectFromConstPool(GateRef constPool,GateRef index)452 GateRef CircuitBuilder::LoadObjectFromConstPool(GateRef constPool, GateRef index)
453 {
454 return GetValueFromTaggedArray(constPool, TruncInt64ToInt32(index));
455 }
456
IsAccessorInternal(GateRef accessor)457 GateRef CircuitBuilder::IsAccessorInternal(GateRef accessor)
458 {
459 return Int32Equal(GetObjectType(LoadHClass(accessor)),
460 Int32(static_cast<int32_t>(JSType::INTERNAL_ACCESSOR)));
461 }
462
AppendFrameArgs(std::vector<GateRef> & args,GateRef hirGate)463 void CircuitBuilder::AppendFrameArgs(std::vector<GateRef> &args, GateRef hirGate)
464 {
465 GateRef frameArgs = acc_.GetFrameArgs(hirGate);
466 if (frameArgs == Circuit::NullGate()) {
467 args.emplace_back(IntPtr(0));
468 } else {
469 args.emplace_back(frameArgs);
470 }
471 }
472
GetGlobalEnv()473 GateRef CircuitBuilder::GetGlobalEnv()
474 {
475 auto currentLabel = env_->GetCurrentLabel();
476 auto currentDepend = currentLabel->GetDepend();
477 auto newGate = GetCircuit()->NewGate(circuit_->GetGlobalEnv(), MachineType::I64,
478 { currentDepend },
479 GateType::AnyType());
480 currentLabel->SetDepend(newGate);
481 return newGate;
482 }
483
GetGlobalEnvObj(GateRef env,size_t index)484 GateRef CircuitBuilder::GetGlobalEnvObj(GateRef env, size_t index)
485 {
486 auto currentLabel = env_->GetCurrentLabel();
487 auto currentDepend = currentLabel->GetDepend();
488 auto newGate = GetCircuit()->NewGate(circuit_->GetGlobalEnvObj(index), MachineType::I64,
489 { currentDepend, env },
490 GateType::AnyType());
491 currentLabel->SetDepend(newGate);
492 return newGate;
493 }
494
GetGlobalEnvObjHClass(GateRef env,size_t index)495 GateRef CircuitBuilder::GetGlobalEnvObjHClass(GateRef env, size_t index)
496 {
497 auto currentLabel = env_->GetCurrentLabel();
498 auto currentDepend = currentLabel->GetDepend();
499 auto newGate = GetCircuit()->NewGate(circuit_->GetGlobalEnvObjHClass(index), MachineType::I64,
500 { currentDepend, env },
501 GateType::AnyType());
502 currentLabel->SetDepend(newGate);
503 return newGate;
504 }
505
GetGlobalConstantValue(ConstantIndex index)506 GateRef CircuitBuilder::GetGlobalConstantValue(ConstantIndex index)
507 {
508 auto currentLabel = env_->GetCurrentLabel();
509 auto currentDepend = currentLabel->GetDepend();
510 auto newGate = GetCircuit()->NewGate(circuit_->GetGlobalConstantValue(static_cast<size_t>(index)),
511 MachineType::I64, { currentDepend }, GateType::AnyType());
512 currentLabel->SetDepend(newGate);
513 return newGate;
514 }
515
HasPendingException(GateRef glue)516 GateRef CircuitBuilder::HasPendingException(GateRef glue)
517 {
518 GateRef exceptionOffset = IntPtr(JSThread::GlueData::GetExceptionOffset(env_->IsArch32Bit()));
519 GateRef exception = Load(VariableType::JS_ANY(), glue, exceptionOffset);
520 return TaggedIsNotHole(exception);
521 }
522
IsUtf8String(GateRef string)523 GateRef CircuitBuilder::IsUtf8String(GateRef string)
524 {
525 // compressedStringsEnabled fixed to true constant
526 GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
527 return Int32Equal(
528 Int32And(len, Int32(EcmaString::STRING_COMPRESSED_BIT)),
529 Int32(EcmaString::STRING_COMPRESSED));
530 }
531
IsUtf16String(GateRef string)532 GateRef CircuitBuilder::IsUtf16String(GateRef string)
533 {
534 // compressedStringsEnabled fixed to true constant
535 GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
536 return Int32Equal(
537 Int32And(len, Int32(EcmaString::STRING_COMPRESSED_BIT)),
538 Int32(EcmaString::STRING_UNCOMPRESSED));
539 }
540
GetGlobalObject(GateRef glue)541 GateRef CircuitBuilder::GetGlobalObject(GateRef glue)
542 {
543 GateRef offset = IntPtr(JSThread::GlueData::GetGlobalObjOffset(cmpCfg_->Is32Bit()));
544 return Load(VariableType::JS_ANY(), glue, offset);
545 }
546
GetMethodFromFunction(GateRef function)547 GateRef CircuitBuilder::GetMethodFromFunction(GateRef function)
548 {
549 GateRef offset = IntPtr(JSFunctionBase::METHOD_OFFSET);
550 return Load(VariableType::JS_POINTER(), function, offset);
551 }
552
GetModuleFromFunction(GateRef function)553 GateRef CircuitBuilder::GetModuleFromFunction(GateRef function)
554 {
555 GateRef offset = IntPtr(JSFunction::ECMA_MODULE_OFFSET);
556 return Load(VariableType::JS_POINTER(), function, offset);
557 }
558
GetSendableEnvFromModule(GateRef module)559 GateRef CircuitBuilder::GetSendableEnvFromModule(GateRef module)
560 {
561 return Load(VariableType::JS_POINTER(), module, IntPtr(SourceTextModule::SENDABLE_ENV_OFFSET));
562 }
563
SetSendableEnvToModule(GateRef glue,GateRef module,GateRef value)564 void CircuitBuilder::SetSendableEnvToModule(GateRef glue, GateRef module, GateRef value)
565 {
566 GateRef offset = IntPtr(SourceTextModule::SENDABLE_ENV_OFFSET);
567 Store(VariableType::JS_POINTER(), glue, module, offset, value);
568 }
569
GetHomeObjectFromFunction(GateRef function)570 GateRef CircuitBuilder::GetHomeObjectFromFunction(GateRef function)
571 {
572 GateRef offset = IntPtr(JSFunction::HOME_OBJECT_OFFSET);
573 return Load(VariableType::JS_POINTER(), function, offset);
574 }
575
GetConstPoolFromFunction(GateRef jsFunc)576 GateRef CircuitBuilder::GetConstPoolFromFunction(GateRef jsFunc)
577 {
578 GateRef method = GetMethodFromFunction(jsFunc);
579 return Load(VariableType::JS_ANY(), method, IntPtr(Method::CONSTANT_POOL_OFFSET));
580 }
581
GetUnsharedConstpoolFromGlue(GateRef glue,GateRef constpool)582 GateRef CircuitBuilder::GetUnsharedConstpoolFromGlue(GateRef glue, GateRef constpool)
583 {
584 GateRef unshareIdx = GetUnsharedConstpoolIndex(constpool);
585 GateRef unshareCpOffset = static_cast<int32_t>(JSThread::GlueData::GetUnSharedConstpoolsOffset(env_->Is32Bit()));
586 GateRef unshareCpAddr = Load(VariableType::NATIVE_POINTER(), glue, IntPtr(unshareCpOffset));
587 return GetUnsharedConstpool(unshareCpAddr, unshareIdx);
588 }
589
GetUnsharedConstpoolIndex(GateRef constpool)590 GateRef CircuitBuilder::GetUnsharedConstpoolIndex(GateRef constpool)
591 {
592 GateRef constPoolSize = GetLengthOfTaggedArray(constpool);
593 GateRef unshareIdx = Int32Sub(constPoolSize, Int32(ConstantPool::UNSHARED_CONSTPOOL_INDEX));
594 return GetValueFromTaggedArray(constpool, unshareIdx);
595 }
596
GetUnsharedConstpool(GateRef arrayAddr,GateRef index)597 GateRef CircuitBuilder::GetUnsharedConstpool(GateRef arrayAddr, GateRef index)
598 {
599 GateRef dataOffset = PtrAdd(arrayAddr,
600 PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()), ZExtInt32ToPtr(TaggedGetInt(index))));
601 return Load(VariableType::JS_ANY(), dataOffset, IntPtr(0));
602 }
603
GetEmptyArray(GateRef glue)604 GateRef CircuitBuilder::GetEmptyArray(GateRef glue)
605 {
606 GateRef gConstAddr = Load(VariableType::JS_ANY(), glue,
607 IntPtr(JSThread::GlueData::GetGlobalConstOffset(env_->Is32Bit())));
608 GateRef offset = GetGlobalConstantOffset(ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
609 return Load(VariableType::JS_ANY(), gConstAddr, offset);
610 }
611
GetPrototypeFromHClass(GateRef hClass)612 GateRef CircuitBuilder::GetPrototypeFromHClass(GateRef hClass)
613 {
614 GateRef protoOffset = IntPtr(JSHClass::PROTOTYPE_OFFSET);
615 return Load(VariableType::JS_ANY(), hClass, protoOffset);
616 }
617
GetEnumCacheFromHClass(GateRef hClass)618 GateRef CircuitBuilder::GetEnumCacheFromHClass(GateRef hClass)
619 {
620 GateRef offset = IntPtr(JSHClass::ENUM_CACHE_OFFSET);
621 return Load(VariableType::JS_ANY(), hClass, offset);
622 }
623
GetProtoChangeMarkerFromHClass(GateRef hClass)624 GateRef CircuitBuilder::GetProtoChangeMarkerFromHClass(GateRef hClass)
625 {
626 GateRef offset = IntPtr(JSHClass::PROTO_CHANGE_MARKER_OFFSET);
627 return Load(VariableType::JS_ANY(), hClass, offset);
628 }
629
GetLengthFromForInIterator(GateRef iter)630 GateRef CircuitBuilder::GetLengthFromForInIterator(GateRef iter)
631 {
632 GateRef offset = IntPtr(JSForInIterator::LENGTH_OFFSET);
633 return Load(VariableType::INT32(), iter, offset);
634 }
635
GetIndexFromForInIterator(GateRef iter)636 GateRef CircuitBuilder::GetIndexFromForInIterator(GateRef iter)
637 {
638 GateRef offset = IntPtr(JSForInIterator::INDEX_OFFSET);
639 return Load(VariableType::INT32(), iter, offset);
640 }
641
GetKeysFromForInIterator(GateRef iter)642 GateRef CircuitBuilder::GetKeysFromForInIterator(GateRef iter)
643 {
644 GateRef offset = IntPtr(JSForInIterator::KEYS_OFFSET);
645 return Load(VariableType::JS_ANY(), iter, offset);
646 }
647
GetObjectFromForInIterator(GateRef iter)648 GateRef CircuitBuilder::GetObjectFromForInIterator(GateRef iter)
649 {
650 GateRef offset = IntPtr(JSForInIterator::OBJECT_OFFSET);
651 return Load(VariableType::JS_ANY(), iter, offset);
652 }
653
GetCachedHclassFromForInIterator(GateRef iter)654 GateRef CircuitBuilder::GetCachedHclassFromForInIterator(GateRef iter)
655 {
656 GateRef offset = IntPtr(JSForInIterator::CACHED_HCLASS_OFFSET);
657 return Load(VariableType::JS_ANY(), iter, offset);
658 }
659
SetLengthOfForInIterator(GateRef glue,GateRef iter,GateRef length)660 void CircuitBuilder::SetLengthOfForInIterator(GateRef glue, GateRef iter, GateRef length)
661 {
662 GateRef offset = IntPtr(JSForInIterator::LENGTH_OFFSET);
663 Store(VariableType::INT32(), glue, iter, offset, length);
664 }
665
SetIndexOfForInIterator(GateRef glue,GateRef iter,GateRef index)666 void CircuitBuilder::SetIndexOfForInIterator(GateRef glue, GateRef iter, GateRef index)
667 {
668 GateRef offset = IntPtr(JSForInIterator::INDEX_OFFSET);
669 Store(VariableType::INT32(), glue, iter, offset, index);
670 }
671
SetKeysOfForInIterator(GateRef glue,GateRef iter,GateRef keys)672 void CircuitBuilder::SetKeysOfForInIterator(GateRef glue, GateRef iter, GateRef keys)
673 {
674 GateRef offset = IntPtr(JSForInIterator::KEYS_OFFSET);
675 Store(VariableType::JS_ANY(), glue, iter, offset, keys);
676 }
677
SetObjectOfForInIterator(GateRef glue,GateRef iter,GateRef object)678 void CircuitBuilder::SetObjectOfForInIterator(GateRef glue, GateRef iter, GateRef object)
679 {
680 GateRef offset = IntPtr(JSForInIterator::OBJECT_OFFSET);
681 Store(VariableType::JS_ANY(), glue, iter, offset, object);
682 }
683
SetCachedHclassOfForInIterator(GateRef glue,GateRef iter,GateRef hclass)684 void CircuitBuilder::SetCachedHclassOfForInIterator(GateRef glue, GateRef iter, GateRef hclass)
685 {
686 GateRef offset = IntPtr(JSForInIterator::CACHED_HCLASS_OFFSET);
687 Store(VariableType::JS_ANY(), glue, iter, offset, hclass);
688 }
689
SetNextIndexOfArrayIterator(GateRef glue,GateRef iter,GateRef nextIndex)690 void CircuitBuilder::SetNextIndexOfArrayIterator(GateRef glue, GateRef iter, GateRef nextIndex)
691 {
692 GateRef offset = IntPtr(JSArrayIterator::NEXT_INDEX_OFFSET);
693 Store(VariableType::INT32(), glue, iter, offset, nextIndex);
694 }
695
SetIteratedArrayOfArrayIterator(GateRef glue,GateRef iter,GateRef iteratedArray)696 void CircuitBuilder::SetIteratedArrayOfArrayIterator(GateRef glue, GateRef iter, GateRef iteratedArray)
697 {
698 GateRef offset = IntPtr(JSArrayIterator::ITERATED_ARRAY_OFFSET);
699 Store(VariableType::JS_ANY(), glue, iter, offset, iteratedArray);
700 }
701
SetBitFieldOfArrayIterator(GateRef glue,GateRef iter,GateRef kind)702 void CircuitBuilder::SetBitFieldOfArrayIterator(GateRef glue, GateRef iter, GateRef kind)
703 {
704 GateRef offset = IntPtr(JSArrayIterator::BIT_FIELD_OFFSET);
705 Store(VariableType::INT32(), glue, iter, offset, kind);
706 }
707
IncreaseInteratorIndex(GateRef glue,GateRef iter,GateRef index)708 void CircuitBuilder::IncreaseInteratorIndex(GateRef glue, GateRef iter, GateRef index)
709 {
710 GateRef newIndex = Int32Add(index, Int32(1));
711 GateRef offset = IntPtr(JSForInIterator::INDEX_OFFSET);
712 Store(VariableType::INT32(), glue, iter, offset, newIndex);
713 }
714
GetHasChanged(GateRef object)715 GateRef CircuitBuilder::GetHasChanged(GateRef object)
716 {
717 GateRef bitfieldOffset = IntPtr(ProtoChangeMarker::BIT_FIELD_OFFSET);
718 GateRef bitfield = Load(VariableType::INT32(), object, bitfieldOffset);
719 GateRef mask = Int32(1LLU << (ProtoChangeMarker::HAS_CHANGED_BITS - 1));
720 return Int32NotEqual(Int32And(bitfield, mask), Int32(0));
721 }
722
GetAccessorHasChanged(GateRef object)723 GateRef CircuitBuilder::GetAccessorHasChanged(GateRef object)
724 {
725 GateRef bitfieldOffset = IntPtr(ProtoChangeMarker::BIT_FIELD_OFFSET);
726 GateRef bitfield = Load(VariableType::INT32(), object, bitfieldOffset);
727 return Int32NotEqual(
728 Int32And(Int32LSR(bitfield, Int32(ProtoChangeMarker::AccessorHasChangedBits::START_BIT)),
729 Int32((1LLU << ProtoChangeMarker::AccessorHasChangedBits::SIZE) - 1)),
730 Int32(0));
731 }
732
HasDeleteProperty(GateRef hClass)733 GateRef CircuitBuilder::HasDeleteProperty(GateRef hClass)
734 {
735 GateRef bitfield = Load(VariableType::INT32(), hClass, IntPtr(JSHClass::BIT_FIELD1_OFFSET));
736 return Int32NotEqual(
737 Int32And(Int32LSR(bitfield, Int32(JSHClass::HasDeletePropertyBit::START_BIT)),
738 Int32((1LLU << JSHClass::HasDeletePropertyBit::SIZE) - 1)),
739 Int32(0));
740 }
741
IsOnHeap(GateRef hClass)742 GateRef CircuitBuilder::IsOnHeap(GateRef hClass)
743 {
744 GateRef bitfield = Load(VariableType::INT32(), hClass, IntPtr(JSHClass::BIT_FIELD_OFFSET));
745 return Int32NotEqual(
746 Int32And(Int32LSR(bitfield, Int32(JSHClass::IsOnHeap::START_BIT)),
747 Int32((1LU << JSHClass::IsOnHeap::SIZE) - 1)),
748 Int32(0));
749 }
750
IsEcmaObject(GateRef obj)751 GateRef CircuitBuilder::IsEcmaObject(GateRef obj)
752 {
753 return LogicAndBuilder(env_).And(TaggedIsHeapObject(obj)).And(TaggedObjectIsEcmaObject(obj)).Done();
754 }
755
CheckJSType(GateRef object,JSType jsType)756 GateRef CircuitBuilder::CheckJSType(GateRef object, JSType jsType)
757 {
758 Label entryPass(env_);
759 SubCfgEntry(&entryPass);
760 DEFVALUE(result, env_, VariableType::BOOL(), False());
761 Label heapObj(env_);
762 Label exit(env_);
763 GateRef isHeapObject = TaggedIsHeapObject(object);
764 BRANCH_CIR2(isHeapObject, &heapObj, &exit);
765 Bind(&heapObj);
766 {
767 GateRef objectType = GetObjectType(LoadHClass(object));
768 result = Int32Equal(objectType, Int32(static_cast<int32_t>(jsType)));
769 Jump(&exit);
770 }
771 Bind(&exit);
772 auto ret = *result;
773 SubCfgExit();
774 return ret;
775 }
776
GetObjectByIndexFromConstPool(GateRef glue,GateRef hirGate,GateRef frameState,GateRef index,ConstPoolType type)777 GateRef CircuitBuilder::GetObjectByIndexFromConstPool(GateRef glue, GateRef hirGate, GateRef frameState, GateRef index,
778 ConstPoolType type)
779 {
780 ArgumentAccessor argAcc(circuit_);
781 GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC);
782 GateRef module = GetModuleFromFunction(jsFunc);
783 GateRef sharedConstpool = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::SHARED_CONST_POOL);
784 GateRef unsharedConstPool = unsharedConstPool = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::UNSHARED_CONST_POOL);
785 GateRef obj = GetObjectFromConstPool(glue, hirGate, sharedConstpool, unsharedConstPool, module, index, type);
786 return obj;
787 }
788
GetObjectFromConstPool(GateRef glue,GateRef hirGate,GateRef sharedConstPool,GateRef unsharedConstPool,GateRef module,GateRef index,ConstPoolType type)789 GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef sharedConstPool,
790 GateRef unsharedConstPool, GateRef module, GateRef index,
791 ConstPoolType type)
792 {
793 Label entry(env_);
794 SubCfgEntry(&entry);
795 Label exit(env_);
796 Label cacheMiss(env_);
797 Label cache(env_);
798 Label unshareCpHit(env_);
799 Label unshareCpMiss(env_);
800
801 // HirGate Can not be a nullGate in Aot
802 if (GetCircuit()->IsOptimizedOrFastJit() && hirGate == Circuit::NullGate()) {
803 hirGate = index;
804 }
805 // Call runtime to create unshared constpool when current context's cache is hole in multi-thread.
806 DEFVALUE(cacheValue, env_, VariableType::JS_ANY(), Hole());
807 if (type == ConstPoolType::ARRAY_LITERAL || type == ConstPoolType::OBJECT_LITERAL) {
808 BRANCH_CIR2(TaggedIsNotHole(unsharedConstPool), &unshareCpHit, &unshareCpMiss);
809 Bind(&unshareCpHit);
810 {
811 cacheValue = GetValueFromTaggedArray(unsharedConstPool, index);
812 Jump(&unshareCpMiss);
813 }
814 } else {
815 cacheValue = GetValueFromTaggedArray(sharedConstPool, index);
816 Jump(&unshareCpMiss);
817 }
818 Bind(&unshareCpMiss);
819 DEFVALUE(result, env_, VariableType::JS_ANY(), *cacheValue);
820 BRANCH_CIR2(BitOr(TaggedIsHole(*result), TaggedIsNullPtr(*result)), &cacheMiss, &cache);
821 Bind(&cacheMiss);
822 {
823 if (type == ConstPoolType::STRING) {
824 result = CallRuntime(glue, RTSTUB_ID(GetStringFromCache), Gate::InvalidGateRef,
825 { sharedConstPool, Int32ToTaggedInt(index) }, hirGate);
826 } else if (type == ConstPoolType::ARRAY_LITERAL) {
827 result = CallRuntime(glue, RTSTUB_ID(GetArrayLiteralFromCache), Gate::InvalidGateRef,
828 { sharedConstPool, Int32ToTaggedInt(index), module }, hirGate);
829 } else if (type == ConstPoolType::OBJECT_LITERAL) {
830 result = CallRuntime(glue, RTSTUB_ID(GetObjectLiteralFromCache), Gate::InvalidGateRef,
831 { sharedConstPool, Int32ToTaggedInt(index), module }, hirGate);
832 } else {
833 result = CallRuntime(glue, RTSTUB_ID(GetMethodFromCache), Gate::InvalidGateRef,
834 { sharedConstPool, Int32ToTaggedInt(index) }, hirGate);
835 }
836 Jump(&exit);
837 }
838 Bind(&cache);
839 {
840 if (type == ConstPoolType::METHOD) {
841 Label isHeapObj(env_);
842 Label checkInteger(env_);
843 BRANCH_CIR2(TaggedIsHeapObject(*result), &isHeapObj, &checkInteger);
844 Bind(&isHeapObj);
845 {
846 Label isAOTLiteralInfo(env_);
847 BRANCH_CIR2(IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit);
848 Bind(&isAOTLiteralInfo);
849 {
850 result = CallRuntime(glue, RTSTUB_ID(GetMethodFromCache), Gate::InvalidGateRef,
851 { sharedConstPool, Int32ToTaggedInt(index) }, hirGate);
852 Jump(&exit);
853 }
854 }
855 Bind(&checkInteger);
856 {
857 Label isInteger(env_);
858 BRANCH_CIR2(TaggedIsInt(*result), &isInteger, &exit);
859 Bind(&isInteger);
860 {
861 result = CallRuntime(glue, RTSTUB_ID(GetMethodFromCache), Gate::InvalidGateRef,
862 { sharedConstPool, Int32ToTaggedInt(index) }, hirGate);
863 Jump(&exit);
864 }
865 }
866 } else if (type == ConstPoolType::ARRAY_LITERAL) {
867 Label isHeapObj(env_);
868 BRANCH_CIR2(TaggedIsHeapObject(*result), &isHeapObj, &exit);
869 Bind(&isHeapObj);
870 {
871 Label isAOTLiteralInfo(env_);
872 BRANCH_CIR2(IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit);
873 Bind(&isAOTLiteralInfo);
874 {
875 result = CallRuntime(glue, RTSTUB_ID(GetArrayLiteralFromCache), Gate::InvalidGateRef,
876 { sharedConstPool, Int32ToTaggedInt(index), module }, hirGate);
877 Jump(&exit);
878 }
879 }
880 } else if (type == ConstPoolType::OBJECT_LITERAL) {
881 Label isHeapObj(env_);
882 BRANCH_CIR2(TaggedIsHeapObject(*result), &isHeapObj, &exit);
883 Bind(&isHeapObj);
884 {
885 Label isAOTLiteralInfo(env_);
886 BRANCH_CIR2(IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit);
887 Bind(&isAOTLiteralInfo);
888 {
889 result = CallRuntime(glue, RTSTUB_ID(GetObjectLiteralFromCache), Gate::InvalidGateRef,
890 { sharedConstPool, Int32ToTaggedInt(index), module }, hirGate);
891 Jump(&exit);
892 }
893 }
894 } else {
895 Jump(&exit);
896 }
897 }
898 Bind(&exit);
899 auto ret = *result;
900 SubCfgExit();
901 return ret;
902 }
903
GetFunctionLexicalEnv(GateRef function)904 GateRef CircuitBuilder::GetFunctionLexicalEnv(GateRef function)
905 {
906 return Load(VariableType::JS_POINTER(), function, IntPtr(JSFunction::LEXICAL_ENV_OFFSET));
907 }
908
SetLengthToFunction(GateRef glue,GateRef function,GateRef value)909 void CircuitBuilder::SetLengthToFunction(GateRef glue, GateRef function, GateRef value)
910 {
911 GateRef offset = IntPtr(JSFunction::LENGTH_OFFSET);
912 Store(VariableType::INT32(), glue, function, offset, value);
913 }
914
SetLexicalEnvToFunction(GateRef glue,GateRef function,GateRef value)915 void CircuitBuilder::SetLexicalEnvToFunction(GateRef glue, GateRef function, GateRef value)
916 {
917 GateRef offset = IntPtr(JSFunction::LEXICAL_ENV_OFFSET);
918 Store(VariableType::JS_ANY(), glue, function, offset, value);
919 }
920
SetHomeObjectToFunction(GateRef glue,GateRef function,GateRef value)921 void CircuitBuilder::SetHomeObjectToFunction(GateRef glue, GateRef function, GateRef value)
922 {
923 GateRef offset = IntPtr(JSFunction::HOME_OBJECT_OFFSET);
924 Store(VariableType::JS_ANY(), glue, function, offset, value);
925 }
926
SetModuleToFunction(GateRef glue,GateRef function,GateRef value)927 void CircuitBuilder::SetModuleToFunction(GateRef glue, GateRef function, GateRef value)
928 {
929 GateRef offset = IntPtr(JSFunction::ECMA_MODULE_OFFSET);
930 Store(VariableType::JS_POINTER(), glue, function, offset, value);
931 }
932
GetGlobalEnvValue(VariableType type,GateRef env,size_t index)933 GateRef CircuitBuilder::GetGlobalEnvValue(VariableType type, GateRef env, size_t index)
934 {
935 auto valueIndex = IntPtr(GlobalEnv::HEADER_SIZE + JSTaggedValue::TaggedTypeSize() * index);
936 return Load(type, env, valueIndex);
937 }
938
GetCodeAddr(GateRef jsFunc)939 GateRef CircuitBuilder::GetCodeAddr(GateRef jsFunc)
940 {
941 auto codeAddOffset = IntPtr(JSFunction::CODE_ENTRY_OFFSET);
942 return Load(VariableType::NATIVE_POINTER(), jsFunc, codeAddOffset);
943 }
944
GetBaselineCodeAddr(GateRef baselineCode)945 GateRef CircuitBuilder::GetBaselineCodeAddr(GateRef baselineCode)
946 {
947 auto codeAddrOffset = IntPtr(MachineCode::FUNCADDR_OFFSET);
948 return Load(VariableType::NATIVE_POINTER(), baselineCode, codeAddrOffset);
949 }
950
GetHClassGateFromIndex(GateRef gate,int32_t index)951 GateRef CircuitBuilder::GetHClassGateFromIndex(GateRef gate, int32_t index)
952 {
953 ArgumentAccessor argAcc(circuit_);
954 GateRef unsharedConstpool = argAcc.GetFrameArgsIn(gate, FrameArgIdx::UNSHARED_CONST_POOL);
955 return LoadHClassFromConstpool(unsharedConstpool, index);
956 }
957
AddPhiOperand(GateRef val)958 GateRef Variable::AddPhiOperand(GateRef val)
959 {
960 ASSERT(GateAccessor(env_->GetCircuit()).IsValueSelector(val));
961 Label label = env_->GetLabelFromSelector(val);
962 size_t idx = 0;
963 for (auto pred : label.GetPredecessors()) {
964 auto preVal = pred.ReadVariable(this);
965 ASSERT(!GateAccessor(env_->GetCircuit()).IsNop(preVal));
966 idx++;
967 val = AddOperandToSelector(val, idx, preVal);
968 }
969 return TryRemoveTrivialPhi(val);
970 }
971
AddOperandToSelector(GateRef val,size_t idx,GateRef in)972 GateRef Variable::AddOperandToSelector(GateRef val, size_t idx, GateRef in)
973 {
974 GateAccessor(env_->GetCircuit()).NewIn(val, idx, in);
975 return val;
976 }
977
TryRemoveTrivialPhi(GateRef phi)978 GateRef Variable::TryRemoveTrivialPhi(GateRef phi)
979 {
980 GateAccessor acc(GetCircuit());
981 GateRef same = Gate::InvalidGateRef;
982 const size_t inNum = acc.GetNumIns(phi);
983 for (size_t i = 1; i < inNum; ++i) {
984 GateRef phiIn = acc.GetIn(phi, i);
985 if (phiIn == same || phiIn == phi) {
986 continue; // unique value or self-reference
987 }
988 if (same != Gate::InvalidGateRef) {
989 return phi; // the phi merges at least two valusses: not trivial
990 }
991 same = phiIn;
992 }
993 if (same == Gate::InvalidGateRef) {
994 // the phi is unreachable or in the start block
995 GateType type = acc.GetGateType(phi);
996 same = env_->GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_UNDEFINED, type);
997 }
998 // remove the trivial phi
999 // get all users of phi except self
1000 std::vector<GateRef> outs;
1001 auto uses = acc.Uses(phi);
1002 for (auto use = uses.begin(); use != uses.end();) {
1003 GateRef u = *use;
1004 if (u != phi) {
1005 outs.push_back(u);
1006 use = acc.ReplaceIn(use, same);
1007 } else {
1008 use++;
1009 }
1010 }
1011 acc.DeleteGate(phi);
1012
1013 // try to recursiveby remove all phi users, which might have vecome trivial
1014 for (auto out : outs) {
1015 if (acc.IsValueSelector(out)) {
1016 auto result = TryRemoveTrivialPhi(out);
1017 if (same == out) {
1018 same = result;
1019 }
1020 }
1021 }
1022 return same;
1023 }
1024
ElementsKindIsIntOrHoleInt(GateRef kind)1025 GateRef CircuitBuilder::ElementsKindIsIntOrHoleInt(GateRef kind)
1026 {
1027 GateRef kindIsInt = Int32Equal(kind, Int32(static_cast<uint32_t>(ElementsKind::INT)));
1028 GateRef kindIsHoleInt = Int32Equal(kind, Int32(static_cast<uint32_t>(ElementsKind::HOLE_INT)));
1029 return BitOr(kindIsInt, kindIsHoleInt);
1030 }
1031
ElementsKindIsNumOrHoleNum(GateRef kind)1032 GateRef CircuitBuilder::ElementsKindIsNumOrHoleNum(GateRef kind)
1033 {
1034 GateRef kindIsNum = Int32Equal(kind, Int32(static_cast<uint32_t>(ElementsKind::NUMBER)));
1035 GateRef kindIsHoleNum = Int32Equal(kind, Int32(static_cast<uint32_t>(ElementsKind::HOLE_NUMBER)));
1036 return BitOr(kindIsNum, kindIsHoleNum);
1037 }
1038
ElementsKindIsHeapKind(GateRef kind)1039 GateRef CircuitBuilder::ElementsKindIsHeapKind(GateRef kind)
1040 {
1041 GateRef overString = Int32GreaterThanOrEqual(kind, Int32(static_cast<uint32_t>(ElementsKind::STRING)));
1042 GateRef isHoleOrNone = Int32LessThanOrEqual(kind, Int32(static_cast<uint32_t>(ElementsKind::HOLE)));
1043 return BitOr(overString, isHoleOrNone);
1044 }
1045
LoadBuiltinObject(size_t offset)1046 GateRef CircuitBuilder::LoadBuiltinObject(size_t offset)
1047 {
1048 auto currentLabel = env_->GetCurrentLabel();
1049 auto currentControl = currentLabel->GetControl();
1050 auto currentDepend = currentLabel->GetDepend();
1051 auto frameState = acc_.FindNearestFrameState(currentDepend);
1052 GateRef ret = GetCircuit()->NewGate(circuit_->LoadBuiltinObject(offset),
1053 MachineType::I64,
1054 {currentControl, currentDepend, frameState},
1055 GateType::AnyType());
1056 currentLabel->SetControl(ret);
1057 currentLabel->SetDepend(ret);
1058 return ret;
1059 }
1060
GetKeyFromLexivalEnv(GateRef lexicalEnv,GateRef levelIndex,GateRef slotIndex)1061 GateRef CircuitBuilder::GetKeyFromLexivalEnv(GateRef lexicalEnv, GateRef levelIndex, GateRef slotIndex)
1062 {
1063 Label entry(env_);
1064 SubCfgEntry(&entry);
1065 Label exit(env_);
1066 Label loopHead(env_);
1067 Label loopEnd(env_);
1068 Label afterLoop(env_);
1069
1070 DEFVALUE(result, env_, VariableType::JS_ANY(), Hole());
1071 DEFVALUE(currentEnv, env_, VariableType::JS_ANY(), lexicalEnv);
1072 DEFVALUE(i, env_, VariableType::INT32(), Int32(0));
1073
1074 Branch(Int32LessThan(*i, levelIndex), &loopHead, &afterLoop);
1075 LoopBegin(&loopHead);
1076 {
1077 currentEnv = GetParentEnv(*currentEnv);
1078 i = Int32Add(*i, Int32(1));
1079 Branch(Int32LessThan(*i, levelIndex), &loopEnd, &afterLoop);
1080 Bind(&loopEnd);
1081 LoopEnd(&loopHead);
1082 }
1083 Bind(&afterLoop);
1084 {
1085 result = GetPropertiesFromLexicalEnv(*currentEnv, slotIndex);
1086 Jump(&exit);
1087 }
1088 Bind(&exit);
1089 auto ret = *result;
1090 SubCfgExit();
1091 return ret;
1092 }
1093
GetParentEnv(GateRef object)1094 GateRef CircuitBuilder::GetParentEnv(GateRef object)
1095 {
1096 GateRef index = Int32(LexicalEnv::PARENT_ENV_INDEX);
1097 return GetValueFromTaggedArray(object, index);
1098 }
1099
GetSendableParentEnv(GateRef object)1100 GateRef CircuitBuilder::GetSendableParentEnv(GateRef object)
1101 {
1102 GateRef index = Int32(SendableEnv::SENDABLE_PARENT_ENV_INDEX);
1103 return GetValueFromTaggedArray(object, index);
1104 }
1105
GetPropertiesFromLexicalEnv(GateRef object,GateRef index)1106 GateRef CircuitBuilder::GetPropertiesFromLexicalEnv(GateRef object, GateRef index)
1107 {
1108 GateRef valueIndex = Int32Add(index, Int32(LexicalEnv::RESERVED_ENV_LENGTH));
1109 return GetValueFromTaggedArray(object, valueIndex);
1110 }
1111
NewJSPrimitiveRef(GateRef glue,size_t index,GateRef obj)1112 GateRef CircuitBuilder::NewJSPrimitiveRef(GateRef glue, size_t index, GateRef obj)
1113 {
1114 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env_->Is32Bit()));
1115 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
1116 GateRef func = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, index);
1117 GateRef protoOrHclass = Load(VariableType::JS_ANY(), func, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1118 NewObjectStubBuilder newBuilder(env_);
1119 GateRef newObj = newBuilder.NewJSObject(glue, protoOrHclass);
1120 GateRef valueOffset = IntPtr(JSPrimitiveRef::VALUE_OFFSET);
1121 Store(VariableType::JS_ANY(), glue, newObj, valueOffset, obj);
1122 return newObj;
1123 }
1124
ToObject(GateRef glue,GateRef obj)1125 GateRef CircuitBuilder::ToObject(GateRef glue, GateRef obj)
1126 {
1127 Label entry(env_);
1128 env_->SubCfgEntry(&entry);
1129 Label exit(env_);
1130 DEFVALUE(result, env_, VariableType::JS_ANY(), obj);
1131 DEFVALUE(taggedId, env_, VariableType::INT32(), Int32(0));
1132 Label isNumber(env_);
1133 Label notNumber(env_);
1134 Label isBoolean(env_);
1135 Label notBoolean(env_);
1136 Label isString(env_);
1137 Label notString(env_);
1138 Label isECMAObject(env_);
1139 Label notIsECMAObject(env_);
1140 Label isSymbol(env_);
1141 Label notSymbol(env_);
1142 Label isUndefined(env_);
1143 Label notIsUndefined(env_);
1144 Label isNull(env_);
1145 Label notIsNull(env_);
1146 Label isHole(env_);
1147 Label notIsHole(env_);
1148 Label isBigInt(env_);
1149 Label notIsBigInt(env_);
1150 Label throwError(env_);
1151 BRANCH_CIR2(IsEcmaObject(obj), &isECMAObject, ¬IsECMAObject);
1152 Bind(&isECMAObject);
1153 {
1154 result = obj;
1155 Jump(&exit);
1156 }
1157 Bind(¬IsECMAObject);
1158 BRANCH_CIR2(TaggedIsNumber(obj), &isNumber, ¬Number);
1159 Bind(&isNumber);
1160 {
1161 result = NewJSPrimitiveRef(glue, GlobalEnv::NUMBER_FUNCTION_INDEX, obj);
1162 Jump(&exit);
1163 }
1164 Bind(¬Number);
1165 BRANCH_CIR2(TaggedIsBoolean(obj), &isBoolean, ¬Boolean);
1166 Bind(&isBoolean);
1167 {
1168 result = NewJSPrimitiveRef(glue, GlobalEnv::BOOLEAN_FUNCTION_INDEX, obj);
1169 Jump(&exit);
1170 }
1171 Bind(¬Boolean);
1172 BRANCH_CIR2(TaggedIsString(obj), &isString, ¬String);
1173 Bind(&isString);
1174 {
1175 result = NewJSPrimitiveRef(glue, GlobalEnv::STRING_FUNCTION_INDEX, obj);
1176 Jump(&exit);
1177 }
1178 Bind(¬String);
1179 BRANCH_CIR2(TaggedIsSymbol(obj), &isSymbol, ¬Symbol);
1180 Bind(&isSymbol);
1181 {
1182 result = NewJSPrimitiveRef(glue, GlobalEnv::SYMBOL_FUNCTION_INDEX, obj);
1183 Jump(&exit);
1184 }
1185 Bind(¬Symbol);
1186 BRANCH_CIR2(TaggedIsUndefined(obj), &isUndefined, ¬IsUndefined);
1187 Bind(&isUndefined);
1188 {
1189 taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotUndefinedObject));
1190 Jump(&throwError);
1191 }
1192 Bind(¬IsUndefined);
1193 BRANCH_CIR2(TaggedIsHole(obj), &isHole, ¬IsHole);
1194 Bind(&isHole);
1195 {
1196 taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotHoleObject));
1197 Jump(&throwError);
1198 }
1199 Bind(¬IsHole);
1200 BRANCH_CIR2(TaggedIsNull(obj), &isNull, ¬IsNull);
1201 Bind(&isNull);
1202 {
1203 taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotNullObject));
1204 Jump(&throwError);
1205 }
1206 Bind(¬IsNull);
1207 BRANCH_CIR2(TaggedIsBigInt(obj), &isBigInt, ¬IsBigInt);
1208 Bind(&isBigInt);
1209 {
1210 result = NewJSPrimitiveRef(glue, GlobalEnv::BIGINT_FUNCTION_INDEX, obj);
1211 Jump(&exit);
1212 }
1213 Bind(¬IsBigInt);
1214 {
1215 taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotNullObject));
1216 Jump(&throwError);
1217 }
1218 Bind(&throwError);
1219 {
1220 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), Gate::InvalidGateRef, { Int32ToTaggedInt(*taggedId) }, glue);
1221 result = ExceptionConstant();
1222 Jump(&exit);
1223 }
1224 Bind(&exit);
1225 auto ret = *result;
1226 env_->SubCfgExit();
1227 return ret;
1228 }
1229
GetPrototype(GateRef glue,GateRef object)1230 GateRef CircuitBuilder::GetPrototype(GateRef glue, GateRef object)
1231 {
1232 Label entry(env_);
1233 env_->SubCfgEntry(&entry);
1234 DEFVALUE(result, env_, VariableType::JS_ANY(), Hole());
1235 Label exit(env_);
1236 Label objectIsHeapObject(env_);
1237 Label objectIsEcmaObject(env_);
1238 Label objectNotEcmaObject(env_);
1239
1240 BRANCH_CIR2(TaggedIsHeapObject(object), &objectIsHeapObject, &objectNotEcmaObject);
1241 Bind(&objectIsHeapObject);
1242 BRANCH_CIR2(TaggedObjectIsEcmaObject(object), &objectIsEcmaObject, &objectNotEcmaObject);
1243 Bind(&objectNotEcmaObject);
1244 {
1245 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotGetNotEcmaObject));
1246 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), Gate::InvalidGateRef, { Int32ToTaggedInt(taggedId) }, glue);
1247 result = ExceptionConstant();
1248 Jump(&exit);
1249 }
1250 Bind(&objectIsEcmaObject);
1251 {
1252 Label objectIsJsProxy(env_);
1253 Label objectNotIsJsProxy(env_);
1254 BRANCH_CIR2(IsJsProxy(object), &objectIsJsProxy, &objectNotIsJsProxy);
1255 Bind(&objectIsJsProxy);
1256 {
1257 result = CallRuntime(glue, RTSTUB_ID(CallGetPrototype), Gate::InvalidGateRef, { object }, glue);
1258 Jump(&exit);
1259 }
1260 Bind(&objectNotIsJsProxy);
1261 {
1262 result = GetPrototypeFromHClass(LoadHClass(object));
1263 Jump(&exit);
1264 }
1265 }
1266 Bind(&exit);
1267 auto ret = *result;
1268 env_->SubCfgExit();
1269 return ret;
1270 }
1271
GetGlobalConstantValue(VariableType type,GateRef glue,ConstantIndex index)1272 GateRef CircuitBuilder::GetGlobalConstantValue(VariableType type, GateRef glue, ConstantIndex index)
1273 {
1274 GateRef gConstAddr = Load(VariableType::JS_ANY(), glue,
1275 IntPtr(JSThread::GlueData::GetGlobalConstOffset(env_->Is32Bit())));
1276 auto constantIndex = IntPtr(JSTaggedValue::TaggedTypeSize() * static_cast<size_t>(index));
1277 return Load(type, gConstAddr, constantIndex);
1278 }
1279
TransProtoWithoutLayout(GateRef glue,GateRef hClass,GateRef proto)1280 GateRef CircuitBuilder::TransProtoWithoutLayout(GateRef glue, GateRef hClass, GateRef proto)
1281 {
1282 Label entry(env_);
1283 env_->SubCfgEntry(&entry);
1284 Label exit(env_);
1285 DEFVALUE(result, env_, VariableType::JS_ANY(), Undefined());
1286
1287 GateRef key = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
1288 ConstantIndex::PROTOTYPE_STRING_INDEX);
1289 GateRef newClass = CallNGCRuntime(glue, RTSTUB_ID(JSHClassFindProtoTransitions), Gate::InvalidGateRef,
1290 { hClass, key, proto }, glue);
1291 Label undef(env_);
1292 Label find(env_);
1293 BRANCH_CIR2(IntPtrEqual(TaggedCastToIntPtr(newClass), IntPtr(0)), &undef, &find);
1294 Bind(&find);
1295 {
1296 result = newClass;
1297 Jump(&exit);
1298 }
1299 Bind(&undef);
1300 {
1301 result = CallRuntime(glue, RTSTUB_ID(HClassCloneWithAddProto), Gate::InvalidGateRef,
1302 { hClass, key, proto }, glue);
1303 Jump(&exit);
1304 }
1305 Bind(&exit);
1306 auto ret = *result;
1307 env_->SubCfgExit();
1308 return ret;
1309 }
1310
1311
OrdinaryNewJSObjectCreate(GateRef glue,GateRef proto)1312 GateRef CircuitBuilder::OrdinaryNewJSObjectCreate(GateRef glue, GateRef proto)
1313 {
1314 Label entry(env_);
1315 env_->SubCfgEntry(&entry);
1316 Label exit(env_);
1317 DEFVALUE(result, env_, VariableType::JS_ANY(), Undefined());
1318
1319 GateRef hClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
1320 ConstantIndex::OBJECT_HCLASS_INDEX);
1321 GateRef newClass = TransProtoWithoutLayout(glue, hClass, proto);
1322 Label exception(env_);
1323 Label noexception(env_);
1324 BRANCH_CIR2(TaggedIsException(newClass), &exception, &noexception);
1325 Bind(&exception);
1326 {
1327 result = ExceptionConstant();
1328 Jump(&exit);
1329 }
1330 Bind(&noexception);
1331 NewObjectStubBuilder newBuilder(env_);
1332 GateRef newObj = newBuilder.NewJSObject(glue, newClass);
1333 Label exceptionNewObj(env_);
1334 Label noexceptionNewObj(env_);
1335 BRANCH_CIR2(TaggedIsException(newObj), &exceptionNewObj, &noexceptionNewObj);
1336 Bind(&exceptionNewObj);
1337 {
1338 result = ExceptionConstant();
1339 Jump(&exit);
1340 }
1341 Bind(&noexceptionNewObj);
1342 {
1343 SetExtensibleToBitfield(glue, newObj, True());
1344 result = newObj;
1345 Jump(&exit);
1346 }
1347 Bind(&exit);
1348 auto ret = *result;
1349 env_->SubCfgExit();
1350 return ret;
1351 }
1352
GetPropertiesFromSendableEnv(GateRef object,GateRef index)1353 GateRef CircuitBuilder::GetPropertiesFromSendableEnv(GateRef object, GateRef index)
1354 {
1355 GateRef valueIndex = Int32Add(index, Int32(SendableEnv::SENDABLE_RESERVED_ENV_LENGTH));
1356 return GetValueFromTaggedArray(object, valueIndex);
1357 }
1358
GetProfileTypeInfo(GateRef function)1359 GateRef CircuitBuilder::GetProfileTypeInfo(GateRef function)
1360 {
1361 GateRef raw = Load(VariableType::JS_POINTER(), function, IntPtr(JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET));
1362 return Load(VariableType::JS_POINTER(), raw, IntPtr(ProfileTypeInfoCell::VALUE_OFFSET));
1363 }
1364
SetRawProfileTypeInfoToFunction(GateRef glue,GateRef function,GateRef value)1365 void CircuitBuilder::SetRawProfileTypeInfoToFunction(GateRef glue, GateRef function, GateRef value)
1366 {
1367 GateRef offset = IntPtr(JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET);
1368 Store(VariableType::JS_ANY(), glue, function, offset, value);
1369 }
1370
UpdateProfileTypeInfoCellToFunction(GateRef glue,GateRef function,GateRef profileTypeInfo,GateRef slotId)1371 void CircuitBuilder::UpdateProfileTypeInfoCellToFunction(GateRef glue, GateRef function,
1372 GateRef profileTypeInfo, GateRef slotId)
1373 {
1374 Label subEntry(env_);
1375 env_->SubCfgEntry(&subEntry);
1376
1377 Label profileTypeInfoNotUndefined(env_);
1378 Label slotValueUpdate(env_);
1379 Label slotValueNotUndefined(env_);
1380 Label profileTypeInfoEnd(env_);
1381 NewObjectStubBuilder newBuilder(env_);
1382 BRANCH_CIR2(TaggedIsUndefined(profileTypeInfo), &profileTypeInfoEnd, &profileTypeInfoNotUndefined);
1383 Bind(&profileTypeInfoNotUndefined);
1384 {
1385 GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId);
1386 BRANCH_CIR2(TaggedIsUndefined(slotValue), &slotValueUpdate, &slotValueNotUndefined);
1387 Bind(&slotValueUpdate);
1388 {
1389 GateRef newProfileTypeInfoCell = newBuilder.NewProfileTypeInfoCell(glue, Undefined());
1390 SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, newProfileTypeInfoCell);
1391 SetRawProfileTypeInfoToFunction(glue, function, newProfileTypeInfoCell);
1392 Jump(&profileTypeInfoEnd);
1393 }
1394 Bind(&slotValueNotUndefined);
1395 UpdateProfileTypeInfoCellType(glue, slotValue);
1396 SetRawProfileTypeInfoToFunction(glue, function, slotValue);
1397 Jump(&profileTypeInfoEnd);
1398 }
1399 Bind(&profileTypeInfoEnd);
1400
1401 env_->SubCfgExit();
1402 }
1403
UpdateProfileTypeInfoCellType(GateRef glue,GateRef profileTypeInfoCell)1404 void CircuitBuilder::UpdateProfileTypeInfoCellType(GateRef glue, GateRef profileTypeInfoCell)
1405 {
1406 Label subEntry(env_);
1407 env_->SubCfgEntry(&subEntry);
1408
1409 // ProfileTypeInfoCell0 -> Cell1 -> CellN
1410 Label isProfileTypeInfoCell0(env_);
1411 Label notProfileTypeInfoCell0(env_);
1412 Label isProfileTypeInfoCell1(env_);
1413 Label endProfileTypeInfoCellType(env_);
1414 GateRef objectType = GetObjectType(LoadHClass(profileTypeInfoCell));
1415 BRANCH_CIR2(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::PROFILE_TYPE_INFO_CELL_0))),
1416 &isProfileTypeInfoCell0, ¬ProfileTypeInfoCell0);
1417 Bind(&isProfileTypeInfoCell0);
1418 {
1419 auto profileTypeInfoCell1Class = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
1420 ConstantIndex::PROFILE_TYPE_INFO_CELL_1_CLASS_INDEX);
1421 StoreHClassWithoutBarrier(glue, profileTypeInfoCell, profileTypeInfoCell1Class);
1422 Jump(&endProfileTypeInfoCellType);
1423 }
1424 Bind(¬ProfileTypeInfoCell0);
1425 BRANCH_CIR2(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::PROFILE_TYPE_INFO_CELL_1))),
1426 &isProfileTypeInfoCell1, &endProfileTypeInfoCellType);
1427 Bind(&isProfileTypeInfoCell1);
1428 {
1429 auto profileTypeInfoCellNClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
1430 ConstantIndex::PROFILE_TYPE_INFO_CELL_N_CLASS_INDEX);
1431 StoreHClassWithoutBarrier(glue, profileTypeInfoCell, profileTypeInfoCellNClass);
1432 Jump(&endProfileTypeInfoCellType);
1433 }
1434 Bind(&endProfileTypeInfoCellType);
1435 env_->SubCfgExit();
1436 }
1437
FastToBoolean(GateRef value)1438 GateRef CircuitBuilder::FastToBoolean(GateRef value)
1439 {
1440 Label entry(env_);
1441 env_->SubCfgEntry(&entry);
1442 DEFVALUE(result, env_, VariableType::JS_ANY(), HoleConstant());
1443 Label exit(env_);
1444
1445 Label isSpecial(env_);
1446 Label notSpecial(env_);
1447 Label isNumber(env_);
1448 Label isInt(env_);
1449 Label isDouble(env_);
1450 Label notNumber(env_);
1451 Label notNan(env_);
1452 Label isString(env_);
1453 Label notString(env_);
1454 Label isBigint(env_);
1455 Label lengthIsOne(env_);
1456 Label returnTrue(env_);
1457 Label returnFalse(env_);
1458
1459 BRANCH_CIR2(TaggedIsSpecial(value), &isSpecial, ¬Special);
1460 Bind(&isSpecial);
1461 {
1462 BRANCH_CIR2(TaggedIsTrue(value), &returnTrue, &returnFalse);
1463 }
1464 Bind(¬Special);
1465 {
1466 BRANCH_CIR2(TaggedIsNumber(value), &isNumber, ¬Number);
1467 Bind(¬Number);
1468 {
1469 BRANCH_CIR2(TaggedIsString(value), &isString, ¬String);
1470 Bind(&isString);
1471 {
1472 auto len = GetLengthFromString(value);
1473 BRANCH_CIR2(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
1474 }
1475 Bind(¬String);
1476 BRANCH_CIR2(TaggedIsBigInt(value), &isBigint, &returnTrue);
1477 Bind(&isBigint);
1478 {
1479 auto len = Load(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
1480 BRANCH_CIR2(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
1481 Bind(&lengthIsOne);
1482 {
1483 auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
1484 auto data0 = Load(VariableType::INT32(), data, Int32(0));
1485 BRANCH_CIR2(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
1486 }
1487 }
1488 }
1489 Bind(&isNumber);
1490 {
1491 BRANCH_CIR2(TaggedIsInt(value), &isInt, &isDouble);
1492 Bind(&isInt);
1493 {
1494 auto intValue = GetInt32OfTInt(value);
1495 BRANCH_CIR2(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
1496 }
1497 Bind(&isDouble);
1498 {
1499 auto doubleValue = GetDoubleOfTDouble(value);
1500 BRANCH_CIR2(DoubleIsNAN(doubleValue), &returnFalse, ¬Nan);
1501 Bind(¬Nan);
1502 BRANCH_CIR2(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
1503 }
1504 }
1505 }
1506 Bind(&returnTrue);
1507 {
1508 result = TaggedTrue();
1509 Jump(&exit);
1510 }
1511 Bind(&returnFalse);
1512 {
1513 result = TaggedFalse();
1514 Jump(&exit);
1515 }
1516 Bind(&exit);
1517 auto ret = *result;
1518 env_->SubCfgExit();
1519 return ret;
1520 }
1521
IsStableArrayLengthWriteable(GateRef array)1522 GateRef CircuitBuilder::IsStableArrayLengthWriteable(GateRef array)
1523 {
1524 Label entry(env_);
1525 env_->SubCfgEntry(&entry);
1526 DEFVALUE(result, env_, VariableType::BOOL(), False());
1527 GateRef hClass = LoadHClassByConstOffset(array);
1528 GateRef attrOffset = IntPtr(JSHClass::LAYOUT_OFFSET);
1529 GateRef layout = Load(VariableType::JS_POINTER(), hClass, attrOffset);
1530 GateRef entryHandler = Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX);
1531 GateRef index =
1532 Int32Add(Int32LSL(entryHandler, Int32(LayoutInfo::ELEMENTS_INDEX_LOG2)), Int32(LayoutInfo::ATTR_INDEX_OFFSET));
1533 GateRef attr = GetInt64OfTInt(GetValueFromTaggedArray(layout, index));
1534 GateRef writeableField =
1535 Int32And(TruncInt64ToInt32(Int64LSR(attr, Int64(PropertyAttributes::WritableField::START_BIT))),
1536 Int32((1LLU << PropertyAttributes::WritableField::SIZE) - 1));
1537 result = Int32NotEqual(writeableField, Int32(0));
1538 auto ret = *result;
1539 env_->SubCfgExit();
1540 return ret;
1541 }
1542 } // namespace panda::ecmascript::kungfu
1543