• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &notIsECMAObject);
1152     Bind(&isECMAObject);
1153     {
1154         result = obj;
1155         Jump(&exit);
1156     }
1157     Bind(&notIsECMAObject);
1158     BRANCH_CIR2(TaggedIsNumber(obj), &isNumber, &notNumber);
1159     Bind(&isNumber);
1160     {
1161         result = NewJSPrimitiveRef(glue, GlobalEnv::NUMBER_FUNCTION_INDEX, obj);
1162         Jump(&exit);
1163     }
1164     Bind(&notNumber);
1165     BRANCH_CIR2(TaggedIsBoolean(obj), &isBoolean, &notBoolean);
1166     Bind(&isBoolean);
1167     {
1168         result = NewJSPrimitiveRef(glue, GlobalEnv::BOOLEAN_FUNCTION_INDEX, obj);
1169         Jump(&exit);
1170     }
1171     Bind(&notBoolean);
1172     BRANCH_CIR2(TaggedIsString(obj), &isString, &notString);
1173     Bind(&isString);
1174     {
1175         result = NewJSPrimitiveRef(glue, GlobalEnv::STRING_FUNCTION_INDEX, obj);
1176         Jump(&exit);
1177     }
1178     Bind(&notString);
1179     BRANCH_CIR2(TaggedIsSymbol(obj), &isSymbol, &notSymbol);
1180     Bind(&isSymbol);
1181     {
1182         result = NewJSPrimitiveRef(glue, GlobalEnv::SYMBOL_FUNCTION_INDEX, obj);
1183         Jump(&exit);
1184     }
1185     Bind(&notSymbol);
1186     BRANCH_CIR2(TaggedIsUndefined(obj), &isUndefined, &notIsUndefined);
1187     Bind(&isUndefined);
1188     {
1189         taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotUndefinedObject));
1190         Jump(&throwError);
1191     }
1192     Bind(&notIsUndefined);
1193     BRANCH_CIR2(TaggedIsHole(obj), &isHole, &notIsHole);
1194     Bind(&isHole);
1195     {
1196         taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotHoleObject));
1197         Jump(&throwError);
1198     }
1199     Bind(&notIsHole);
1200     BRANCH_CIR2(TaggedIsNull(obj), &isNull, &notIsNull);
1201     Bind(&isNull);
1202     {
1203         taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotNullObject));
1204         Jump(&throwError);
1205     }
1206     Bind(&notIsNull);
1207     BRANCH_CIR2(TaggedIsBigInt(obj), &isBigInt, &notIsBigInt);
1208     Bind(&isBigInt);
1209     {
1210         result = NewJSPrimitiveRef(glue, GlobalEnv::BIGINT_FUNCTION_INDEX, obj);
1211         Jump(&exit);
1212     }
1213     Bind(&notIsBigInt);
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, &notProfileTypeInfoCell0);
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(&notProfileTypeInfoCell0);
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, &notSpecial);
1460     Bind(&isSpecial);
1461     {
1462         BRANCH_CIR2(TaggedIsTrue(value), &returnTrue, &returnFalse);
1463     }
1464     Bind(&notSpecial);
1465     {
1466         BRANCH_CIR2(TaggedIsNumber(value), &isNumber, &notNumber);
1467         Bind(&notNumber);
1468         {
1469             BRANCH_CIR2(TaggedIsString(value), &isString, &notString);
1470             Bind(&isString);
1471             {
1472                 auto len = GetLengthFromString(value);
1473                 BRANCH_CIR2(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
1474             }
1475             Bind(&notString);
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, &notNan);
1501                 Bind(&notNan);
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