• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/common_stubs.h"
21 #include "ecmascript/compiler/rt_call_signature.h"
22 #include "ecmascript/deoptimizer/deoptimizer.h"
23 #include "ecmascript/global_env.h"
24 #include "ecmascript/js_thread.h"
25 #include "ecmascript/js_function.h"
26 
27 namespace panda::ecmascript::kungfu {
Merge(const std::vector<GateRef> & inList)28 GateRef CircuitBuilder::Merge(const std::vector<GateRef> &inList)
29 {
30     return circuit_->NewGate(circuit_->Merge(inList.size()), inList);
31 }
32 
Selector(OpCode opcode,MachineType machineType,GateRef control,const std::vector<GateRef> & values,int valueCounts,VariableType type)33 GateRef CircuitBuilder::Selector(OpCode opcode, MachineType machineType, GateRef control,
34     const std::vector<GateRef> &values, int valueCounts, VariableType type)
35 {
36     std::vector<GateRef> inList;
37     inList.push_back(control);
38     if (values.size() == 0) {
39         for (int i = 0; i < valueCounts; i++) {
40             inList.push_back(Circuit::NullGate());
41         }
42     } else {
43         for (int i = 0; i < valueCounts; i++) {
44             inList.push_back(values[i]);
45         }
46     }
47     ASSERT((opcode == OpCode::VALUE_SELECTOR) || (opcode == OpCode::DEPEND_SELECTOR));
48     const GateMetaData* meta = (opcode == OpCode::DEPEND_SELECTOR) ?
49         circuit_->DependSelector(valueCounts) : circuit_->ValueSelector(valueCounts);
50     return circuit_->NewGate(meta, machineType, inList.size(), inList.data(), type.GetGateType());
51 }
52 
Selector(OpCode opcode,GateRef control,const std::vector<GateRef> & values,int valueCounts,VariableType type)53 GateRef CircuitBuilder::Selector(OpCode opcode, GateRef control,
54     const std::vector<GateRef> &values, int valueCounts, VariableType type)
55 {
56     MachineType machineType = (opcode == OpCode::DEPEND_SELECTOR) ?
57         MachineType::NOVALUE : MachineType::FLEX;
58     return Selector(opcode, machineType, control, values, valueCounts, type);
59 }
60 
UndefineConstant()61 GateRef CircuitBuilder::UndefineConstant()
62 {
63     auto type = GateType::TaggedValue();
64     return circuit_->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_UNDEFINED, type);
65 }
66 
Branch(GateRef state,GateRef condition)67 GateRef CircuitBuilder::Branch(GateRef state, GateRef condition)
68 {
69     return circuit_->NewGate(circuit_->IfBranch(), { state, condition });
70 }
71 
SwitchBranch(GateRef state,GateRef index,int caseCounts)72 GateRef CircuitBuilder::SwitchBranch(GateRef state, GateRef index, int caseCounts)
73 {
74     return circuit_->NewGate(circuit_->SwitchBranch(caseCounts), { state, index });
75 }
76 
Return(GateRef state,GateRef depend,GateRef value)77 GateRef CircuitBuilder::Return(GateRef state, GateRef depend, GateRef value)
78 {
79     auto returnList = circuit_->GetReturnRoot();
80     return circuit_->NewGate(circuit_->Return(), { state, depend, value, returnList });
81 }
82 
ReturnVoid(GateRef state,GateRef depend)83 GateRef CircuitBuilder::ReturnVoid(GateRef state, GateRef depend)
84 {
85     auto returnList = circuit_->GetReturnRoot();
86     return circuit_->NewGate(circuit_->ReturnVoid(), { state, depend, returnList });
87 }
88 
Goto(GateRef state)89 GateRef CircuitBuilder::Goto(GateRef state)
90 {
91     return circuit_->NewGate(circuit_->OrdinaryBlock(), { state });
92 }
93 
LoopBegin(GateRef state)94 GateRef CircuitBuilder::LoopBegin(GateRef state)
95 {
96     auto nullGate = Circuit::NullGate();
97     return circuit_->NewGate(circuit_->LoopBegin(), { state, nullGate });
98 }
99 
LoopEnd(GateRef state)100 GateRef CircuitBuilder::LoopEnd(GateRef state)
101 {
102     return circuit_->NewGate(circuit_->LoopBack(), { state });
103 }
104 
IfTrue(GateRef ifBranch)105 GateRef CircuitBuilder::IfTrue(GateRef ifBranch)
106 {
107     return circuit_->NewGate(circuit_->IfTrue(), { ifBranch });
108 }
109 
IfFalse(GateRef ifBranch)110 GateRef CircuitBuilder::IfFalse(GateRef ifBranch)
111 {
112     return circuit_->NewGate(circuit_->IfFalse(), { ifBranch });
113 }
114 
SwitchCase(GateRef switchBranch,int64_t value)115 GateRef CircuitBuilder::SwitchCase(GateRef switchBranch, int64_t value)
116 {
117     return circuit_->NewGate(circuit_->SwitchCase(value), { switchBranch });
118 }
119 
DefaultCase(GateRef switchBranch)120 GateRef CircuitBuilder::DefaultCase(GateRef switchBranch)
121 {
122     return circuit_->NewGate(circuit_->DefaultCase(), { switchBranch });
123 }
124 
DependRelay(GateRef state,GateRef depend)125 GateRef CircuitBuilder::DependRelay(GateRef state, GateRef depend)
126 {
127     return circuit_->NewGate(circuit_->DependRelay(), { state, depend });
128 }
129 
ReadSp()130 GateRef CircuitBuilder::ReadSp()
131 {
132     return circuit_->NewGate(circuit_->ReadSp(), MachineType::I64, GateType::NJSValue());
133 }
134 
Arguments(size_t index)135 GateRef CircuitBuilder::Arguments(size_t index)
136 {
137     auto argListOfCircuit = circuit_->GetArgRoot();
138     return GetCircuit()->NewArg(MachineType::I64, index, GateType::NJSValue(), argListOfCircuit);
139 }
140 
ObjectTypeCheck(GateType type,bool isHeapObject,GateRef gate,GateRef hclassIndex)141 GateRef CircuitBuilder::ObjectTypeCheck(GateType type, bool isHeapObject, GateRef gate, GateRef hclassIndex)
142 {
143     auto currentLabel = env_->GetCurrentLabel();
144     auto currentControl = currentLabel->GetControl();
145     auto currentDepend = currentLabel->GetDepend();
146     auto frameState = acc_.FindNearestFrameState(currentDepend);
147     ObjectTypeAccessor accessor(type, isHeapObject);
148     GateRef ret = GetCircuit()->NewGate(circuit_->ObjectTypeCheck(accessor.ToValue()), MachineType::I1,
149         {currentControl, currentDepend, gate, hclassIndex, frameState}, GateType::NJSValue());
150     currentLabel->SetControl(ret);
151     currentLabel->SetDepend(ret);
152     return ret;
153 }
154 
ObjectTypeCompare(GateType type,bool isHeapObject,GateRef gate,GateRef hclassIndex)155 GateRef CircuitBuilder::ObjectTypeCompare(GateType type, bool isHeapObject, GateRef gate, GateRef hclassIndex)
156 {
157     auto currentLabel = env_->GetCurrentLabel();
158     auto currentControl = currentLabel->GetControl();
159     auto currentDepend = currentLabel->GetDepend();
160     auto frameState = acc_.FindNearestFrameState(currentDepend);
161     ObjectTypeAccessor accessor(type, isHeapObject);
162     GateRef ret = GetCircuit()->NewGate(circuit_->ObjectTypeCompare(accessor.ToValue()), MachineType::I1,
163         {currentControl, currentDepend, gate, hclassIndex, frameState}, GateType::NJSValue());
164     currentLabel->SetControl(ret);
165     currentLabel->SetDepend(ret);
166     return ret;
167 }
168 
HeapObjectCheck(GateRef gate,GateRef frameState)169 GateRef CircuitBuilder::HeapObjectCheck(GateRef gate, GateRef frameState)
170 {
171     auto currentLabel = env_->GetCurrentLabel();
172     auto currentControl = currentLabel->GetControl();
173     auto currentDepend = currentLabel->GetDepend();
174     GateRef ret = GetCircuit()->NewGate(circuit_->HeapObjectCheck(),
175         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
176     currentLabel->SetControl(ret);
177     currentLabel->SetDepend(ret);
178     return ret;
179 }
180 
StableArrayCheck(GateRef gate,ElementsKind kind,ArrayMetaDataAccessor::Mode mode)181 GateRef CircuitBuilder::StableArrayCheck(GateRef gate, ElementsKind kind, ArrayMetaDataAccessor::Mode mode)
182 {
183     auto currentLabel = env_->GetCurrentLabel();
184     auto currentControl = currentLabel->GetControl();
185     auto currentDepend = currentLabel->GetDepend();
186     auto frameState = acc_.FindNearestFrameState(currentDepend);
187     ArrayMetaDataAccessor accessor(kind, mode);
188     GateRef ret = GetCircuit()->NewGate(circuit_->StableArrayCheck(accessor.ToValue()),
189         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
190     currentLabel->SetControl(ret);
191     currentLabel->SetDepend(ret);
192     return ret;
193 }
194 
COWArrayCheck(GateRef gate)195 GateRef CircuitBuilder::COWArrayCheck(GateRef gate)
196 {
197     auto currentLabel = env_->GetCurrentLabel();
198     auto currentControl = currentLabel->GetControl();
199     auto currentDepend = currentLabel->GetDepend();
200     auto frameState = acc_.FindNearestFrameState(currentDepend);
201     GateRef ret = GetCircuit()->NewGate(circuit_->COWArrayCheck(),
202         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
203     currentLabel->SetControl(ret);
204     currentLabel->SetDepend(ret);
205     return ret;
206 }
207 
HClassStableArrayCheck(GateRef gate,GateRef frameState,ArrayMetaDataAccessor accessor)208 GateRef CircuitBuilder::HClassStableArrayCheck(GateRef gate, GateRef frameState, ArrayMetaDataAccessor accessor)
209 {
210     auto currentLabel = env_->GetCurrentLabel();
211     auto currentControl = currentLabel->GetControl();
212     auto currentDepend = currentLabel->GetDepend();
213     GateRef ret = GetCircuit()->NewGate(circuit_->HClassStableArrayCheck(accessor.ToValue()),
214         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
215     currentLabel->SetControl(ret);
216     currentLabel->SetDepend(ret);
217     return ret;
218 }
219 
ArrayGuardianCheck(GateRef frameState)220 GateRef CircuitBuilder::ArrayGuardianCheck(GateRef frameState)
221 {
222     auto currentLabel = env_->GetCurrentLabel();
223     auto currentControl = currentLabel->GetControl();
224     auto currentDepend = currentLabel->GetDepend();
225     GateRef ret = GetCircuit()->NewGate(circuit_->ArrayGuardianCheck(),
226         MachineType::I1, {currentControl, currentDepend, frameState}, GateType::NJSValue());
227     currentLabel->SetControl(ret);
228     currentLabel->SetDepend(ret);
229     return ret;
230 }
231 
TypedArrayCheck(GateType type,GateRef gate)232 GateRef CircuitBuilder::TypedArrayCheck(GateType type, GateRef gate)
233 {
234     auto currentLabel = env_->GetCurrentLabel();
235     auto currentControl = currentLabel->GetControl();
236     auto currentDepend = currentLabel->GetDepend();
237     auto frameState = acc_.FindNearestFrameState(currentDepend);
238     GateRef ret = GetCircuit()->NewGate(circuit_->TypedArrayCheck(static_cast<size_t>(type.Value())),
239         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
240     currentLabel->SetControl(ret);
241     currentLabel->SetDepend(ret);
242     return ret;
243 }
244 
LoadTypedArrayLength(GateType type,GateRef gate)245 GateRef CircuitBuilder::LoadTypedArrayLength(GateType type, GateRef gate)
246 {
247     auto currentLabel = env_->GetCurrentLabel();
248     auto currentControl = currentLabel->GetControl();
249     auto currentDepend = currentLabel->GetDepend();
250     GateRef ret = GetCircuit()->NewGate(circuit_->LoadTypedArrayLength(static_cast<size_t>(type.Value())),
251         MachineType::I64, {currentControl, currentDepend, gate}, GateType::IntType());
252     currentLabel->SetControl(ret);
253     currentLabel->SetDepend(ret);
254     return ret;
255 }
256 
RangeGuard(GateRef gate,uint32_t left,uint32_t right)257 GateRef CircuitBuilder::RangeGuard(GateRef gate, uint32_t left, uint32_t right)
258 {
259     auto currentLabel = env_->GetCurrentLabel();
260     auto currentControl = currentLabel->GetControl();
261     auto currentDepend = currentLabel->GetDepend();
262     UInt32PairAccessor accessor(left, right);
263     GateRef ret = GetCircuit()->NewGate(circuit_->RangeGuard(accessor.ToValue()),
264         MachineType::I64, {currentControl, currentDepend, gate}, GateType::IntType());
265     currentLabel->SetControl(ret);
266     currentLabel->SetDepend(ret);
267     return ret;
268 }
269 
IndexCheck(GateType type,GateRef gate,GateRef index)270 GateRef CircuitBuilder::IndexCheck(GateType type, GateRef gate, GateRef index)
271 {
272     auto currentLabel = env_->GetCurrentLabel();
273     auto currentControl = currentLabel->GetControl();
274     auto currentDepend = currentLabel->GetDepend();
275     auto frameState = acc_.FindNearestFrameState(currentDepend);
276     GateRef ret = GetCircuit()->NewGate(circuit_->IndexCheck(static_cast<size_t>(type.Value())),
277         MachineType::I64, {currentControl, currentDepend, gate, index, frameState}, GateType::IntType());
278     currentLabel->SetControl(ret);
279     currentLabel->SetDepend(ret);
280     return ret;
281 }
282 
IsJsCOWArray(GateRef obj)283 GateRef CircuitBuilder::IsJsCOWArray(GateRef obj)
284 {
285     // Elements of JSArray are shared and properties are not yet.
286     GateRef elements = GetElementsArray(obj);
287     GateRef objectType = GetObjectType(LoadHClass(elements));
288     return IsCOWArray(objectType);
289 }
290 
IsCOWArray(GateRef objectType)291 GateRef CircuitBuilder::IsCOWArray(GateRef objectType)
292 {
293     return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::COW_TAGGED_ARRAY)));
294 }
295 
GetElementsArray(GateRef object)296 GateRef CircuitBuilder::GetElementsArray(GateRef object)
297 {
298     GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
299     return Load(VariableType::JS_POINTER(), object, elementsOffset);
300 }
301 
GetMachineTypeOfValueType(ValueType type)302 MachineType CircuitBuilder::GetMachineTypeOfValueType(ValueType type)
303 {
304     switch (type) {
305         case ValueType::BOOL:
306             return MachineType::I1;
307         case ValueType::INT32:
308             return MachineType::I32;
309         case ValueType::FLOAT64:
310             return MachineType::F64;
311         case ValueType::TAGGED_BOOLEAN:
312         case ValueType::TAGGED_INT:
313         case ValueType::TAGGED_DOUBLE:
314         case ValueType::TAGGED_NUMBER:
315             return MachineType::I64;
316         default:
317             return MachineType::NOVALUE;
318     }
319 }
320 
GetGateTypeOfValueType(ValueType type)321 GateType CircuitBuilder::GetGateTypeOfValueType(ValueType type)
322 {
323     switch (type) {
324         case ValueType::BOOL:
325         case ValueType::INT32:
326         case ValueType::FLOAT64:
327             return GateType::NJSValue();
328         case ValueType::TAGGED_BOOLEAN:
329             return GateType::BooleanType();
330         case ValueType::TAGGED_INT:
331             return GateType::IntType();
332         case ValueType::TAGGED_DOUBLE:
333             return GateType::DoubleType();
334         case ValueType::TAGGED_NUMBER:
335             return GateType::NumberType();
336         default:
337             return GateType::Empty();
338     }
339 }
340 
CheckAndConvert(GateRef gate,ValueType src,ValueType dst,ConvertSupport support)341 GateRef CircuitBuilder::CheckAndConvert(GateRef gate, ValueType src, ValueType dst, ConvertSupport support)
342 {
343     auto currentLabel = env_->GetCurrentLabel();
344     auto currentControl = currentLabel->GetControl();
345     auto currentDepend = currentLabel->GetDepend();
346     auto stateSplit = acc_.FindNearestStateSplit(currentDepend);
347     auto frameState = acc_.GetFrameState(stateSplit);
348     MachineType machineType = GetMachineTypeOfValueType(dst);
349     GateType gateType = GetGateTypeOfValueType(dst);
350     uint64_t value = ValuePairTypeAccessor::ToValue(src, dst, support);
351     GateRef ret = GetCircuit()->NewGate(circuit_->CheckAndConvert(value),
352         machineType, {currentControl, currentDepend, gate, frameState}, gateType);
353     currentLabel->SetControl(ret);
354     currentLabel->SetDepend(ret);
355     return ret;
356 }
357 
Convert(GateRef gate,ValueType src,ValueType dst)358 GateRef CircuitBuilder::Convert(GateRef gate, ValueType src, ValueType dst)
359 {
360     MachineType machineType = GetMachineTypeOfValueType(dst);
361     GateType gateType = GetGateTypeOfValueType(dst);
362     uint64_t value = ValuePairTypeAccessor::ToValue(src, dst);
363     GateRef ret = GetCircuit()->NewGate(circuit_->Convert(value), machineType, {gate}, gateType);
364     return ret;
365 }
366 
ConvertBoolToInt32(GateRef gate,ConvertSupport support)367 GateRef CircuitBuilder::ConvertBoolToInt32(GateRef gate, ConvertSupport support)
368 {
369     return CheckAndConvert(gate, ValueType::BOOL, ValueType::INT32, support);
370 }
371 
ConvertBoolToFloat64(GateRef gate,ConvertSupport support)372 GateRef CircuitBuilder::ConvertBoolToFloat64(GateRef gate, ConvertSupport support)
373 {
374     return CheckAndConvert(gate, ValueType::BOOL, ValueType::FLOAT64, support);
375 }
376 
ConvertInt32ToFloat64(GateRef gate)377 GateRef CircuitBuilder::ConvertInt32ToFloat64(GateRef gate)
378 {
379     return Convert(gate, ValueType::INT32, ValueType::FLOAT64);
380 }
381 
ConvertUInt32ToFloat64(GateRef gate)382 GateRef CircuitBuilder::ConvertUInt32ToFloat64(GateRef gate)
383 {
384     return Convert(gate, ValueType::UINT32, ValueType::FLOAT64);
385 }
386 
ConvertFloat64ToInt32(GateRef gate)387 GateRef CircuitBuilder::ConvertFloat64ToInt32(GateRef gate)
388 {
389     return Convert(gate, ValueType::FLOAT64, ValueType::INT32);
390 }
391 
ConvertBoolToTaggedBoolean(GateRef gate)392 GateRef CircuitBuilder::ConvertBoolToTaggedBoolean(GateRef gate)
393 {
394     return Convert(gate, ValueType::BOOL, ValueType::TAGGED_BOOLEAN);
395 }
396 
ConvertTaggedBooleanToBool(GateRef gate)397 GateRef CircuitBuilder::ConvertTaggedBooleanToBool(GateRef gate)
398 {
399     return Convert(gate, ValueType::TAGGED_BOOLEAN, ValueType::BOOL);
400 }
401 
ConvertInt32ToTaggedInt(GateRef gate)402 GateRef CircuitBuilder::ConvertInt32ToTaggedInt(GateRef gate)
403 {
404     return Convert(gate, ValueType::INT32, ValueType::TAGGED_INT);
405 }
406 
ConvertUInt32ToTaggedNumber(GateRef gate)407 GateRef CircuitBuilder::ConvertUInt32ToTaggedNumber(GateRef gate)
408 {
409     return Convert(gate, ValueType::UINT32, ValueType::TAGGED_NUMBER);
410 }
411 
ConvertInt32ToBool(GateRef gate)412 GateRef CircuitBuilder::ConvertInt32ToBool(GateRef gate)
413 {
414     return Convert(gate, ValueType::INT32, ValueType::BOOL);
415 }
416 
ConvertUInt32ToBool(GateRef gate)417 GateRef CircuitBuilder::ConvertUInt32ToBool(GateRef gate)
418 {
419     return Convert(gate, ValueType::UINT32, ValueType::BOOL);
420 }
421 
ConvertFloat64ToBool(GateRef gate)422 GateRef CircuitBuilder::ConvertFloat64ToBool(GateRef gate)
423 {
424     return Convert(gate, ValueType::FLOAT64, ValueType::BOOL);
425 }
426 
CheckTaggedBooleanAndConvertToBool(GateRef gate)427 GateRef CircuitBuilder::CheckTaggedBooleanAndConvertToBool(GateRef gate)
428 {
429     return CheckAndConvert(gate, ValueType::TAGGED_BOOLEAN, ValueType::BOOL);
430 }
431 
CheckTaggedNumberAndConvertToBool(GateRef gate)432 GateRef CircuitBuilder::CheckTaggedNumberAndConvertToBool(GateRef gate)
433 {
434     return CheckAndConvert(gate, ValueType::TAGGED_NUMBER, ValueType::BOOL);
435 }
436 
ConvertFloat64ToTaggedDouble(GateRef gate)437 GateRef CircuitBuilder::ConvertFloat64ToTaggedDouble(GateRef gate)
438 {
439     return Convert(gate, ValueType::FLOAT64, ValueType::TAGGED_DOUBLE);
440 }
441 
CheckUInt32AndConvertToInt32(GateRef gate)442 GateRef CircuitBuilder::CheckUInt32AndConvertToInt32(GateRef gate)
443 {
444     return CheckAndConvert(gate, ValueType::UINT32, ValueType::INT32);
445 }
446 
CheckTaggedIntAndConvertToInt32(GateRef gate)447 GateRef CircuitBuilder::CheckTaggedIntAndConvertToInt32(GateRef gate)
448 {
449     return CheckAndConvert(gate, ValueType::TAGGED_INT, ValueType::INT32);
450 }
451 
CheckTaggedDoubleAndConvertToInt32(GateRef gate)452 GateRef CircuitBuilder::CheckTaggedDoubleAndConvertToInt32(GateRef gate)
453 {
454     return CheckAndConvert(gate, ValueType::TAGGED_DOUBLE, ValueType::INT32);
455 }
456 
CheckTaggedNumberAndConvertToInt32(GateRef gate)457 GateRef CircuitBuilder::CheckTaggedNumberAndConvertToInt32(GateRef gate)
458 {
459     return CheckAndConvert(gate, ValueType::TAGGED_NUMBER, ValueType::INT32);
460 }
461 
CheckTaggedIntAndConvertToFloat64(GateRef gate)462 GateRef CircuitBuilder::CheckTaggedIntAndConvertToFloat64(GateRef gate)
463 {
464     return CheckAndConvert(gate, ValueType::TAGGED_INT, ValueType::FLOAT64);
465 }
466 
CheckTaggedDoubleAndConvertToFloat64(GateRef gate)467 GateRef CircuitBuilder::CheckTaggedDoubleAndConvertToFloat64(GateRef gate)
468 {
469     return CheckAndConvert(gate, ValueType::TAGGED_DOUBLE, ValueType::FLOAT64);
470 }
471 
CheckTaggedNumberAndConvertToFloat64(GateRef gate)472 GateRef CircuitBuilder::CheckTaggedNumberAndConvertToFloat64(GateRef gate)
473 {
474     return CheckAndConvert(gate, ValueType::TAGGED_NUMBER, ValueType::FLOAT64);
475 }
476 
TryPrimitiveTypeCheck(GateType type,GateRef gate)477 GateRef CircuitBuilder::TryPrimitiveTypeCheck(GateType type, GateRef gate)
478 {
479     if (acc_.GetOpCode(gate) == OpCode::CONSTANT) {
480         return Circuit::NullGate();
481     }
482     auto currentLabel = env_->GetCurrentLabel();
483     auto currentControl = currentLabel->GetControl();
484     auto currentDepend = currentLabel->GetDepend();
485     auto frameState = acc_.FindNearestFrameState(currentDepend);
486     GateRef ret = GetCircuit()->NewGate(circuit_->PrimitiveTypeCheck(static_cast<size_t>(type.Value())),
487         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
488     currentLabel->SetControl(ret);
489     currentLabel->SetDepend(ret);
490     return ret;
491 }
492 
CallTargetCheck(GateRef gate,GateRef function,GateRef id,GateRef param,const char * comment)493 GateRef CircuitBuilder::CallTargetCheck(GateRef gate, GateRef function, GateRef id, GateRef param, const char* comment)
494 {
495     auto currentLabel = env_->GetCurrentLabel();
496     auto currentControl = currentLabel->GetControl();
497     auto currentDepend = currentLabel->GetDepend();
498     auto frameState = acc_.GetFrameState(gate);
499     GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallCheck(),
500                                         MachineType::I1,
501                                         { currentControl, currentDepend, function, id, param, frameState},
502                                         GateType::NJSValue(),
503                                         comment);
504     currentLabel->SetControl(ret);
505     currentLabel->SetDepend(ret);
506     return ret;
507 }
508 
JSCallTargetFromDefineFuncCheck(GateType type,GateRef func,GateRef gate)509 GateRef CircuitBuilder::JSCallTargetFromDefineFuncCheck(GateType type, GateRef func, GateRef gate)
510 {
511     auto currentLabel = env_->GetCurrentLabel();
512     auto currentControl = currentLabel->GetControl();
513     auto currentDepend = currentLabel->GetDepend();
514     auto frameState = acc_.GetFrameState(gate);
515     GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(1, static_cast<size_t>(type.Value()),
516         TypedCallTargetCheckOp::JSCALL_IMMEDIATE_AFTER_FUNC_DEF),
517         MachineType::I1, {currentControl, currentDepend, func, frameState}, GateType::NJSValue());
518     currentLabel->SetControl(ret);
519     currentLabel->SetDepend(ret);
520     return ret;
521 }
522 
DeoptCheck(GateRef condition,GateRef frameState,DeoptType type)523 GateRef CircuitBuilder::DeoptCheck(GateRef condition, GateRef frameState, DeoptType type)
524 {
525     std::string comment = Deoptimizier::DisplayItems(type);
526     auto currentLabel = env_->GetCurrentLabel();
527     auto currentControl = currentLabel->GetControl();
528     auto currentDepend = currentLabel->GetDepend();
529     ASSERT(acc_.GetOpCode(frameState) == OpCode::FRAME_STATE);
530     GateRef ret = GetCircuit()->NewGate(circuit_->DeoptCheck(),
531         MachineType::I1, { currentControl, currentDepend, condition,
532         frameState, Int64(static_cast<int64_t>(type))}, GateType::NJSValue(), comment.c_str());
533     currentLabel->SetControl(ret);
534     currentLabel->SetDepend(ret);
535     return ret;
536 }
537 
TypedNewAllocateThis(GateRef ctor,GateRef hclassIndex,GateRef frameState)538 GateRef CircuitBuilder::TypedNewAllocateThis(GateRef ctor, GateRef hclassIndex, GateRef frameState)
539 {
540     auto currentLabel = env_->GetCurrentLabel();
541     auto currentControl = currentLabel->GetControl();
542     auto currentDepend = currentLabel->GetDepend();
543     GateRef ret = GetCircuit()->NewGate(circuit_->TypedNewAllocateThis(),
544         MachineType::ANYVALUE, {currentControl, currentDepend, ctor, hclassIndex, frameState}, GateType::TaggedValue());
545     currentLabel->SetControl(ret);
546     currentLabel->SetDepend(ret);
547     return ret;
548 }
549 
TypedSuperAllocateThis(GateRef superCtor,GateRef newTarget,GateRef frameState)550 GateRef CircuitBuilder::TypedSuperAllocateThis(GateRef superCtor, GateRef newTarget, GateRef frameState)
551 {
552     auto currentLabel = env_->GetCurrentLabel();
553     auto currentControl = currentLabel->GetControl();
554     auto currentDepend = currentLabel->GetDepend();
555     GateRef ret = GetCircuit()->NewGate(circuit_->TypedSuperAllocateThis(), MachineType::ANYVALUE,
556         {currentControl, currentDepend, superCtor, newTarget, frameState}, GateType::TaggedValue());
557     currentLabel->SetControl(ret);
558     currentLabel->SetDepend(ret);
559     return ret;
560 }
561 
GetSuperConstructor(GateRef ctor)562 GateRef CircuitBuilder::GetSuperConstructor(GateRef ctor)
563 {
564     auto currentLabel = env_->GetCurrentLabel();
565     auto currentControl = currentLabel->GetControl();
566     auto currentDepend = currentLabel->GetDepend();
567     auto ret = GetCircuit()->NewGate(circuit_->GetSuperConstructor(), MachineType::ANYVALUE,
568                                      { currentControl, currentDepend, ctor }, GateType::TaggedValue());
569     currentLabel->SetControl(ret);
570     currentLabel->SetDepend(ret);
571     return ret;
572 }
573 
TypedCallOperator(GateRef hirGate,MachineType type,const std::initializer_list<GateRef> & args)574 GateRef CircuitBuilder::TypedCallOperator(GateRef hirGate, MachineType type, const std::initializer_list<GateRef>& args)
575 {
576     ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
577     auto numValueIn = args.size() - 2; // 2: state & depend
578     uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
579     ASSERT(pcOffset != 0);
580     return GetCircuit()->NewGate(circuit_->TypedCallBuiltin(numValueIn, pcOffset), type, args, GateType::AnyType());
581 }
582 
AddWithOverflow(GateRef left,GateRef right)583 GateRef CircuitBuilder::AddWithOverflow(GateRef left, GateRef right)
584 {
585     return GetCircuit()->NewGate(circuit_->AddWithOverflow(), MachineType::I64, {left, right}, GateType::AnyType());
586 }
587 
SubWithOverflow(GateRef left,GateRef right)588 GateRef CircuitBuilder::SubWithOverflow(GateRef left, GateRef right)
589 {
590     return GetCircuit()->NewGate(circuit_->SubWithOverflow(), MachineType::I64, {left, right}, GateType::AnyType());
591 }
592 
MulWithOverflow(GateRef left,GateRef right)593 GateRef CircuitBuilder::MulWithOverflow(GateRef left, GateRef right)
594 {
595     return GetCircuit()->NewGate(circuit_->MulWithOverflow(), MachineType::I64, {left, right}, GateType::AnyType());
596 }
597 
ExtractValue(MachineType mt,GateRef pointer,GateRef index)598 GateRef CircuitBuilder::ExtractValue(MachineType mt, GateRef pointer, GateRef index)
599 {
600     ASSERT(acc_.GetOpCode(index) == OpCode::CONSTANT);
601     ASSERT(acc_.GetMachineType(index) == MachineType::I32);
602     return GetCircuit()->NewGate(circuit_->ExtractValue(), mt, {pointer, index}, GateType::NJSValue());
603 }
604 
Sqrt(GateRef param)605 GateRef CircuitBuilder::Sqrt(GateRef param)
606 {
607     return GetCircuit()->NewGate(circuit_->Sqrt(), MachineType::F64, {param}, GateType::DoubleType());
608 }
609 
Int32CheckRightIsZero(GateRef right)610 GateRef CircuitBuilder::Int32CheckRightIsZero(GateRef right)
611 {
612     auto currentLabel = env_->GetCurrentLabel();
613     auto currentControl = currentLabel->GetControl();
614     auto currentDepend = currentLabel->GetDepend();
615     auto frameState = acc_.FindNearestFrameState(currentDepend);
616     GateRef ret = GetCircuit()->NewGate(circuit_->Int32CheckRightIsZero(),
617     MachineType::I1, {currentControl, currentDepend, right, frameState}, GateType::NJSValue());
618     currentLabel->SetControl(ret);
619     currentLabel->SetDepend(ret);
620     return ret;
621 }
622 
Float64CheckRightIsZero(GateRef right)623 GateRef CircuitBuilder::Float64CheckRightIsZero(GateRef right)
624 {
625     auto currentLabel = env_->GetCurrentLabel();
626     auto currentControl = currentLabel->GetControl();
627     auto currentDepend = currentLabel->GetDepend();
628     auto frameState = acc_.FindNearestFrameState(currentDepend);
629     GateRef ret = GetCircuit()->NewGate(circuit_->Float64CheckRightIsZero(),
630     MachineType::I1, {currentControl, currentDepend, right, frameState}, GateType::NJSValue());
631     currentLabel->SetControl(ret);
632     currentLabel->SetDepend(ret);
633     return ret;
634 }
635 
LexVarIsHoleCheck(GateRef value)636 GateRef CircuitBuilder::LexVarIsHoleCheck(GateRef value)
637 {
638     auto currentLabel = env_->GetCurrentLabel();
639     auto currentControl = currentLabel->GetControl();
640     auto currentDepend = currentLabel->GetDepend();
641     auto frameState = acc_.FindNearestFrameState(currentDepend);
642     GateRef ret = GetCircuit()->NewGate(circuit_->LexVarIsHoleCheck(),
643     MachineType::I1, {currentControl, currentDepend, value, frameState}, GateType::NJSValue());
644     currentLabel->SetControl(ret);
645     currentLabel->SetDepend(ret);
646     return ret;
647 }
648 
ValueCheckNegOverflow(GateRef value)649 GateRef CircuitBuilder::ValueCheckNegOverflow(GateRef value)
650 {
651     auto currentLabel = env_->GetCurrentLabel();
652     auto currentControl = currentLabel->GetControl();
653     auto currentDepend = currentLabel->GetDepend();
654     auto frameState = acc_.FindNearestFrameState(currentDepend);
655     GateRef ret = GetCircuit()->NewGate(circuit_->ValueCheckNegOverflow(),
656     MachineType::I1, {currentControl, currentDepend, value, frameState}, GateType::NJSValue());
657     currentLabel->SetControl(ret);
658     currentLabel->SetDepend(ret);
659     return ret;
660 }
661 
OverflowCheck(GateRef value)662 GateRef CircuitBuilder::OverflowCheck(GateRef value)
663 {
664     auto currentLabel = env_->GetCurrentLabel();
665     auto currentControl = currentLabel->GetControl();
666     auto currentDepend = currentLabel->GetDepend();
667     auto frameState = acc_.FindNearestFrameState(currentDepend);
668     GateRef ret = GetCircuit()->NewGate(circuit_->OverflowCheck(),
669         MachineType::I1, {currentControl, currentDepend, value, frameState}, GateType::IntType());
670     currentLabel->SetControl(ret);
671     currentLabel->SetDepend(ret);
672     return ret;
673 }
674 
Int32UnsignedUpperBoundCheck(GateRef value,GateRef upperBound)675 GateRef CircuitBuilder::Int32UnsignedUpperBoundCheck(GateRef value, GateRef upperBound)
676 {
677     auto currentLabel = env_->GetCurrentLabel();
678     auto currentControl = currentLabel->GetControl();
679     auto currentDepend = currentLabel->GetDepend();
680     auto frameState = acc_.FindNearestFrameState(currentDepend);
681     GateRef ret = GetCircuit()->NewGate(circuit_->Int32UnsignedUpperBoundCheck(),
682         MachineType::I1, {currentControl, currentDepend, value, upperBound, frameState}, GateType::IntType());
683     currentLabel->SetControl(ret);
684     currentLabel->SetDepend(ret);
685     return ret;
686 }
687 
Int32DivWithCheck(GateRef left,GateRef right)688 GateRef CircuitBuilder::Int32DivWithCheck(GateRef left, GateRef right)
689 {
690     auto currentLabel = env_->GetCurrentLabel();
691     auto currentControl = currentLabel->GetControl();
692     auto currentDepend = currentLabel->GetDepend();
693     auto frameState = acc_.FindNearestFrameState(currentDepend);
694     GateRef ret = GetCircuit()->NewGate(circuit_->Int32DivWithCheck(),
695         MachineType::I32, {currentControl, currentDepend, left, right, frameState}, GateType::NJSValue());
696     currentLabel->SetControl(ret);
697     currentLabel->SetDepend(ret);
698     return ret;
699 }
700 
TypeConvert(MachineType type,GateType typeFrom,GateType typeTo,const std::vector<GateRef> & inList)701 GateRef CircuitBuilder::TypeConvert(MachineType type, GateType typeFrom, GateType typeTo,
702                                     const std::vector<GateRef>& inList)
703 {
704     // merge types of valueIns before and after convertion
705     uint64_t operandTypes = GatePairTypeAccessor::ToValue(typeFrom, typeTo);
706     return GetCircuit()->NewGate(circuit_->TypedConvert(operandTypes),
707         type, inList.size(), inList.data(), GateType::AnyType());
708 }
709 
TypedConditionJump(MachineType type,TypedJumpOp jumpOp,GateType typeVal,const std::vector<GateRef> & inList)710 GateRef CircuitBuilder::TypedConditionJump(MachineType type, TypedJumpOp jumpOp, GateType typeVal,
711                                            const std::vector<GateRef>& inList)
712 {
713     uint64_t value = TypedJumpAccessor::ToValue(typeVal, jumpOp);
714     return GetCircuit()->NewGate(circuit_->TypedConditionJump(value),
715         type, inList.size(), inList.data(), GateType::Empty());
716 }
717 
Int8(int8_t val)718 GateRef CircuitBuilder::Int8(int8_t val)
719 {
720     return GetCircuit()->GetConstantGate(MachineType::I8, val, GateType::NJSValue());
721 }
722 
Int16(int16_t val)723 GateRef CircuitBuilder::Int16(int16_t val)
724 {
725     return GetCircuit()->GetConstantGate(MachineType::I16, val, GateType::NJSValue());
726 }
727 
Int32(int32_t val)728 GateRef CircuitBuilder::Int32(int32_t val)
729 {
730     return GetCircuit()->GetConstantGate(MachineType::I32, static_cast<BitField>(val), GateType::NJSValue());
731 }
732 
Int64(int64_t val)733 GateRef CircuitBuilder::Int64(int64_t val)
734 {
735     return GetCircuit()->GetConstantGate(MachineType::I64, val, GateType::NJSValue());
736 }
737 
IntPtr(int64_t val)738 GateRef CircuitBuilder::IntPtr(int64_t val)
739 {
740     return GetCircuit()->GetConstantGate(MachineType::ARCH, val, GateType::NJSValue());
741 }
742 
StringPtr(const std::string & str)743 GateRef CircuitBuilder::StringPtr(const std::string &str)
744 {
745     return GetCircuit()->GetConstantStringGate(MachineType::ARCH, str, GateType::NJSValue());
746 }
747 
RelocatableData(uint64_t val)748 GateRef CircuitBuilder::RelocatableData(uint64_t val)
749 {
750     return GetCircuit()->NewGate(circuit_->RelocatableData(val),
751         MachineType::ARCH, GateType::TaggedValue());
752 }
753 
Boolean(bool val)754 GateRef CircuitBuilder::Boolean(bool val)
755 {
756     return GetCircuit()->GetConstantGate(MachineType::I1, val ? 1 : 0, GateType::NJSValue());
757 }
758 
Double(double val)759 GateRef CircuitBuilder::Double(double val)
760 {
761     return GetCircuit()->GetConstantGate(MachineType::F64, base::bit_cast<int64_t>(val), GateType::NJSValue());
762 }
763 
HoleConstant()764 GateRef CircuitBuilder::HoleConstant()
765 {
766     auto type = GateType::TaggedValue();
767     return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_HOLE, type);
768 }
769 
NullPtrConstant()770 GateRef CircuitBuilder::NullPtrConstant()
771 {
772     auto type = GateType::TaggedValue();
773     return GetCircuit()->GetConstantGate(MachineType::I64, 0u, type);
774 }
775 
NullConstant()776 GateRef CircuitBuilder::NullConstant()
777 {
778     auto type = GateType::TaggedValue();
779     return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_NULL, type);
780 }
781 
ExceptionConstant()782 GateRef CircuitBuilder::ExceptionConstant()
783 {
784     auto type = GateType::TaggedValue();
785     return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_EXCEPTION, type);
786 }
787 
GetMachineTypeFromVariableType(VariableType type)788 MachineType CircuitBuilder::GetMachineTypeFromVariableType(VariableType type)
789 {
790     return type.GetMachineType();
791 }
792 
BinaryArithmetic(const GateMetaData * meta,MachineType machineType,GateRef left,GateRef right,GateType gateType)793 GateRef CircuitBuilder::BinaryArithmetic(const GateMetaData* meta, MachineType machineType,
794                                          GateRef left, GateRef right, GateType gateType)
795 {
796     auto circuit = GetCircuit();
797     if (gateType == GateType::Empty()) {
798         gateType = acc_.GetGateType(left);
799     }
800     return circuit->NewGate(meta, machineType, { left, right }, gateType);
801 }
802 
BinaryCmp(const GateMetaData * meta,GateRef left,GateRef right)803 GateRef CircuitBuilder::BinaryCmp(const GateMetaData* meta, GateRef left, GateRef right)
804 {
805     return GetCircuit()->NewGate(meta, MachineType::I1, { left, right }, GateType::NJSValue());
806 }
807 
CallBCHandler(GateRef glue,GateRef target,const std::vector<GateRef> & args,const char * comment)808 GateRef CircuitBuilder::CallBCHandler(GateRef glue, GateRef target, const std::vector<GateRef> &args,
809                                       const char* comment)
810 {
811     ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame());
812     const CallSignature *cs = BytecodeStubCSigns::BCHandler();
813     ASSERT(cs->IsBCStub());
814     auto label = GetCurrentLabel();
815     auto depend = label->GetDepend();
816     GateRef result = Call(cs, glue, target, depend, args, Circuit::NullGate(), comment);
817     return result;
818 }
819 
CallBuiltin(GateRef glue,GateRef target,const std::vector<GateRef> & args,const char * comment)820 GateRef CircuitBuilder::CallBuiltin(GateRef glue, GateRef target, const std::vector<GateRef> &args,
821                                     const char* comment)
822 {
823     ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame());
824     const CallSignature *cs = BuiltinsStubCSigns::BuiltinsCSign();
825     ASSERT(cs->IsBuiltinsStub());
826     auto label = GetCurrentLabel();
827     auto depend = label->GetDepend();
828     GateRef result = Call(cs, glue, target, depend, args, Circuit::NullGate(), comment);
829     return result;
830 }
831 
CallBuiltinWithArgv(GateRef glue,GateRef target,const std::vector<GateRef> & args,const char * comment)832 GateRef CircuitBuilder::CallBuiltinWithArgv(GateRef glue, GateRef target, const std::vector<GateRef> &args,
833                                             const char* comment)
834 {
835     ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame());
836     const CallSignature *cs = BuiltinsStubCSigns::BuiltinsWithArgvCSign();
837     ASSERT(cs->IsBuiltinsWithArgvStub());
838     auto label = GetCurrentLabel();
839     auto depend = label->GetDepend();
840     GateRef result = Call(cs, glue, target, depend, args, Circuit::NullGate(), comment);
841     return result;
842 }
843 
CallBCDebugger(GateRef glue,GateRef target,const std::vector<GateRef> & args,const char * comment)844 GateRef CircuitBuilder::CallBCDebugger(GateRef glue, GateRef target, const std::vector<GateRef> &args,
845                                        const char* comment)
846 {
847     ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame());
848     const CallSignature *cs = BytecodeStubCSigns::BCDebuggerHandler();
849     ASSERT(cs->IsBCDebuggerStub());
850     auto label = GetCurrentLabel();
851     auto depend = label->GetDepend();
852     GateRef result = Call(cs, glue, target, depend, args, Circuit::NullGate(), comment);
853     return result;
854 }
855 
CallRuntime(GateRef glue,int index,GateRef depend,const std::vector<GateRef> & args,GateRef hirGate,const char * comment)856 GateRef CircuitBuilder::CallRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args,
857                                     GateRef hirGate, const char* comment)
858 {
859     GateRef target = IntPtr(index);
860     const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
861     ASSERT(cs->IsRuntimeStub());
862     auto label = GetCurrentLabel();
863     if (depend == Gate::InvalidGateRef) {
864         depend = label->GetDepend();
865     }
866     GateRef filteredHirGate = Circuit::NullGate();
867     if (GetCircuit()->IsOptimizedJSFunctionFrame()) {
868         ASSERT(hirGate != Circuit::NullGate());
869         filteredHirGate = hirGate;
870     }
871     GateRef result = Call(cs, glue, target, depend, args, filteredHirGate, comment);
872     return result;
873 }
874 
CallRuntimeVarargs(GateRef glue,int index,GateRef argc,GateRef argv,const char * comment)875 GateRef CircuitBuilder::CallRuntimeVarargs(GateRef glue, int index, GateRef argc, GateRef argv, const char* comment)
876 {
877     ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame());
878     const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntimeWithArgv));
879     GateRef target = IntPtr(index);
880     auto label = GetCurrentLabel();
881     auto depend = label->GetDepend();
882     ASSERT(cs->IsRuntimeVAStub());
883     GateRef result = Call(cs, glue, target, depend, {argc, argv}, Circuit::NullGate(), comment);
884     return result;
885 }
886 
CallNGCRuntime(GateRef glue,int index,GateRef depend,const std::vector<GateRef> & args,GateRef hirGate,const char * comment)887 GateRef CircuitBuilder::CallNGCRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args,
888                                        GateRef hirGate, const char* comment)
889 {
890     const CallSignature *cs = RuntimeStubCSigns::Get(index);
891     ASSERT(cs->IsRuntimeNGCStub());
892     GateRef target = IntPtr(index);
893     auto label = GetCurrentLabel();
894     if (depend == Gate::InvalidGateRef) {
895         depend = label->GetDepend();
896     }
897     GateRef filteredHirGate = Circuit::NullGate();
898     if (GetCircuit()->IsOptimizedJSFunctionFrame() && RuntimeStubCSigns::IsAsmStub(index)) {
899         ASSERT(hirGate != Circuit::NullGate());
900         filteredHirGate = hirGate;
901     }
902     GateRef result = Call(cs, glue, target, depend, args, filteredHirGate, comment);
903     return result;
904 }
905 
CallNGCRuntime(GateRef glue,GateRef gate,int index,const std::vector<GateRef> & args,bool useLabel)906 GateRef CircuitBuilder::CallNGCRuntime(GateRef glue, GateRef gate, int index, const std::vector<GateRef> &args,
907                                        bool useLabel)
908 {
909     const std::string name = RuntimeStubCSigns::GetRTName(index);
910     if (useLabel) {
911         GateRef result = CallNGCRuntime(glue, index, Gate::InvalidGateRef, args, gate, name.c_str());
912         return result;
913     } else {
914         const CallSignature *cs = RuntimeStubCSigns::Get(index);
915         GateRef target = IntPtr(index);
916         GateRef result = Call(cs, glue, target, GetDepend(), args, gate, name.c_str());
917         return result;
918     }
919 }
920 
StartCallTimer(GateRef glue,GateRef gate,const std::vector<GateRef> & args,bool useLabel)921 void CircuitBuilder::StartCallTimer(GateRef glue, GateRef gate, const std::vector<GateRef> &args, bool useLabel)
922 {
923     (void)glue;
924     (void)gate;
925     (void)args;
926     (void)useLabel;
927 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
928     CallNGCRuntime(glue, gate, RTSTUB_ID(StartCallTimer), args, useLabel);
929 #endif
930 }
931 
EndCallTimer(GateRef glue,GateRef gate,const std::vector<GateRef> & args,bool useLabel)932 void CircuitBuilder::EndCallTimer(GateRef glue, GateRef gate, const std::vector<GateRef> &args, bool useLabel)
933 {
934     (void)glue;
935     (void)gate;
936     (void)args;
937     (void)useLabel;
938 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
939     CallNGCRuntime(glue, gate, RTSTUB_ID(EndCallTimer), args, useLabel);
940 #endif
941 }
942 
FastCallOptimized(GateRef glue,GateRef code,GateRef depend,const std::vector<GateRef> & args,GateRef hirGate)943 GateRef CircuitBuilder::FastCallOptimized(GateRef glue, GateRef code, GateRef depend, const std::vector<GateRef> &args,
944                                           GateRef hirGate)
945 {
946     const CallSignature *cs = RuntimeStubCSigns::GetOptimizedFastCallSign();
947     ASSERT(cs->IsOptimizedFastCallStub());
948     auto label = GetCurrentLabel();
949     if (depend == Gate::InvalidGateRef) {
950         depend = label->GetDepend();
951     }
952     GateRef filteredHirGate = Circuit::NullGate();
953     if (GetCircuit()->IsOptimizedJSFunctionFrame()) {
954         ASSERT(hirGate != Circuit::NullGate());
955         filteredHirGate = hirGate;
956     }
957     GateRef result = Call(cs, glue, code, depend, args, filteredHirGate);
958     return result;
959 }
960 
CallOptimized(GateRef glue,GateRef code,GateRef depend,const std::vector<GateRef> & args,GateRef hirGate)961 GateRef CircuitBuilder::CallOptimized(GateRef glue, GateRef code, GateRef depend, const std::vector<GateRef> &args,
962                                       GateRef hirGate)
963 {
964     const CallSignature *cs = RuntimeStubCSigns::GetOptimizedCallSign();
965     ASSERT(cs->IsOptimizedStub());
966     auto label = GetCurrentLabel();
967     if (depend == Gate::InvalidGateRef) {
968         depend = label->GetDepend();
969     }
970     GateRef filteredHirGate = Circuit::NullGate();
971     if (GetCircuit()->IsOptimizedJSFunctionFrame()) {
972         ASSERT(hirGate != Circuit::NullGate());
973         filteredHirGate = hirGate;
974     }
975     GateRef result = Call(cs, glue, code, depend, args, filteredHirGate);
976     return result;
977 }
978 
CallStub(GateRef glue,GateRef hirGate,int index,const std::vector<GateRef> & args,const char * comment)979 GateRef CircuitBuilder::CallStub(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args,
980                                  const char* comment)
981 {
982     const CallSignature *cs = CommonStubCSigns::Get(index);
983     ASSERT(cs->IsCommonStub());
984     GateRef target = IntPtr(index);
985     auto label = GetCurrentLabel();
986     auto depend = label->GetDepend();
987     GateRef result;
988     if (GetCircuit()->IsOptimizedJSFunctionFrame()) {
989         ASSERT(hirGate != Circuit::NullGate());
990         result = Call(cs, glue, target, depend, args, hirGate, comment);
991     } else {
992         result = Call(cs, glue, target, depend, args, Circuit::NullGate(), comment);
993     }
994     return result;
995 }
996 
CallBuiltinRuntime(GateRef glue,GateRef depend,const std::vector<GateRef> & args,bool isNew,const char * comment)997 GateRef CircuitBuilder::CallBuiltinRuntime(GateRef glue, GateRef depend, const std::vector<GateRef> &args,
998                                            bool isNew, const char* comment)
999 {
1000     ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame());
1001     int index = 0;
1002     if (!isNew) {
1003         index = static_cast<int>(RTSTUB_ID(PushCallArgsAndDispatchNative));
1004     } else {
1005         index = static_cast<int>(RTSTUB_ID(PushCallNewAndDispatchNative));
1006     }
1007 
1008     const CallSignature *cs = RuntimeStubCSigns::Get(index);
1009     GateRef target = IntPtr(index);
1010     auto label = GetCurrentLabel();
1011     if (depend == Gate::InvalidGateRef) {
1012         depend = label->GetDepend();
1013     }
1014     GateRef result = Call(cs, glue, target, depend, args, Circuit::NullGate(), comment);
1015     return result;
1016 }
1017 
Call(const CallSignature * cs,GateRef glue,GateRef target,GateRef depend,const std::vector<GateRef> & args,GateRef hirGate,const char * comment)1018 GateRef CircuitBuilder::Call(const CallSignature* cs, GateRef glue, GateRef target, GateRef depend,
1019                              const std::vector<GateRef> &args, GateRef hirGate, const char* comment)
1020 {
1021     std::vector<GateRef> inputs { depend, target, glue };
1022     inputs.insert(inputs.end(), args.begin(), args.end());
1023     auto numValuesIn = args.size() + 2; // 2: target & glue
1024     if (GetCircuit()->IsOptimizedJSFunctionFrame() && hirGate != Circuit::NullGate()) {
1025         GateRef pcOffset = Int64(acc_.TryGetPcOffset(hirGate));
1026         inputs.emplace_back(pcOffset);
1027         numValuesIn += 1;
1028     }
1029 
1030     const GateMetaData* meta = nullptr;
1031     if (cs->IsCommonStub()) {
1032         meta = circuit_->Call(numValuesIn);
1033     } else if (cs->IsRuntimeVAStub()) {
1034         meta = circuit_->RuntimeCallWithArgv(numValuesIn);
1035     } else if (cs->IsRuntimeStub()) {
1036         meta = circuit_->RuntimeCall(numValuesIn);
1037     } else if (cs->IsBCDebuggerStub()) {
1038         meta = circuit_->DebuggerBytecodeCall(numValuesIn);
1039     } else if (cs->IsBCHandlerStub()) {
1040         meta = circuit_->BytecodeCall(numValuesIn);
1041     } else if (cs->IsBuiltinsStub()) {
1042         meta = circuit_->BuiltinsCall(numValuesIn);
1043     } else if (cs->IsBuiltinsWithArgvStub()) {
1044         meta = circuit_->BuiltinsCallWithArgv(numValuesIn);
1045     } else if (cs->IsRuntimeNGCStub()) {
1046         meta = circuit_->NoGcRuntimeCall(numValuesIn);
1047     } else if (cs->IsOptimizedStub()) {
1048         bool isNoGC = acc_.GetNoGCFlag(hirGate);
1049         meta = circuit_->CallOptimized(numValuesIn, isNoGC);
1050     } else if (cs->IsOptimizedFastCallStub()) {
1051         bool isNoGC = acc_.GetNoGCFlag(hirGate);
1052         meta = circuit_->FastCallOptimized(numValuesIn, isNoGC);
1053     } else {
1054         LOG_ECMA(FATAL) << "unknown call operator";
1055         UNREACHABLE();
1056     }
1057     MachineType machineType = cs->GetReturnType().GetMachineType();
1058     GateType type = cs->GetReturnType().GetGateType();
1059     GateRef result = GetCircuit()->NewGate(meta, machineType, inputs.size(), inputs.data(), type, comment);
1060     auto label = GetCurrentLabel();
1061     label->SetDepend(result);
1062     return result;
1063 }
1064 
StoreMemory(MemoryType Op,VariableType type,GateRef receiver,GateRef index,GateRef value)1065 GateRef CircuitBuilder::StoreMemory(MemoryType Op, VariableType type, GateRef receiver, GateRef index, GateRef value)
1066 {
1067     auto opIdx = static_cast<uint64_t>(Op);
1068     auto currentLabel = env_->GetCurrentLabel();
1069     auto currentControl = currentLabel->GetControl();
1070     auto currentDepend = currentLabel->GetDepend();
1071     auto ret = GetCircuit()->NewGate(GetCircuit()->StoreMemory(opIdx), type.GetMachineType(),
1072         {currentControl, currentDepend, receiver, index, value}, type.GetGateType());
1073     currentLabel->SetControl(ret);
1074     currentLabel->SetDepend(ret);
1075     return ret;
1076 }
1077 
NoLabelCallRuntime(GateRef glue,GateRef depend,size_t index,std::vector<GateRef> & args,GateRef hirGate)1078 GateRef CircuitBuilder::NoLabelCallRuntime(GateRef glue, GateRef depend, size_t index, std::vector<GateRef> &args,
1079                                            GateRef hirGate)
1080 {
1081     const std::string name = RuntimeStubCSigns::GetRTName(RTSTUB_ID(CallRuntime));
1082     const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
1083     GateRef target = IntPtr(index);
1084     std::vector<GateRef> inputs { depend, target, glue };
1085     inputs.insert(inputs.end(), args.begin(), args.end());
1086     auto numValuesIn = args.size() + 2; // 2: target & glue
1087     GateRef pcOffset = Int64(acc_.TryGetPcOffset(hirGate));
1088     inputs.emplace_back(pcOffset);
1089     numValuesIn += 1;
1090 
1091     const GateMetaData* meta = circuit_->RuntimeCall(numValuesIn);
1092     MachineType machineType = cs->GetReturnType().GetMachineType();
1093     GateType type = cs->GetReturnType().GetGateType();
1094     GateRef result = circuit_->NewGate(meta, machineType, inputs.size(), inputs.data(), type, name.c_str());
1095     return result;
1096 }
1097 
StoreWithNoBarrier(VariableType type,GateRef base,GateRef offset,GateRef value)1098 void CircuitBuilder::StoreWithNoBarrier(VariableType type, GateRef base, GateRef offset, GateRef value)
1099 {
1100     auto label = GetCurrentLabel();
1101     auto depend = label->GetDepend();
1102     GateRef ptr = PtrAdd(base, offset);
1103     GateRef result = GetCircuit()->NewGate(circuit_->Store(),
1104         MachineType::NOVALUE, { depend, value, ptr }, type.GetGateType());
1105     label->SetDepend(result);
1106 }
1107 
1108 // memory
Store(VariableType type,GateRef glue,GateRef base,GateRef offset,GateRef value)1109 void CircuitBuilder::Store(VariableType type, GateRef glue, GateRef base, GateRef offset, GateRef value)
1110 {
1111     StoreWithNoBarrier(type, base, offset, value);
1112     if (type == VariableType::JS_POINTER() || type == VariableType::JS_ANY()) {
1113         Label entry(env_);
1114         SubCfgEntry(&entry);
1115         Label exit(env_);
1116         Label isHeapObject(env_);
1117         Branch(TaggedIsHeapObject(value), &isHeapObject, &exit);
1118         Bind(&isHeapObject);
1119         {
1120             CallStub(glue, base, CommonStubCSigns::SetValueWithBarrier, { glue, base, offset, value });
1121             Jump(&exit);
1122         }
1123         Bind(&exit);
1124         SubCfgExit();
1125     }
1126 }
1127 
Alloca(size_t size)1128 GateRef CircuitBuilder::Alloca(size_t size)
1129 {
1130     return GetCircuit()->NewGate(circuit_->Alloca(size), MachineType::ARCH, GateType::NJSValue());
1131 }
1132 
ToLength(GateRef receiver)1133 GateRef CircuitBuilder::ToLength(GateRef receiver)
1134 {
1135     auto currentLabel = env_->GetCurrentLabel();
1136     auto currentControl = currentLabel->GetControl();
1137     auto currentDepend = currentLabel->GetDepend();
1138     auto ret = GetCircuit()->NewGate(circuit_->ToLength(), MachineType::I64,
1139                                      { currentControl, currentDepend, receiver }, GateType::NumberType());
1140     currentLabel->SetControl(ret);
1141     currentLabel->SetDepend(ret);
1142     return ret;
1143 }
1144 
LoadProperty(GateRef receiver,GateRef propertyLookupResult,bool isFunction)1145 GateRef CircuitBuilder::LoadProperty(GateRef receiver, GateRef propertyLookupResult, bool isFunction)
1146 {
1147     auto currentLabel = env_->GetCurrentLabel();
1148     auto currentControl = currentLabel->GetControl();
1149     auto currentDepend = currentLabel->GetDepend();
1150     auto ret = GetCircuit()->NewGate(circuit_->LoadProperty(isFunction), MachineType::I64,
1151                                      { currentControl, currentDepend, receiver, propertyLookupResult },
1152                                      GateType::AnyType());
1153     currentLabel->SetControl(ret);
1154     currentLabel->SetDepend(ret);
1155     return ret;
1156 }
1157 
StoreProperty(GateRef receiver,GateRef propertyLookupResult,GateRef value)1158 GateRef CircuitBuilder::StoreProperty(GateRef receiver, GateRef propertyLookupResult, GateRef value)
1159 {
1160     auto currentLabel = env_->GetCurrentLabel();
1161     auto currentControl = currentLabel->GetControl();
1162     auto currentDepend = currentLabel->GetDepend();
1163     auto ret = GetCircuit()->NewGate(circuit_->StoreProperty(), MachineType::I64,
1164                                      { currentControl, currentDepend, receiver, propertyLookupResult, value },
1165                                      GateType::AnyType());
1166     currentLabel->SetControl(ret);
1167     currentLabel->SetDepend(ret);
1168     return ret;
1169 }
1170 
LoadArrayLength(GateRef array)1171 GateRef CircuitBuilder::LoadArrayLength(GateRef array)
1172 {
1173     auto currentLabel = env_->GetCurrentLabel();
1174     auto currentControl = currentLabel->GetControl();
1175     auto currentDepend = currentLabel->GetDepend();
1176     auto ret = GetCircuit()->NewGate(circuit_->LoadArrayLength(), MachineType::I64,
1177                                      { currentControl, currentDepend, array }, GateType::IntType());
1178     currentLabel->SetControl(ret);
1179     currentLabel->SetDepend(ret);
1180     return ret;
1181 }
1182 
LoadConstOffset(VariableType type,GateRef receiver,size_t offset)1183 GateRef CircuitBuilder::LoadConstOffset(VariableType type, GateRef receiver, size_t offset)
1184 {
1185     auto currentLabel = env_->GetCurrentLabel();
1186     auto currentDepend = currentLabel->GetDepend();
1187 
1188     auto ret = GetCircuit()->NewGate(circuit_->LoadConstOffset(offset), type.GetMachineType(),
1189                                      { currentDepend, receiver }, type.GetGateType());
1190     currentLabel->SetDepend(ret);
1191     return ret;
1192 }
1193 
StoreConstOffset(VariableType type,GateRef receiver,size_t offset,GateRef value)1194 GateRef CircuitBuilder::StoreConstOffset(VariableType type,
1195     GateRef receiver, size_t offset, GateRef value)
1196 {
1197     auto currentLabel = env_->GetCurrentLabel();
1198     auto currentControl = currentLabel->GetControl();
1199     auto currentDepend = currentLabel->GetDepend();
1200 
1201     auto ret = GetCircuit()->NewGate(circuit_->StoreConstOffset(offset), type.GetMachineType(),
1202         { currentControl, currentDepend, receiver, value }, type.GetGateType());
1203     currentLabel->SetControl(ret);
1204     currentLabel->SetDepend(ret);
1205     return ret;
1206 }
1207 
LoadObjectFromConstPool(GateRef jsFunc,GateRef index)1208 GateRef CircuitBuilder::LoadObjectFromConstPool(GateRef jsFunc, GateRef index)
1209 {
1210     GateRef constPool = GetConstPoolFromFunction(jsFunc);
1211     return GetValueFromTaggedArray(constPool, TruncInt64ToInt32(index));
1212 }
1213 
ConvertHoleAsUndefined(GateRef receiver)1214 GateRef CircuitBuilder::ConvertHoleAsUndefined(GateRef receiver)
1215 {
1216     auto currentLabel = env_->GetCurrentLabel();
1217     auto currentControl = currentLabel->GetControl();
1218     auto currentDepend = currentLabel->GetDepend();
1219 
1220     auto ret = GetCircuit()->NewGate(circuit_->ConvertHoleAsUndefined(),
1221         MachineType::I64, { currentControl, currentDepend, receiver }, GateType::AnyType());
1222     currentLabel->SetControl(ret);
1223     currentLabel->SetDepend(ret);
1224     return ret;
1225 }
1226 
Construct(GateRef hirGate,std::vector<GateRef> args)1227 GateRef CircuitBuilder::Construct(GateRef hirGate, std::vector<GateRef> args)
1228 {
1229     ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
1230     auto currentLabel = env_->GetCurrentLabel();
1231     auto currentControl = currentLabel->GetControl();
1232     auto currentDepend = currentLabel->GetDepend();
1233     uint64_t bitfield = args.size();
1234     uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
1235     ASSERT(pcOffset != 0);
1236     args.insert(args.begin(), currentDepend);
1237     args.insert(args.begin(), currentControl);
1238     auto callGate = GetCircuit()->NewGate(circuit_->Construct(bitfield, pcOffset), MachineType::I64,
1239                                           args.size(), args.data(), GateType::AnyType());
1240     currentLabel->SetControl(callGate);
1241     currentLabel->SetDepend(callGate);
1242     return callGate;
1243 }
1244 
TypedCall(GateRef hirGate,std::vector<GateRef> args,bool isNoGC)1245 GateRef CircuitBuilder::TypedCall(GateRef hirGate, std::vector<GateRef> args, bool isNoGC)
1246 {
1247     ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
1248     auto currentLabel = env_->GetCurrentLabel();
1249     auto currentControl = currentLabel->GetControl();
1250     auto currentDepend = currentLabel->GetDepend();
1251     uint64_t bitfield = args.size();
1252     uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
1253     ASSERT(pcOffset != 0);
1254     args.insert(args.begin(), currentDepend);
1255     args.insert(args.begin(), currentControl);
1256     auto callGate = GetCircuit()->NewGate(circuit_->TypedCall(bitfield, pcOffset, isNoGC), MachineType::I64,
1257                                           args.size(), args.data(), GateType::AnyType());
1258     currentLabel->SetControl(callGate);
1259     currentLabel->SetDepend(callGate);
1260     return callGate;
1261 }
1262 
TypedFastCall(GateRef hirGate,std::vector<GateRef> args,bool isNoGC)1263 GateRef CircuitBuilder::TypedFastCall(GateRef hirGate, std::vector<GateRef> args, bool isNoGC)
1264 {
1265     ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
1266     auto currentLabel = env_->GetCurrentLabel();
1267     auto currentControl = currentLabel->GetControl();
1268     auto currentDepend = currentLabel->GetDepend();
1269     uint64_t bitfield = args.size();
1270     uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
1271     ASSERT(pcOffset != 0);
1272     args.insert(args.begin(), currentDepend);
1273     args.insert(args.begin(), currentControl);
1274     auto callGate = GetCircuit()->NewGate(circuit_->TypedFastCall(bitfield, pcOffset, isNoGC), MachineType::I64,
1275                                           args.size(), args.data(), GateType::AnyType());
1276     currentLabel->SetControl(callGate);
1277     currentLabel->SetDepend(callGate);
1278     return callGate;
1279 }
1280 
CallGetter(GateRef hirGate,GateRef receiver,GateRef propertyLookupResult,const char * comment)1281 GateRef CircuitBuilder::CallGetter(GateRef hirGate, GateRef receiver, GateRef propertyLookupResult,
1282                                    const char* comment)
1283 {
1284     ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
1285     uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
1286     ASSERT(pcOffset != 0);
1287 
1288     auto currentLabel = env_->GetCurrentLabel();
1289     auto currentControl = currentLabel->GetControl();
1290     auto currentDepend = currentLabel->GetDepend();
1291     auto callGate = GetCircuit()->NewGate(circuit_->CallGetter(pcOffset),
1292                                           MachineType::I64,
1293                                           { currentControl, currentDepend, receiver, propertyLookupResult },
1294                                           GateType::AnyType(),
1295                                           comment);
1296     currentLabel->SetControl(callGate);
1297     currentLabel->SetDepend(callGate);
1298     return callGate;
1299 }
1300 
CallSetter(GateRef hirGate,GateRef receiver,GateRef propertyLookupResult,GateRef value,const char * comment)1301 GateRef CircuitBuilder::CallSetter(GateRef hirGate, GateRef receiver, GateRef propertyLookupResult,
1302                                    GateRef value, const char* comment)
1303 {
1304     ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
1305     uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
1306     ASSERT(pcOffset != 0);
1307 
1308     auto currentLabel = env_->GetCurrentLabel();
1309     auto currentControl = currentLabel->GetControl();
1310     auto currentDepend = currentLabel->GetDepend();
1311     auto callGate = GetCircuit()->NewGate(circuit_->CallSetter(pcOffset),
1312                                           MachineType::I64,
1313                                           { currentControl, currentDepend, receiver, propertyLookupResult, value },
1314                                           GateType::AnyType(),
1315                                           comment);
1316     currentLabel->SetControl(callGate);
1317     currentLabel->SetDepend(callGate);
1318     return callGate;
1319 }
1320 
GetConstPool(GateRef jsFunc)1321 GateRef CircuitBuilder::GetConstPool(GateRef jsFunc)
1322 {
1323     auto currentLabel = env_->GetCurrentLabel();
1324     auto currentDepend = currentLabel->GetDepend();
1325     auto newGate = GetCircuit()->NewGate(circuit_->GetConstPool(), MachineType::I64,
1326                                          { currentDepend, jsFunc },
1327                                          GateType::AnyType());
1328     currentLabel->SetDepend(newGate);
1329     return newGate;
1330 }
1331 
GetGlobalEnv()1332 GateRef CircuitBuilder::GetGlobalEnv()
1333 {
1334     auto currentLabel = env_->GetCurrentLabel();
1335     auto currentDepend = currentLabel->GetDepend();
1336     auto newGate = GetCircuit()->NewGate(circuit_->GetGlobalEnv(), MachineType::I64,
1337                                          { currentDepend },
1338                                          GateType::AnyType());
1339     currentLabel->SetDepend(newGate);
1340     return newGate;
1341 }
1342 
GetGlobalEnvObjHClass(GateRef env,size_t index)1343 GateRef CircuitBuilder::GetGlobalEnvObjHClass(GateRef env, size_t index)
1344 {
1345     auto currentLabel = env_->GetCurrentLabel();
1346     auto currentDepend = currentLabel->GetDepend();
1347     auto newGate = GetCircuit()->NewGate(circuit_->GetGlobalEnvObjHClass(index), MachineType::I64,
1348                                          { currentDepend, env },
1349                                          GateType::AnyType());
1350     currentLabel->SetDepend(newGate);
1351     return newGate;
1352 }
1353 
GetGlobalConstantValue(ConstantIndex index)1354 GateRef CircuitBuilder::GetGlobalConstantValue(ConstantIndex index)
1355 {
1356     auto currentLabel = env_->GetCurrentLabel();
1357     auto currentDepend = currentLabel->GetDepend();
1358     auto newGate = GetCircuit()->NewGate(circuit_->GetGlobalConstantValue(static_cast<size_t>(index)),
1359                                          MachineType::I64, { currentDepend }, GateType::AnyType());
1360     currentLabel->SetDepend(newGate);
1361     return newGate;
1362 }
1363 
HasPendingException(GateRef glue)1364 GateRef CircuitBuilder::HasPendingException(GateRef glue)
1365 {
1366     GateRef exceptionOffset = IntPtr(JSThread::GlueData::GetExceptionOffset(env_->IsArch32Bit()));
1367     GateRef exception = Load(VariableType::JS_ANY(), glue, exceptionOffset);
1368     return TaggedIsNotHole(exception);
1369 }
1370 
TaggedIsString(GateRef obj)1371 GateRef CircuitBuilder::TaggedIsString(GateRef obj)
1372 {
1373     Label entry(env_);
1374     SubCfgEntry(&entry);
1375     Label exit(env_);
1376     DEFVAlUE(result, env_, VariableType::BOOL(), False());
1377     Label isHeapObject(env_);
1378     Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
1379     Bind(&isHeapObject);
1380     {
1381         result = TaggedObjectIsString(obj);
1382         Jump(&exit);
1383     }
1384     Bind(&exit);
1385     auto ret = *result;
1386     SubCfgExit();
1387     return ret;
1388 }
1389 
TaggedIsStringOrSymbol(GateRef obj)1390 GateRef CircuitBuilder::TaggedIsStringOrSymbol(GateRef obj)
1391 {
1392     Label entry(env_);
1393     SubCfgEntry(&entry);
1394     Label exit(env_);
1395     DEFVAlUE(result, env_, VariableType::BOOL(), False());
1396     Label isHeapObject(env_);
1397     Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
1398     Bind(&isHeapObject);
1399     {
1400         result = TaggedObjectIsString(obj);
1401         Label isString(env_);
1402         Label notString(env_);
1403         Branch(*result, &exit, &notString);
1404         Bind(&notString);
1405         {
1406             GateRef objType = GetObjectType(LoadHClass(obj));
1407             result = Equal(objType, Int32(static_cast<int32_t>(JSType::SYMBOL)));
1408             Jump(&exit);
1409         }
1410     }
1411     Bind(&exit);
1412     auto ret = *result;
1413     SubCfgExit();
1414     return ret;
1415 }
1416 
IsUtf16String(GateRef string)1417 GateRef CircuitBuilder::IsUtf16String(GateRef string)
1418 {
1419     // compressedStringsEnabled fixed to true constant
1420     GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
1421     return Int32Equal(
1422         Int32And(len, Int32(EcmaString::STRING_COMPRESSED_BIT)),
1423         Int32(EcmaString::STRING_UNCOMPRESSED));
1424 }
1425 
GetGlobalObject(GateRef glue)1426 GateRef CircuitBuilder::GetGlobalObject(GateRef glue)
1427 {
1428     GateRef offset = IntPtr(JSThread::GlueData::GetGlobalObjOffset(cmpCfg_->Is32Bit()));
1429     return Load(VariableType::JS_ANY(), glue, offset);
1430 }
1431 
GetMethodFromFunction(GateRef function)1432 GateRef CircuitBuilder::GetMethodFromFunction(GateRef function)
1433 {
1434     GateRef offset = IntPtr(JSFunctionBase::METHOD_OFFSET);
1435     return Load(VariableType::JS_POINTER(), function, offset);
1436 }
1437 
GetModuleFromFunction(GateRef function)1438 GateRef CircuitBuilder::GetModuleFromFunction(GateRef function)
1439 {
1440     GateRef offset = IntPtr(JSFunction::ECMA_MODULE_OFFSET);
1441     return Load(VariableType::JS_POINTER(), function, offset);
1442 }
1443 
GetHomeObjectFromFunction(GateRef function)1444 GateRef CircuitBuilder::GetHomeObjectFromFunction(GateRef function)
1445 {
1446     GateRef offset = IntPtr(JSFunction::HOME_OBJECT_OFFSET);
1447     return Load(VariableType::JS_POINTER(), function, offset);
1448 }
1449 
GetLengthFromString(GateRef value)1450 GateRef CircuitBuilder::GetLengthFromString(GateRef value)
1451 {
1452     GateRef len = Load(VariableType::INT32(), value, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
1453     return Int32LSR(len, Int32(2));  // 2 : 2 means len must be right shift 2 bits
1454 }
1455 
GetConstPoolFromFunction(GateRef jsFunc)1456 GateRef CircuitBuilder::GetConstPoolFromFunction(GateRef jsFunc)
1457 {
1458     GateRef method = GetMethodFromFunction(jsFunc);
1459     return Load(VariableType::JS_ANY(), method, IntPtr(Method::CONSTANT_POOL_OFFSET));
1460 }
1461 
GetObjectFromConstPool(GateRef glue,GateRef hirGate,GateRef jsFunc,GateRef index,ConstPoolType type)1462 GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef jsFunc, GateRef index,
1463                                                ConstPoolType type)
1464 {
1465     GateRef constPool = GetConstPoolFromFunction(jsFunc);
1466     GateRef module = GetModuleFromFunction(jsFunc);
1467     return GetObjectFromConstPool(glue, hirGate, constPool, module, index, type);
1468 }
1469 
GetObjectFromConstPool(GateRef glue,GateRef hirGate,GateRef constPool,GateRef module,GateRef index,ConstPoolType type)1470 GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef constPool, GateRef module,
1471                                                GateRef index, ConstPoolType type)
1472 {
1473     Label entry(env_);
1474     SubCfgEntry(&entry);
1475     Label exit(env_);
1476     Label cacheMiss(env_);
1477     Label cache(env_);
1478 
1479     auto cacheValue = GetValueFromTaggedArray(constPool, index);
1480     DEFVAlUE(result, env_, VariableType::JS_ANY(), cacheValue);
1481     Branch(BoolOr(TaggedIsHole(*result), TaggedIsNullPtr(*result)), &cacheMiss, &cache);
1482     Bind(&cacheMiss);
1483     {
1484         if (type == ConstPoolType::STRING) {
1485             result = CallRuntime(glue, RTSTUB_ID(GetStringFromCache), Gate::InvalidGateRef,
1486                 { constPool, Int32ToTaggedInt(index) }, hirGate);
1487         } else if (type == ConstPoolType::ARRAY_LITERAL) {
1488             result = CallRuntime(glue, RTSTUB_ID(GetArrayLiteralFromCache), Gate::InvalidGateRef,
1489                 { constPool, Int32ToTaggedInt(index), module }, hirGate);
1490         } else if (type == ConstPoolType::OBJECT_LITERAL) {
1491             result = CallRuntime(glue, RTSTUB_ID(GetObjectLiteralFromCache), Gate::InvalidGateRef,
1492                 { constPool, Int32ToTaggedInt(index), module }, hirGate);
1493         } else {
1494             result = CallRuntime(glue, RTSTUB_ID(GetMethodFromCache), Gate::InvalidGateRef,
1495                 { constPool, Int32ToTaggedInt(index) }, hirGate);
1496         }
1497         Jump(&exit);
1498     }
1499     Bind(&cache);
1500     {
1501         if (type == ConstPoolType::METHOD) {
1502             Label isInt(env_);
1503             Branch(TaggedIsInt(*result), &isInt, &exit);
1504             Bind(&isInt);
1505             {
1506                 result = CallRuntime(glue, RTSTUB_ID(GetMethodFromCache), Gate::InvalidGateRef,
1507                     { constPool, Int32ToTaggedInt(index) }, hirGate);
1508                 Jump(&exit);
1509             }
1510         } else if (type == ConstPoolType::ARRAY_LITERAL) {
1511             Label isAOTLiteralInfo(env_);
1512             Branch(IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit);
1513             Bind(&isAOTLiteralInfo);
1514             {
1515                 result = CallRuntime(glue, RTSTUB_ID(GetArrayLiteralFromCache), Gate::InvalidGateRef,
1516                     { constPool, Int32ToTaggedInt(index), module }, hirGate);
1517                 Jump(&exit);
1518             }
1519         } else if (type == ConstPoolType::OBJECT_LITERAL) {
1520             Label isAOTLiteralInfo(env_);
1521             Branch(IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit);
1522             Bind(&isAOTLiteralInfo);
1523             {
1524                 result = CallRuntime(glue, RTSTUB_ID(GetObjectLiteralFromCache), Gate::InvalidGateRef,
1525                     { constPool, Int32ToTaggedInt(index), module }, hirGate);
1526                 Jump(&exit);
1527             }
1528         } else {
1529             Jump(&exit);
1530         }
1531     }
1532     Bind(&exit);
1533     auto ret = *result;
1534     SubCfgExit();
1535     return ret;
1536 }
1537 
ComputeTaggedArraySize(GateRef length)1538 GateRef CircuitBuilder::ComputeTaggedArraySize(GateRef length)
1539 {
1540     return PtrAdd(IntPtr(TaggedArray::DATA_OFFSET),
1541         PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()), length));
1542 }
1543 
CreateArray(size_t arraySize)1544 GateRef CircuitBuilder::CreateArray(size_t arraySize)
1545 {
1546     auto currentLabel = env_->GetCurrentLabel();
1547     auto currentControl = currentLabel->GetControl();
1548     auto currentDepend = currentLabel->GetDepend();
1549     GateRef newGate = GetCircuit()->NewGate(circuit_->CreateArray(arraySize), MachineType::I64,
1550                                             { currentControl, currentDepend }, GateType::TaggedValue());
1551     currentLabel->SetControl(newGate);
1552     currentLabel->SetDepend(newGate);
1553     return newGate;
1554 }
1555 
CreateArrayWithBuffer(size_t arraySize,GateRef constPoolIndex,GateRef elementIndex)1556 GateRef CircuitBuilder::CreateArrayWithBuffer(size_t arraySize, GateRef constPoolIndex,
1557                                               GateRef elementIndex)
1558 {
1559     auto currentLabel = env_->GetCurrentLabel();
1560     auto currentControl = currentLabel->GetControl();
1561     auto currentDepend = currentLabel->GetDepend();
1562     auto frameState = acc_.FindNearestFrameState(currentDepend);
1563     GateRef newGate = GetCircuit()->NewGate(circuit_->CreateArrayWithBuffer(arraySize),
1564                                             MachineType::I64,
1565                                             { currentControl, currentDepend, constPoolIndex,
1566                                               elementIndex, frameState },
1567                                             GateType::NJSValue());
1568     currentLabel->SetControl(newGate);
1569     currentLabel->SetDepend(newGate);
1570     return newGate;
1571 }
1572 
StartAllocate()1573 GateRef CircuitBuilder::StartAllocate()
1574 {
1575     auto currentLabel = env_->GetCurrentLabel();
1576     auto currentDepend = currentLabel->GetDepend();
1577     GateRef newGate = GetCircuit()->NewGate(circuit_->StartAllocate(),  MachineType::I64,
1578                                             { currentDepend }, GateType::NJSValue());
1579     currentLabel->SetDepend(newGate);
1580     return newGate;
1581 }
1582 
FinishAllocate()1583 GateRef CircuitBuilder::FinishAllocate()
1584 {
1585     auto currentLabel = env_->GetCurrentLabel();
1586     auto currentDepend = currentLabel->GetDepend();
1587     GateRef newGate = GetCircuit()->NewGate(circuit_->FinishAllocate(),  MachineType::I64,
1588                                             { currentDepend }, GateType::NJSValue());
1589     currentLabel->SetDepend(newGate);
1590     return newGate;
1591 }
1592 
HeapAlloc(GateRef size,GateType type,RegionSpaceFlag flag)1593 GateRef CircuitBuilder::HeapAlloc(GateRef size, GateType type, RegionSpaceFlag flag)
1594 {
1595     auto currentLabel = env_->GetCurrentLabel();
1596     auto currentControl = currentLabel->GetControl();
1597     auto currentDepend = currentLabel->GetDepend();
1598     auto ret = GetCircuit()->NewGate(circuit_->HeapAlloc(flag), MachineType::ANYVALUE,
1599                                      { currentControl, currentDepend, size }, type);
1600     currentLabel->SetControl(ret);
1601     currentLabel->SetDepend(ret);
1602     return ret;
1603 }
1604 
TryGetHashcodeFromString(GateRef string)1605 GateRef CircuitBuilder::TryGetHashcodeFromString(GateRef string)
1606 {
1607     Label subentry(env_);
1608     SubCfgEntry(&subentry);
1609     Label noRawHashcode(env_);
1610     Label storeHash(env_);
1611     Label exit(env_);
1612     DEFVAlUE(result, env_, VariableType::INT64(), Int64(-1));
1613     GateRef hashCode = ZExtInt32ToInt64(Load(VariableType::INT32(), string, IntPtr(EcmaString::HASHCODE_OFFSET)));
1614     Branch(Int64Equal(hashCode, Int64(0)), &noRawHashcode, &storeHash);
1615     Bind(&noRawHashcode);
1616     {
1617         GateRef length = GetLengthFromString(string);
1618         Label lengthNotZero(env_);
1619         Branch(Int32Equal(length, Int32(0)), &storeHash, &exit);
1620     }
1621     Bind(&storeHash);
1622     result = hashCode;
1623     Jump(&exit);
1624     Bind(&exit);
1625     auto ret = *result;
1626     SubCfgExit();
1627     return ret;
1628 }
1629 
GetHashcodeFromString(GateRef glue,GateRef value)1630 GateRef CircuitBuilder::GetHashcodeFromString(GateRef glue, GateRef value)
1631 {
1632     ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame());
1633     Label subentry(env_);
1634     SubCfgEntry(&subentry);
1635     Label noRawHashcode(env_);
1636     Label exit(env_);
1637     DEFVAlUE(hashcode, env_, VariableType::INT32(), Int32(0));
1638     hashcode = Load(VariableType::INT32(), value, IntPtr(EcmaString::HASHCODE_OFFSET));
1639     Branch(Int32Equal(*hashcode, Int32(0)), &noRawHashcode, &exit);
1640     Bind(&noRawHashcode);
1641     {
1642         hashcode = GetInt32OfTInt(
1643             CallRuntime(glue, RTSTUB_ID(ComputeHashcode), Gate::InvalidGateRef, { value }, Circuit::NullGate()));
1644         Store(VariableType::INT32(), glue, value, IntPtr(EcmaString::HASHCODE_OFFSET), *hashcode);
1645         Jump(&exit);
1646     }
1647     Bind(&exit);
1648     auto ret = *hashcode;
1649     SubCfgExit();
1650     return ret;
1651 }
1652 
TaggedIsBigInt(GateRef obj)1653 GateRef CircuitBuilder::TaggedIsBigInt(GateRef obj)
1654 {
1655     Label entry(env_);
1656     SubCfgEntry(&entry);
1657     Label exit(env_);
1658     DEFVAlUE(result, env_, VariableType::BOOL(), False());
1659     Label isHeapObject(env_);
1660     Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
1661     Bind(&isHeapObject);
1662     {
1663         result = Int32Equal(GetObjectType(LoadHClass(obj)),
1664                             Int32(static_cast<int32_t>(JSType::BIGINT)));
1665         Jump(&exit);
1666     }
1667     Bind(&exit);
1668     auto ret = *result;
1669     SubCfgExit();
1670     return ret;
1671 }
1672 
SetLexicalEnvToFunction(GateRef glue,GateRef function,GateRef value)1673 void CircuitBuilder::SetLexicalEnvToFunction(GateRef glue, GateRef function, GateRef value)
1674 {
1675     GateRef offset = IntPtr(JSFunction::LEXICAL_ENV_OFFSET);
1676     Store(VariableType::JS_ANY(), glue, function, offset, value);
1677 }
1678 
GetFunctionLexicalEnv(GateRef function)1679 GateRef CircuitBuilder::GetFunctionLexicalEnv(GateRef function)
1680 {
1681     return Load(VariableType::JS_POINTER(), function, IntPtr(JSFunction::LEXICAL_ENV_OFFSET));
1682 }
1683 
SetModuleToFunction(GateRef glue,GateRef function,GateRef value)1684 void CircuitBuilder::SetModuleToFunction(GateRef glue, GateRef function, GateRef value)
1685 {
1686     GateRef offset = IntPtr(JSFunction::ECMA_MODULE_OFFSET);
1687     Store(VariableType::JS_POINTER(), glue, function, offset, value);
1688 }
1689 
SetPropertyInlinedProps(GateRef glue,GateRef obj,GateRef hClass,GateRef value,GateRef attrOffset,VariableType type)1690 void CircuitBuilder::SetPropertyInlinedProps(GateRef glue, GateRef obj, GateRef hClass,
1691     GateRef value, GateRef attrOffset, VariableType type)
1692 {
1693     GateRef bitfield = Load(VariableType::INT32(), hClass, IntPtr(JSHClass::BIT_FIELD1_OFFSET));
1694     GateRef inlinedPropsStart = Int32And(Int32LSR(bitfield,
1695         Int32(JSHClass::InlinedPropsStartBits::START_BIT)),
1696         Int32((1LU << JSHClass::InlinedPropsStartBits::SIZE) - 1));
1697     GateRef propOffset = Int32Mul(Int32Add(inlinedPropsStart, attrOffset),
1698         Int32(JSTaggedValue::TaggedTypeSize()));
1699     Store(type, glue, obj, ZExtInt32ToPtr(propOffset), value);
1700 }
1701 
SetHomeObjectToFunction(GateRef glue,GateRef function,GateRef value)1702 void CircuitBuilder::SetHomeObjectToFunction(GateRef glue, GateRef function, GateRef value)
1703 {
1704     GateRef offset = IntPtr(JSFunction::HOME_OBJECT_OFFSET);
1705     Store(VariableType::JS_ANY(), glue, function, offset, value);
1706 }
1707 
GetGlobalEnvValue(VariableType type,GateRef env,size_t index)1708 GateRef CircuitBuilder::GetGlobalEnvValue(VariableType type, GateRef env, size_t index)
1709 {
1710     auto valueIndex = IntPtr(GlobalEnv::HEADER_SIZE + JSTaggedValue::TaggedTypeSize() * index);
1711     return Load(type, env, valueIndex);
1712 }
1713 
GetCodeAddr(GateRef method)1714 GateRef CircuitBuilder::GetCodeAddr(GateRef method)
1715 {
1716     auto codeAddOffset = IntPtr(Method::CODE_ENTRY_OFFSET);
1717     return Load(VariableType::NATIVE_POINTER(), method, codeAddOffset);
1718 }
1719 
GetCallBuiltinId(GateRef method)1720 GateRef CircuitBuilder::GetCallBuiltinId(GateRef method)
1721 {
1722     GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
1723     GateRef extraLiteralInfo = Load(VariableType::INT64(), method, extraLiteralInfoOffset);
1724     return Int64And(
1725         Int64LSR(extraLiteralInfo, Int64(MethodLiteral::BuiltinIdBits::START_BIT)),
1726         Int64((1LU << MethodLiteral::BuiltinIdBits::SIZE) - 1));
1727 }
1728 
Environment(size_t arguments,CircuitBuilder * builder)1729 Environment::Environment(size_t arguments, CircuitBuilder *builder)
1730     : circuit_(builder->GetCircuit()), circuitBuilder_(builder), arguments_(arguments)
1731 {
1732     circuitBuilder_->SetEnvironment(this);
1733     SetCompilationConfig(circuitBuilder_->GetCompilationConfig());
1734     for (size_t i = 0; i < arguments; i++) {
1735         arguments_[i] = circuitBuilder_->Arguments(i);
1736     }
1737     entry_ = Label(NewLabel(this, circuit_->GetStateRoot()));
1738     currentLabel_ = &entry_;
1739     currentLabel_->Seal();
1740     auto depend_entry = circuit_->GetDependRoot();
1741     currentLabel_->SetDepend(depend_entry);
1742 }
1743 
Environment(GateRef hir,Circuit * circuit,CircuitBuilder * builder)1744 Environment::Environment(GateRef hir, Circuit *circuit, CircuitBuilder *builder)
1745     : circuit_(circuit), circuitBuilder_(builder)
1746 {
1747     circuitBuilder_->SetEnvironment(this);
1748     SetCompilationConfig(circuitBuilder_->GetCompilationConfig());
1749     GateAccessor acc(circuit);
1750     entry_ = Label(NewLabel(this, acc.GetIn(hir, 0)));
1751     currentLabel_ = &entry_;
1752     currentLabel_->Seal();
1753     auto dependEntry = acc.GetDep(hir);
1754     currentLabel_->SetDepend(dependEntry);
1755     for (size_t i = 2; i < acc.GetNumIns(hir); i++) {
1756         inputList_.emplace_back(acc.GetIn(hir, i));
1757     }
1758 }
1759 
Environment(GateRef stateEntry,GateRef dependEntry,const std::initializer_list<GateRef> & args,Circuit * circuit,CircuitBuilder * builder)1760 Environment::Environment(GateRef stateEntry, GateRef dependEntry,
1761     const std::initializer_list<GateRef>& args, Circuit *circuit, CircuitBuilder *builder)
1762     : circuit_(circuit), circuitBuilder_(builder)
1763 {
1764     circuitBuilder_->SetEnvironment(this);
1765     SetCompilationConfig(circuitBuilder_->GetCompilationConfig());
1766     entry_ = Label(NewLabel(this, stateEntry));
1767     currentLabel_ = &entry_;
1768     currentLabel_->Seal();
1769     currentLabel_->SetDepend(dependEntry);
1770     for (auto in : args) {
1771         inputList_.emplace_back(in);
1772     }
1773 }
1774 
~Environment()1775 Environment::~Environment()
1776 {
1777     circuitBuilder_->SetEnvironment(nullptr);
1778     for (auto label : rawLabels_) {
1779         delete label;
1780     }
1781 }
1782 
Jump(Label * label)1783 void CircuitBuilder::Jump(Label *label)
1784 {
1785     ASSERT(label);
1786     auto currentLabel = env_->GetCurrentLabel();
1787     auto currentControl = currentLabel->GetControl();
1788     auto jump = Goto(currentControl);
1789     currentLabel->SetControl(jump);
1790     label->AppendPredecessor(currentLabel);
1791     label->MergeControl(currentLabel->GetControl());
1792     env_->SetCurrentLabel(nullptr);
1793 }
1794 
Branch(GateRef condition,Label * trueLabel,Label * falseLabel)1795 void CircuitBuilder::Branch(GateRef condition, Label *trueLabel, Label *falseLabel)
1796 {
1797     auto currentLabel = env_->GetCurrentLabel();
1798     auto currentControl = currentLabel->GetControl();
1799     GateRef ifBranch = Branch(currentControl, condition);
1800     currentLabel->SetControl(ifBranch);
1801     GateRef ifTrue = IfTrue(ifBranch);
1802     trueLabel->AppendPredecessor(GetCurrentLabel());
1803     trueLabel->MergeControl(ifTrue);
1804     GateRef ifFalse = IfFalse(ifBranch);
1805     falseLabel->AppendPredecessor(GetCurrentLabel());
1806     falseLabel->MergeControl(ifFalse);
1807     env_->SetCurrentLabel(nullptr);
1808 }
1809 
Switch(GateRef index,Label * defaultLabel,int64_t * keysValue,Label * keysLabel,int numberOfKeys)1810 void CircuitBuilder::Switch(GateRef index, Label *defaultLabel, int64_t *keysValue, Label *keysLabel, int numberOfKeys)
1811 {
1812     auto currentLabel = env_->GetCurrentLabel();
1813     auto currentControl = currentLabel->GetControl();
1814     GateRef switchBranch = SwitchBranch(currentControl, index, numberOfKeys);
1815     currentLabel->SetControl(switchBranch);
1816     for (int i = 0; i < numberOfKeys; i++) {
1817         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1818         GateRef switchCase = SwitchCase(switchBranch, keysValue[i]);
1819         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1820         keysLabel[i].AppendPredecessor(currentLabel);
1821         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1822         keysLabel[i].MergeControl(switchCase);
1823     }
1824 
1825     GateRef defaultCase = DefaultCase(switchBranch);
1826     defaultLabel->AppendPredecessor(currentLabel);
1827     defaultLabel->MergeControl(defaultCase);
1828     env_->SetCurrentLabel(nullptr);
1829 }
1830 
LoopBegin(Label * loopHead)1831 void CircuitBuilder::LoopBegin(Label *loopHead)
1832 {
1833     ASSERT(loopHead);
1834     auto loopControl = LoopBegin(loopHead->GetControl());
1835     loopHead->SetControl(loopControl);
1836     loopHead->SetPreControl(loopControl);
1837     loopHead->Bind();
1838     env_->SetCurrentLabel(loopHead);
1839 }
1840 
LoopEnd(Label * loopHead)1841 void CircuitBuilder::LoopEnd(Label *loopHead)
1842 {
1843     ASSERT(loopHead);
1844     auto currentLabel = GetCurrentLabel();
1845     auto currentControl = currentLabel->GetControl();
1846     auto loopend = LoopEnd(currentControl);
1847     currentLabel->SetControl(loopend);
1848     loopHead->AppendPredecessor(currentLabel);
1849     loopHead->MergeControl(loopend);
1850     loopHead->Seal();
1851     loopHead->MergeAllControl();
1852     loopHead->MergeAllDepend();
1853     env_->SetCurrentLabel(nullptr);
1854 }
1855 
Label(Environment * env)1856 Label::Label(Environment *env)
1857 {
1858     impl_ = env->NewLabel(env);
1859 }
1860 
Label(CircuitBuilder * cirBuilder)1861 Label::Label(CircuitBuilder *cirBuilder)
1862 {
1863     auto env = cirBuilder->GetCurrentEnvironment();
1864     impl_ = env->NewLabel(env);
1865 }
1866 
Seal()1867 void Label::LabelImpl::Seal()
1868 {
1869     for (auto &[variable, gate] : incompletePhis_) {
1870         variable->AddPhiOperand(gate);
1871     }
1872     isSealed_ = true;
1873 }
1874 
WriteVariable(Variable * var,GateRef value)1875 void Label::LabelImpl::WriteVariable(Variable *var, GateRef value)
1876 {
1877     valueMap_[var] = value;
1878 }
1879 
ReadVariable(Variable * var)1880 GateRef Label::LabelImpl::ReadVariable(Variable *var)
1881 {
1882     if (valueMap_.find(var) != valueMap_.end()) {
1883         auto result = valueMap_.at(var);
1884         GateAccessor acc(env_->GetCircuit());
1885         if (!acc.IsNop(result)) {
1886             return result;
1887         }
1888     }
1889     return ReadVariableRecursive(var);
1890 }
1891 
ReadVariableRecursive(Variable * var)1892 GateRef Label::LabelImpl::ReadVariableRecursive(Variable *var)
1893 {
1894     GateRef val;
1895     MachineType machineType = CircuitBuilder::GetMachineTypeFromVariableType(var->Type());
1896     if (!IsSealed()) {
1897         // only loopheader gate will be not sealed
1898         int valueCounts = static_cast<int>(this->predecessors_.size()) + 1;
1899         if (machineType == MachineType::NOVALUE) {
1900             val = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR,
1901                 predeControl_, {}, valueCounts, var->Type());
1902         } else {
1903             val = env_->GetBuilder()->Selector(OpCode::VALUE_SELECTOR,
1904                 machineType, predeControl_, {}, valueCounts, var->Type());
1905         }
1906         env_->AddSelectorToLabel(val, Label(this));
1907         incompletePhis_[var] = val;
1908     } else if (predecessors_.size() == 1) {
1909         val = predecessors_[0]->ReadVariable(var);
1910     } else {
1911         if (machineType == MachineType::NOVALUE) {
1912             val = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR,
1913                 predeControl_, {}, this->predecessors_.size(), var->Type());
1914         } else {
1915             val = env_->GetBuilder()->Selector(OpCode::VALUE_SELECTOR, machineType,
1916                 predeControl_, {}, this->predecessors_.size(), var->Type());
1917         }
1918         env_->AddSelectorToLabel(val, Label(this));
1919         WriteVariable(var, val);
1920         val = var->AddPhiOperand(val);
1921     }
1922     WriteVariable(var, val);
1923     return val;
1924 }
1925 
Bind()1926 void Label::LabelImpl::Bind()
1927 {
1928     ASSERT(!predecessors_.empty());
1929     if (IsLoopHead()) {
1930         // 2 means input number of depend selector gate
1931         loopDepend_ = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR, predeControl_, {}, 2);
1932         GateAccessor(env_->GetCircuit()).NewIn(loopDepend_, 1, predecessors_[0]->GetDepend());
1933         depend_ = loopDepend_;
1934     }
1935     if (IsNeedSeal()) {
1936         Seal();
1937         MergeAllControl();
1938         MergeAllDepend();
1939     }
1940 }
1941 
MergeAllControl()1942 void Label::LabelImpl::MergeAllControl()
1943 {
1944     if (predecessors_.size() < 2) {  // 2 : Loop Head only support two predecessors_
1945         return;
1946     }
1947 
1948     if (IsLoopHead()) {
1949         ASSERT(predecessors_.size() == 2);  // 2 : Loop Head only support two predecessors_
1950         ASSERT(otherPredeControls_.size() == 1);
1951         GateAccessor(env_->GetCircuit()).NewIn(predeControl_, 1, otherPredeControls_[0]);
1952         return;
1953     }
1954 
1955     // merge all control of predecessors_
1956     std::vector<GateRef> inGates(predecessors_.size());
1957     size_t i = 0;
1958     ASSERT(predeControl_ != -1);
1959     ASSERT((otherPredeControls_.size() + 1) == predecessors_.size());
1960     inGates[i++] = predeControl_;
1961     for (auto in : otherPredeControls_) {
1962         inGates[i++] = in;
1963     }
1964 
1965     GateRef merge = env_->GetBuilder()->Merge(inGates);
1966     predeControl_ = merge;
1967     control_ = merge;
1968 }
1969 
MergeAllDepend()1970 void Label::LabelImpl::MergeAllDepend()
1971 {
1972     if (predecessors_.size() < 2) {  // 2 : Loop Head only support two predecessors_
1973         depend_ = predecessors_[0]->GetDepend();
1974         if (IsControlCase()) {
1975             // Add depend_relay to current label
1976             depend_ = env_->GetBuilder()->DependRelay(predeControl_, depend_);
1977         }
1978         return;
1979     }
1980     if (IsLoopHead()) {
1981         ASSERT(predecessors_.size() == 2);  // 2 : Loop Head only support two predecessors_
1982         // Add loop depend to in of depend_seclector
1983         ASSERT(loopDepend_ != -1);
1984         // 2 mean 3rd input gate for loopDepend_(depend_selector)
1985         GateAccessor(env_->GetCircuit()).NewIn(loopDepend_, 2, predecessors_[1]->GetDepend());
1986         return;
1987     }
1988 
1989     //  Merge all depends to depend_seclector
1990     std::vector<GateRef> dependsList;
1991     for (auto prede : this->GetPredecessors()) {
1992         dependsList.push_back(prede->GetDepend());
1993     }
1994     depend_ = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR,
1995         predeControl_, dependsList, dependsList.size());
1996 }
1997 
AppendPredecessor(Label::LabelImpl * predecessor)1998 void Label::LabelImpl::AppendPredecessor(Label::LabelImpl *predecessor)
1999 {
2000     if (predecessor != nullptr) {
2001         predecessors_.push_back(predecessor);
2002     }
2003 }
2004 
IsNeedSeal() const2005 bool Label::LabelImpl::IsNeedSeal() const
2006 {
2007     auto stateCount = GateAccessor(env_->GetCircuit()).GetStateCount(predeControl_);
2008     return predecessors_.size() >= stateCount;
2009 }
2010 
IsLoopHead() const2011 bool Label::LabelImpl::IsLoopHead() const
2012 {
2013     return GateAccessor(env_->GetCircuit()).IsLoopHead(predeControl_);
2014 }
2015 
IsControlCase() const2016 bool Label::LabelImpl::IsControlCase() const
2017 {
2018     return GateAccessor(env_->GetCircuit()).IsControlCase(predeControl_);
2019 }
2020 
AddPhiOperand(GateRef val)2021 GateRef Variable::AddPhiOperand(GateRef val)
2022 {
2023     ASSERT(GateAccessor(env_->GetCircuit()).IsValueSelector(val));
2024     Label label = env_->GetLabelFromSelector(val);
2025     size_t idx = 0;
2026     for (auto pred : label.GetPredecessors()) {
2027         auto preVal = pred.ReadVariable(this);
2028         ASSERT(!GateAccessor(env_->GetCircuit()).IsNop(preVal));
2029         idx++;
2030         val = AddOperandToSelector(val, idx, preVal);
2031     }
2032     return TryRemoveTrivialPhi(val);
2033 }
2034 
AddOperandToSelector(GateRef val,size_t idx,GateRef in)2035 GateRef Variable::AddOperandToSelector(GateRef val, size_t idx, GateRef in)
2036 {
2037     GateAccessor(env_->GetCircuit()).NewIn(val, idx, in);
2038     return val;
2039 }
2040 
TryRemoveTrivialPhi(GateRef phi)2041 GateRef Variable::TryRemoveTrivialPhi(GateRef phi)
2042 {
2043     GateAccessor acc(GetCircuit());
2044     GateRef same = Gate::InvalidGateRef;
2045     const size_t inNum = acc.GetNumIns(phi);
2046     for (size_t i = 1; i < inNum; ++i) {
2047         GateRef phiIn = acc.GetIn(phi, i);
2048         if (phiIn == same || phiIn == phi) {
2049             continue;  // unique value or self-reference
2050         }
2051         if (same != Gate::InvalidGateRef) {
2052             return phi;  // the phi merges at least two valusses: not trivial
2053         }
2054         same = phiIn;
2055     }
2056     if (same == Gate::InvalidGateRef) {
2057         // the phi is unreachable or in the start block
2058         GateType type = acc.GetGateType(phi);
2059         same = env_->GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_UNDEFINED, type);
2060     }
2061     // remove the trivial phi
2062     // get all users of phi except self
2063     std::vector<GateRef> outs;
2064     auto uses = acc.Uses(phi);
2065     for (auto use = uses.begin(); use != uses.end();) {
2066         GateRef u = *use;
2067         if (u != phi) {
2068             outs.push_back(u);
2069             use = acc.ReplaceIn(use, same);
2070         } else {
2071             use++;
2072         }
2073     }
2074     acc.DeleteGate(phi);
2075 
2076     // try to recursiveby remove all phi users, which might have vecome trivial
2077     for (auto out : outs) {
2078         if (acc.IsValueSelector(out)) {
2079             auto result = TryRemoveTrivialPhi(out);
2080             if (same == out) {
2081                 same = result;
2082             }
2083         }
2084     }
2085     return same;
2086 }
2087 
ClearConstantCache(GateRef gate)2088 void CircuitBuilder::ClearConstantCache(GateRef gate)
2089 {
2090     ASSERT(acc_.GetOpCode(gate) == OpCode::CONSTANT);
2091     auto machineType = acc_.GetMachineType(gate);
2092     auto value = acc_.GetConstantValue(gate);
2093     auto gateType = acc_.GetGateType(gate);
2094     GetCircuit()->ClearConstantCache(machineType, value, gateType);
2095 }
2096 }  // namespace panda::ecmascript::kungfu
2097