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