• 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/global_env.h"
23 #include "ecmascript/js_thread.h"
24 #include "ecmascript/js_function.h"
25 
26 namespace panda::ecmascript::kungfu {
Merge(const std::vector<GateRef> & inList)27 GateRef CircuitBuilder::Merge(const std::vector<GateRef> &inList)
28 {
29     return circuit_->NewGate(circuit_->Merge(inList.size()), inList);
30 }
31 
Selector(OpCode opcode,MachineType machineType,GateRef control,const std::vector<GateRef> & values,int valueCounts,VariableType type)32 GateRef CircuitBuilder::Selector(OpCode opcode, MachineType machineType, GateRef control,
33     const std::vector<GateRef> &values, int valueCounts, VariableType type)
34 {
35     std::vector<GateRef> inList;
36     inList.push_back(control);
37     if (values.size() == 0) {
38         for (int i = 0; i < valueCounts; i++) {
39             inList.push_back(Circuit::NullGate());
40         }
41     } else {
42         for (int i = 0; i < valueCounts; i++) {
43             inList.push_back(values[i]);
44         }
45     }
46     ASSERT((opcode == OpCode::VALUE_SELECTOR) || (opcode == OpCode::DEPEND_SELECTOR));
47     const GateMetaData* meta = (opcode == OpCode::DEPEND_SELECTOR) ?
48         circuit_->DependSelector(valueCounts) : circuit_->ValueSelector(valueCounts);
49     return circuit_->NewGate(meta, machineType, inList.size(), inList.data(), type.GetGateType());
50 }
51 
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 
DependAnd(std::initializer_list<GateRef> args)130 GateRef CircuitBuilder::DependAnd(std::initializer_list<GateRef> args)
131 {
132     return circuit_->NewGate(circuit_->DependAnd(), args);
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,GateRef gate,GateRef index)141 GateRef CircuitBuilder::ObjectTypeCheck(GateType type, GateRef gate, GateRef index)
142 {
143     auto currentLabel = env_->GetCurrentLabel();
144     auto currentControl = currentLabel->GetControl();
145     auto currentDepend = currentLabel->GetDepend();
146     ASSERT(acc_.HasFrameState(currentDepend));
147     auto frameState = acc_.GetFrameState(currentDepend);
148     GateRef ret = GetCircuit()->NewGate(circuit_->ObjectTypeCheck(static_cast<size_t>(type.Value())),
149         MachineType::I1, {currentControl, currentDepend, gate, index, frameState}, GateType::NJSValue());
150     currentLabel->SetControl(ret);
151     currentLabel->SetDepend(ret);
152     return ret;
153 }
154 
ArrayCheck(GateRef gate)155 GateRef CircuitBuilder::ArrayCheck(GateRef gate)
156 {
157     auto currentLabel = env_->GetCurrentLabel();
158     auto currentControl = currentLabel->GetControl();
159     auto currentDepend = currentLabel->GetDepend();
160     ASSERT(acc_.HasFrameState(currentDepend));
161     auto frameState = acc_.GetFrameState(currentDepend);
162     GateRef ret = GetCircuit()->NewGate(circuit_->ArrayCheck(),
163         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
164     currentLabel->SetControl(ret);
165     currentLabel->SetDepend(ret);
166     return ret;
167 }
168 
StableArrayCheck(GateRef gate)169 GateRef CircuitBuilder::StableArrayCheck(GateRef gate)
170 {
171     auto currentLabel = env_->GetCurrentLabel();
172     auto currentControl = currentLabel->GetControl();
173     auto currentDepend = currentLabel->GetDepend();
174     ASSERT(acc_.HasFrameState(currentDepend));
175     auto frameState = acc_.GetFrameState(currentDepend);
176     GateRef ret = GetCircuit()->NewGate(circuit_->StableArrayCheck(),
177         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
178     currentLabel->SetControl(ret);
179     currentLabel->SetDepend(ret);
180     return ret;
181 }
182 
TypedArrayCheck(GateType type,GateRef gate)183 GateRef CircuitBuilder::TypedArrayCheck(GateType type, GateRef gate)
184 {
185     auto currentLabel = env_->GetCurrentLabel();
186     auto currentControl = currentLabel->GetControl();
187     auto currentDepend = currentLabel->GetDepend();
188     ASSERT(acc_.HasFrameState(currentDepend));
189     auto frameState = acc_.GetFrameState(currentDepend);
190     GateRef ret = GetCircuit()->NewGate(circuit_->TypedArrayCheck(static_cast<size_t>(type.Value())),
191         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
192     currentLabel->SetControl(ret);
193     currentLabel->SetDepend(ret);
194     return ret;
195 }
196 
IndexCheck(GateType type,GateRef gate,GateRef index)197 GateRef CircuitBuilder::IndexCheck(GateType type, GateRef gate, GateRef index)
198 {
199     auto currentLabel = env_->GetCurrentLabel();
200     auto currentControl = currentLabel->GetControl();
201     auto currentDepend = currentLabel->GetDepend();
202     ASSERT(acc_.HasFrameState(currentDepend));
203     auto frameState = acc_.GetFrameState(currentDepend);
204     GateRef ret = GetCircuit()->NewGate(circuit_->IndexCheck(static_cast<size_t>(type.Value())),
205         MachineType::I1, {currentControl, currentDepend, gate, index, frameState}, GateType::NJSValue());
206     currentLabel->SetControl(ret);
207     currentLabel->SetDepend(ret);
208     return ret;
209 }
210 
PrimitiveTypeCheck(GateType type,GateRef gate)211 GateRef CircuitBuilder::PrimitiveTypeCheck(GateType type, GateRef gate)
212 {
213     auto currentLabel = env_->GetCurrentLabel();
214     auto currentControl = currentLabel->GetControl();
215     auto currentDepend = currentLabel->GetDepend();
216     ASSERT(acc_.HasFrameState(currentDepend));
217     auto frameState = acc_.GetFrameState(currentDepend);
218     GateRef ret = GetCircuit()->NewGate(circuit_->PrimitiveTypeCheck(static_cast<size_t>(type.Value())),
219         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
220     currentLabel->SetControl(ret);
221     currentLabel->SetDepend(ret);
222     return ret;
223 }
224 
CallTargetCheck(GateRef function,GateRef id,GateRef param)225 GateRef CircuitBuilder::CallTargetCheck(GateRef function, GateRef id, GateRef param)
226 {
227     auto currentLabel = env_->GetCurrentLabel();
228     auto currentControl = currentLabel->GetControl();
229     auto currentDepend = currentLabel->GetDepend();
230     ASSERT(acc_.HasFrameState(currentDepend));
231     auto frameState = acc_.GetFrameState(currentDepend);
232     GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallCheck(),
233         MachineType::I1, { currentControl, currentDepend, function, id, param, frameState}, GateType::NJSValue());
234     currentLabel->SetControl(ret);
235     currentLabel->SetDepend(ret);
236     return ret;
237 }
238 
DeoptCheck(GateRef condition,GateRef frameState,DeoptType type)239 GateRef CircuitBuilder::DeoptCheck(GateRef condition, GateRef frameState, DeoptType type)
240 {
241     auto currentLabel = env_->GetCurrentLabel();
242     auto currentControl = currentLabel->GetControl();
243     auto currentDepend = currentLabel->GetDepend();
244     GateRef ret = GetCircuit()->NewGate(circuit_->DeoptCheck(),
245         MachineType::I1, { currentControl, currentDepend, condition,
246             frameState, Int64(static_cast<int64_t>(type))}, GateType::NJSValue());
247     currentLabel->SetControl(ret);
248     currentLabel->SetDepend(ret);
249     return ret;
250 }
251 
TypedNewAllocateThis(GateRef ctor,GateRef hclassIndex,GateRef frameState)252 GateRef CircuitBuilder::TypedNewAllocateThis(GateRef ctor, GateRef hclassIndex, GateRef frameState)
253 {
254     auto currentLabel = env_->GetCurrentLabel();
255     auto currentControl = currentLabel->GetControl();
256     auto currentDepend = currentLabel->GetDepend();
257     ASSERT(acc_.HasFrameState(currentDepend));
258     GateRef ret = GetCircuit()->NewGate(circuit_->TypedNewAllocateThis(),
259         MachineType::ANYVALUE, {currentControl, currentDepend, ctor, hclassIndex, frameState}, GateType::TaggedValue());
260     currentLabel->SetControl(ret);
261     currentLabel->SetDepend(ret);
262     return ret;
263 }
264 
TypedSuperAllocateThis(GateRef superCtor,GateRef newTarget,GateRef frameState)265 GateRef CircuitBuilder::TypedSuperAllocateThis(GateRef superCtor, GateRef newTarget, GateRef frameState)
266 {
267     auto currentLabel = env_->GetCurrentLabel();
268     auto currentControl = currentLabel->GetControl();
269     auto currentDepend = currentLabel->GetDepend();
270     GateRef ret = GetCircuit()->NewGate(circuit_->TypedSuperAllocateThis(), MachineType::ANYVALUE,
271         {currentControl, currentDepend, superCtor, newTarget, frameState}, GateType::TaggedValue());
272     currentLabel->SetControl(ret);
273     currentLabel->SetDepend(ret);
274     return ret;
275 }
276 
GetSuperConstructor(GateRef ctor)277 GateRef CircuitBuilder::GetSuperConstructor(GateRef ctor)
278 {
279     auto currentLabel = env_->GetCurrentLabel();
280     auto currentControl = currentLabel->GetControl();
281     auto currentDepend = currentLabel->GetDepend();
282     auto ret = GetCircuit()->NewGate(circuit_->GetSuperConstructor(), MachineType::ANYVALUE,
283                                      { currentControl, currentDepend, ctor }, GateType::TaggedValue());
284     currentLabel->SetControl(ret);
285     currentLabel->SetDepend(ret);
286     return ret;
287 }
288 
TypedBinaryOperator(MachineType type,TypedBinOp binOp,GateType typeLeft,GateType typeRight,std::vector<GateRef> inList,GateType gateType)289 GateRef CircuitBuilder::TypedBinaryOperator(MachineType type, TypedBinOp binOp, GateType typeLeft, GateType typeRight,
290                                             std::vector<GateRef> inList, GateType gateType)
291 {
292     uint64_t operandTypes = GatePairTypeAccessor::ToValue(typeLeft, typeRight);
293     return GetCircuit()->NewGate(circuit_->TypedBinaryOp(operandTypes, binOp),
294         type, inList.size(), inList.data(), gateType);
295 }
296 
TypedCallOperator(MachineType type,const std::initializer_list<GateRef> & args)297 GateRef CircuitBuilder::TypedCallOperator(MachineType type, const std::initializer_list<GateRef>& args)
298 {
299     auto numValueIn = args.size() - 2; // 2: state & depend
300     return GetCircuit()->NewGate(circuit_->TypedCall(numValueIn), type, args, GateType::AnyType());
301 }
302 
TypeConvert(MachineType type,GateType typeFrom,GateType typeTo,const std::vector<GateRef> & inList)303 GateRef CircuitBuilder::TypeConvert(MachineType type, GateType typeFrom, GateType typeTo,
304                                     const std::vector<GateRef>& inList)
305 {
306     // merge types of valueIns before and after convertion
307     uint64_t operandTypes = GatePairTypeAccessor::ToValue(typeFrom, typeTo);
308     return GetCircuit()->NewGate(circuit_->TypedConvert(operandTypes),
309         type, inList.size(), inList.data(), GateType::AnyType());
310 }
311 
TypedUnaryOperator(MachineType type,TypedUnOp unaryOp,GateType typeVal,const std::vector<GateRef> & inList,GateType gateType)312 GateRef CircuitBuilder::TypedUnaryOperator(MachineType type, TypedUnOp unaryOp, GateType typeVal,
313                                            const std::vector<GateRef>& inList, GateType gateType)
314 {
315     uint64_t value = TypedUnaryAccessor::ToValue(typeVal, unaryOp);
316     return GetCircuit()->NewGate(circuit_->TypedUnaryOp(value),
317         type, inList.size(), inList.data(), gateType);
318 }
319 
Int8(int8_t val)320 GateRef CircuitBuilder::Int8(int8_t val)
321 {
322     return GetCircuit()->GetConstantGate(MachineType::I8, val, GateType::NJSValue());
323 }
324 
Int16(int16_t val)325 GateRef CircuitBuilder::Int16(int16_t val)
326 {
327     return GetCircuit()->GetConstantGate(MachineType::I16, val, GateType::NJSValue());
328 }
329 
Int32(int32_t val)330 GateRef CircuitBuilder::Int32(int32_t val)
331 {
332     return GetCircuit()->GetConstantGate(MachineType::I32, static_cast<BitField>(val), GateType::NJSValue());
333 }
334 
Int64(int64_t val)335 GateRef CircuitBuilder::Int64(int64_t val)
336 {
337     return GetCircuit()->GetConstantGate(MachineType::I64, val, GateType::NJSValue());
338 }
339 
IntPtr(int64_t val)340 GateRef CircuitBuilder::IntPtr(int64_t val)
341 {
342     return GetCircuit()->GetConstantGate(MachineType::ARCH, val, GateType::NJSValue());
343 }
344 
RelocatableData(uint64_t val)345 GateRef CircuitBuilder::RelocatableData(uint64_t val)
346 {
347     return GetCircuit()->NewGate(circuit_->RelocatableData(val),
348         MachineType::ARCH, GateType::TaggedValue());
349 }
350 
Boolean(bool val)351 GateRef CircuitBuilder::Boolean(bool val)
352 {
353     return GetCircuit()->GetConstantGate(MachineType::I1, val ? 1 : 0, GateType::NJSValue());
354 }
355 
Double(double val)356 GateRef CircuitBuilder::Double(double val)
357 {
358     return GetCircuit()->GetConstantGate(MachineType::F64, bit_cast<int64_t>(val), GateType::NJSValue());
359 }
360 
HoleConstant()361 GateRef CircuitBuilder::HoleConstant()
362 {
363     auto type = GateType::TaggedValue();
364     return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_HOLE, type);
365 }
366 
NullConstant()367 GateRef CircuitBuilder::NullConstant()
368 {
369     auto type = GateType::TaggedValue();
370     return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_NULL, type);
371 }
372 
ExceptionConstant()373 GateRef CircuitBuilder::ExceptionConstant()
374 {
375     auto type = GateType::TaggedValue();
376     return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_EXCEPTION, type);
377 }
378 
GetMachineTypeFromVariableType(VariableType type)379 MachineType CircuitBuilder::GetMachineTypeFromVariableType(VariableType type)
380 {
381     return type.GetMachineType();
382 }
383 
BinaryArithmetic(const GateMetaData * meta,MachineType machineType,GateRef left,GateRef right)384 GateRef CircuitBuilder::BinaryArithmetic(const GateMetaData* meta, MachineType machineType, GateRef left, GateRef right)
385 {
386     auto circuit = GetCircuit();
387     GateType type = acc_.GetGateType(left);
388     return circuit->NewGate(meta, machineType, { left, right }, type);
389 }
390 
BinaryCmp(const GateMetaData * meta,GateRef left,GateRef right)391 GateRef CircuitBuilder::BinaryCmp(const GateMetaData* meta, GateRef left, GateRef right)
392 {
393     return GetCircuit()->NewGate(meta, MachineType::I1, { left, right }, GateType::NJSValue());
394 }
395 
CallBCHandler(GateRef glue,GateRef target,const std::vector<GateRef> & args)396 GateRef CircuitBuilder::CallBCHandler(GateRef glue, GateRef target, const std::vector<GateRef> &args)
397 {
398     const CallSignature *cs = BytecodeStubCSigns::BCHandler();
399     ASSERT(cs->IsBCStub());
400     auto label = GetCurrentLabel();
401     auto depend = label->GetDepend();
402     GateRef result = Call(cs, glue, target, depend, args);
403     label->SetDepend(result);
404     return result;
405 }
406 
CallBuiltin(GateRef glue,GateRef target,const std::vector<GateRef> & args)407 GateRef CircuitBuilder::CallBuiltin(GateRef glue, GateRef target, const std::vector<GateRef> &args)
408 {
409     const CallSignature *cs = BuiltinsStubCSigns::BuiltinsCSign();
410     ASSERT(cs->IsBuiltinsStub());
411     auto label = GetCurrentLabel();
412     auto depend = label->GetDepend();
413     GateRef result = Call(cs, glue, target, depend, args);
414     label->SetDepend(result);
415     return result;
416 }
417 
CallBuiltinWithArgv(GateRef glue,GateRef target,const std::vector<GateRef> & args)418 GateRef CircuitBuilder::CallBuiltinWithArgv(GateRef glue, GateRef target, const std::vector<GateRef> &args)
419 {
420     const CallSignature *cs = BuiltinsStubCSigns::BuiltinsWithArgvCSign();
421     ASSERT(cs->IsBuiltinsWithArgvStub());
422     auto label = GetCurrentLabel();
423     auto depend = label->GetDepend();
424     GateRef result = Call(cs, glue, target, depend, args);
425     label->SetDepend(result);
426     return result;
427 }
428 
CallBCDebugger(GateRef glue,GateRef target,const std::vector<GateRef> & args)429 GateRef CircuitBuilder::CallBCDebugger(GateRef glue, GateRef target, const std::vector<GateRef> &args)
430 {
431     const CallSignature *cs = BytecodeStubCSigns::BCDebuggerHandler();
432     ASSERT(cs->IsBCDebuggerStub());
433     auto label = GetCurrentLabel();
434     auto depend = label->GetDepend();
435     GateRef result = Call(cs, glue, target, depend, args);
436     label->SetDepend(result);
437     return result;
438 }
439 
CallRuntime(GateRef glue,int index,GateRef depend,const std::vector<GateRef> & args)440 GateRef CircuitBuilder::CallRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args)
441 {
442     GateRef target = IntPtr(index);
443     const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
444     ASSERT(cs->IsRuntimeStub());
445     auto label = GetCurrentLabel();
446     if (depend == Gate::InvalidGateRef) {
447         depend = label->GetDepend();
448     }
449     GateRef result = Call(cs, glue, target, depend, args);
450     label->SetDepend(result);
451     return result;
452 }
453 
CallRuntimeVarargs(GateRef glue,int index,GateRef argc,GateRef argv)454 GateRef CircuitBuilder::CallRuntimeVarargs(GateRef glue, int index, GateRef argc, GateRef argv)
455 {
456     const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntimeWithArgv));
457     GateRef target = IntPtr(index);
458     auto label = GetCurrentLabel();
459     auto depend = label->GetDepend();
460     ASSERT(cs->IsRuntimeVAStub());
461     GateRef result = Call(cs, glue, target, depend, {argc, argv});
462     label->SetDepend(result);
463     return result;
464 }
465 
466 // call operation
CallNGCRuntime(GateRef glue,int index,GateRef depend,const std::vector<GateRef> & args)467 GateRef CircuitBuilder::CallNGCRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args)
468 {
469     const CallSignature *cs = RuntimeStubCSigns::Get(index);
470     ASSERT(cs->IsRuntimeNGCStub());
471     GateRef target = IntPtr(index);
472     auto label = GetCurrentLabel();
473     if (depend == Gate::InvalidGateRef) {
474         depend = label->GetDepend();
475     }
476     GateRef result = Call(cs, glue, target, depend, args);
477     label->SetDepend(result);
478     return result;
479 }
480 
CallStub(GateRef glue,int index,const std::vector<GateRef> & args)481 GateRef CircuitBuilder::CallStub(GateRef glue, int index, const std::vector<GateRef> &args)
482 {
483     const CallSignature *cs = CommonStubCSigns::Get(index);
484     ASSERT(cs->IsCommonStub());
485     GateRef target = IntPtr(index);
486     auto label = GetCurrentLabel();
487     auto depend = label->GetDepend();
488     GateRef result = Call(cs, glue, target, depend, args);
489     label->SetDepend(result);
490     return result;
491 }
492 
CallBuiltinRuntime(GateRef glue,GateRef depend,const std::vector<GateRef> & args,bool isNew)493 GateRef CircuitBuilder::CallBuiltinRuntime(GateRef glue, GateRef depend, const std::vector<GateRef> &args, bool isNew)
494 {
495     int index = 0;
496     if (!isNew) {
497         index = static_cast<int>(RTSTUB_ID(PushCallArgsAndDispatchNative));
498     } else {
499         index = static_cast<int>(RTSTUB_ID(PushCallNewAndDispatchNative));
500     }
501 
502     const CallSignature *cs = RuntimeStubCSigns::Get(index);
503     GateRef target = IntPtr(index);
504     auto label = GetCurrentLabel();
505     if (depend == Gate::InvalidGateRef) {
506         depend = label->GetDepend();
507     }
508     GateRef result = Call(cs, glue, target, depend, args);
509     label->SetDepend(result);
510     return result;
511 }
512 
Call(const CallSignature * cs,GateRef glue,GateRef target,GateRef depend,const std::vector<GateRef> & args)513 GateRef CircuitBuilder::Call(const CallSignature* cs, GateRef glue, GateRef target, GateRef depend,
514                              const std::vector<GateRef> &args)
515 {
516     std::vector<GateRef> inputs { depend, target, glue };
517     inputs.insert(inputs.end(), args.begin(), args.end());
518     auto numValuesIn = args.size() + 2; // 2: target & glue
519     const GateMetaData* meta = nullptr;
520     if (cs->IsCommonStub()) {
521         meta = circuit_->Call(numValuesIn);
522     } else if (cs->IsRuntimeVAStub()) {
523         meta = circuit_->RuntimeCallWithArgv(numValuesIn);
524     } else if (cs->IsRuntimeStub()) {
525         meta = circuit_->RuntimeCall(numValuesIn);
526     } else if (cs->IsBCDebuggerStub()) {
527         meta = circuit_->DebuggerBytecodeCall(numValuesIn);
528     } else if (cs->IsBCHandlerStub()) {
529         meta = circuit_->BytecodeCall(numValuesIn);
530     } else if (cs->IsBuiltinsStub()) {
531         meta = circuit_->BuiltinsCall(numValuesIn);
532     } else if (cs->IsBuiltinsWithArgvStub()) {
533         meta = circuit_->BuiltinsCallWithArgv(numValuesIn);
534     } else if (cs->IsRuntimeNGCStub()) {
535         meta = circuit_->NoGcRuntimeCall(numValuesIn);
536     } else {
537         UNREACHABLE();
538     }
539     MachineType machineType = cs->GetReturnType().GetMachineType();
540     GateType type = cs->GetReturnType().GetGateType();
541     GateRef result = GetCircuit()->NewGate(meta, machineType, inputs.size(), inputs.data(), type);
542     return result;
543 }
544 
545 // memory
Store(VariableType type,GateRef glue,GateRef base,GateRef offset,GateRef value)546 void CircuitBuilder::Store(VariableType type, GateRef glue, GateRef base, GateRef offset, GateRef value)
547 {
548     auto label = GetCurrentLabel();
549     auto depend = label->GetDepend();
550     GateRef ptr = PtrAdd(base, offset);
551     GateRef result = GetCircuit()->NewGate(circuit_->Store(),
552         MachineType::NOVALUE, { depend, value, ptr }, type.GetGateType());
553     label->SetDepend(result);
554     if (type == VariableType::JS_POINTER() || type == VariableType::JS_ANY()) {
555         CallStub(glue, CommonStubCSigns::SetValueWithBarrier, { glue, base, offset, value });
556     }
557 }
558 
Alloca(size_t size)559 GateRef CircuitBuilder::Alloca(size_t size)
560 {
561     return GetCircuit()->NewGate(circuit_->Alloca(size), MachineType::ARCH, GateType::NJSValue());
562 }
563 
ToLength(GateRef receiver)564 GateRef CircuitBuilder::ToLength(GateRef receiver)
565 {
566     auto currentLabel = env_->GetCurrentLabel();
567     auto currentControl = currentLabel->GetControl();
568     auto currentDepend = currentLabel->GetDepend();
569     auto ret = GetCircuit()->NewGate(circuit_->ToLength(), MachineType::I64,
570                                      { currentControl, currentDepend, receiver }, GateType::NumberType());
571     currentLabel->SetControl(ret);
572     currentLabel->SetDepend(ret);
573     return ret;
574 }
575 
HeapAlloc(GateRef initialHClass,GateType type,RegionSpaceFlag flag)576 GateRef CircuitBuilder::HeapAlloc(GateRef initialHClass, GateType type, RegionSpaceFlag flag)
577 {
578     auto currentLabel = env_->GetCurrentLabel();
579     auto currentControl = currentLabel->GetControl();
580     auto currentDepend = currentLabel->GetDepend();
581     auto ret = GetCircuit()->NewGate(circuit_->HeapAlloc(flag), MachineType::ANYVALUE,
582                                      { currentControl, currentDepend, initialHClass }, type);
583     currentLabel->SetControl(ret);
584     currentLabel->SetDepend(ret);
585     return ret;
586 }
587 
LoadProperty(GateRef receiver,GateRef offset)588 GateRef CircuitBuilder::LoadProperty(GateRef receiver, GateRef offset)
589 {
590     auto currentLabel = env_->GetCurrentLabel();
591     auto currentControl = currentLabel->GetControl();
592     auto currentDepend = currentLabel->GetDepend();
593     auto ret = GetCircuit()->NewGate(circuit_->LoadProperty(), MachineType::I64,
594                                      { currentControl, currentDepend, receiver, offset }, GateType::AnyType());
595     currentLabel->SetControl(ret);
596     currentLabel->SetDepend(ret);
597     return ret;
598 }
599 
StoreProperty(GateRef receiver,GateRef offset,GateRef value)600 GateRef CircuitBuilder::StoreProperty(GateRef receiver, GateRef offset, GateRef value)
601 {
602     auto currentLabel = env_->GetCurrentLabel();
603     auto currentControl = currentLabel->GetControl();
604     auto currentDepend = currentLabel->GetDepend();
605     auto ret = GetCircuit()->NewGate(circuit_->StoreProperty(), MachineType::I64,
606                                      { currentControl, currentDepend, receiver, offset, value }, GateType::AnyType());
607     currentLabel->SetControl(ret);
608     currentLabel->SetDepend(ret);
609     return ret;
610 }
611 
LoadArrayLength(GateRef array)612 GateRef CircuitBuilder::LoadArrayLength(GateRef array)
613 {
614     auto currentLabel = env_->GetCurrentLabel();
615     auto currentControl = currentLabel->GetControl();
616     auto currentDepend = currentLabel->GetDepend();
617     auto ret = GetCircuit()->NewGate(circuit_->LoadArrayLength(), MachineType::I64,
618                                      { currentControl, currentDepend, array }, GateType::IntType());
619     currentLabel->SetControl(ret);
620     currentLabel->SetDepend(ret);
621     return ret;
622 }
623 
Construct(std::vector<GateRef> args)624 GateRef CircuitBuilder::Construct(std::vector<GateRef> args)
625 {
626     auto currentLabel = env_->GetCurrentLabel();
627     auto currentControl = currentLabel->GetControl();
628     auto currentDepend = currentLabel->GetDepend();
629     uint64_t bitfield = args.size();
630     args.insert(args.begin(), currentDepend);
631     args.insert(args.begin(), currentControl);
632     auto callGate = GetCircuit()->NewGate(circuit_->Construct(bitfield), MachineType::I64,
633                                           args.size(), args.data(), GateType::AnyType());
634     currentLabel->SetControl(callGate);
635     currentLabel->SetDepend(callGate);
636     return callGate;
637 }
638 
HasPendingException(GateRef glue)639 GateRef CircuitBuilder::HasPendingException(GateRef glue)
640 {
641     GateRef exceptionOffset = IntPtr(JSThread::GlueData::GetExceptionOffset(env_->IsArch32Bit()));
642     GateRef exception = Load(VariableType::JS_ANY(), glue, exceptionOffset);
643     return TaggedIsNotHole(exception);
644 }
645 
TaggedIsString(GateRef obj)646 GateRef CircuitBuilder::TaggedIsString(GateRef obj)
647 {
648     Label entry(env_);
649     SubCfgEntry(&entry);
650     Label exit(env_);
651     DEFVAlUE(result, env_, VariableType::BOOL(), False());
652     Label isHeapObject(env_);
653     Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
654     Bind(&isHeapObject);
655     {
656         result = Equal(GetObjectType(LoadHClass(obj)),
657             Int32(static_cast<int32_t>(JSType::STRING)));
658         Jump(&exit);
659     }
660     Bind(&exit);
661     auto ret = *result;
662     SubCfgExit();
663     return ret;
664 }
665 
TaggedIsStringOrSymbol(GateRef obj)666 GateRef CircuitBuilder::TaggedIsStringOrSymbol(GateRef obj)
667 {
668     Label entry(env_);
669     SubCfgEntry(&entry);
670     Label exit(env_);
671     DEFVAlUE(result, env_, VariableType::BOOL(), False());
672     Label isHeapObject(env_);
673     Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
674     Bind(&isHeapObject);
675     {
676         GateRef objType = GetObjectType(LoadHClass(obj));
677         result = Equal(objType, Int32(static_cast<int32_t>(JSType::STRING)));
678         Label isString(env_);
679         Label notString(env_);
680         Branch(*result, &exit, &notString);
681         Bind(&notString);
682         {
683             result = Equal(objType, Int32(static_cast<int32_t>(JSType::SYMBOL)));
684             Jump(&exit);
685         }
686     }
687     Bind(&exit);
688     auto ret = *result;
689     SubCfgExit();
690     return ret;
691 }
692 
IsUtf16String(GateRef string)693 GateRef CircuitBuilder::IsUtf16String(GateRef string)
694 {
695     // compressedStringsEnabled fixed to true constant
696     GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
697     return Int32Equal(
698         Int32And(len, Int32(EcmaString::STRING_COMPRESSED_BIT)),
699         Int32(EcmaString::STRING_UNCOMPRESSED));
700 }
701 
GetGlobalObject(GateRef glue)702 GateRef CircuitBuilder::GetGlobalObject(GateRef glue)
703 {
704     GateRef offset = IntPtr(JSThread::GlueData::GetGlobalObjOffset(cmpCfg_->Is32Bit()));
705     return Load(VariableType::JS_ANY(), glue, offset);
706 }
707 
GetMethodFromFunction(GateRef function)708 GateRef CircuitBuilder::GetMethodFromFunction(GateRef function)
709 {
710     GateRef offset = IntPtr(JSFunctionBase::METHOD_OFFSET);
711     return Load(VariableType::JS_POINTER(), function, offset);
712 }
713 
GetModuleFromFunction(GateRef function)714 GateRef CircuitBuilder::GetModuleFromFunction(GateRef function)
715 {
716     GateRef offset = IntPtr(JSFunction::ECMA_MODULE_OFFSET);
717     return Load(VariableType::JS_POINTER(), function, offset);
718 }
719 
GetHomeObjectFromFunction(GateRef function)720 GateRef CircuitBuilder::GetHomeObjectFromFunction(GateRef function)
721 {
722     GateRef offset = IntPtr(JSFunction::HOME_OBJECT_OFFSET);
723     return Load(VariableType::JS_POINTER(), function, offset);
724 }
725 
GetLengthFromString(GateRef value)726 GateRef CircuitBuilder::GetLengthFromString(GateRef value)
727 {
728     GateRef len = Load(VariableType::INT32(), value, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
729     return Int32LSR(len, Int32(2));  // 2 : 2 means len must be right shift 2 bits
730 }
731 
GetConstPool(GateRef jsFunc)732 GateRef CircuitBuilder::GetConstPool(GateRef jsFunc)
733 {
734     GateRef method = GetMethodFromFunction(jsFunc);
735     return Load(VariableType::JS_ANY(), method, IntPtr(Method::CONSTANT_POOL_OFFSET));
736 }
737 
GetObjectFromConstPool(GateRef glue,GateRef jsFunc,GateRef index,ConstPoolType type)738 GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef jsFunc, GateRef index, ConstPoolType type)
739 {
740     GateRef constPool = GetConstPool(jsFunc);
741     GateRef module = GetModuleFromFunction(jsFunc);
742     return GetObjectFromConstPool(glue, constPool, module, index, type);
743 }
744 
GetObjectFromConstPool(GateRef glue,GateRef constPool,GateRef module,GateRef index,ConstPoolType type)745 GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef constPool, GateRef module, GateRef index,
746                                                ConstPoolType type)
747 {
748     Label entry(env_);
749     SubCfgEntry(&entry);
750     Label exit(env_);
751     Label cacheMiss(env_);
752     Label cache(env_);
753 
754     auto cacheValue = GetValueFromTaggedArray(constPool, index);
755     DEFVAlUE(result, env_, VariableType::JS_ANY(), cacheValue);
756     Branch(TaggedIsHole(*result), &cacheMiss, &cache);
757     Bind(&cacheMiss);
758     {
759         if (type == ConstPoolType::STRING) {
760             result = CallRuntime(glue, RTSTUB_ID(GetStringFromCache), Gate::InvalidGateRef,
761                 { constPool, Int32ToTaggedInt(index) });
762         } else if (type == ConstPoolType::ARRAY_LITERAL) {
763             result = CallRuntime(glue, RTSTUB_ID(GetArrayLiteralFromCache), Gate::InvalidGateRef,
764                 { constPool, Int32ToTaggedInt(index), module });
765         } else if (type == ConstPoolType::OBJECT_LITERAL) {
766             result = CallRuntime(glue, RTSTUB_ID(GetObjectLiteralFromCache), Gate::InvalidGateRef,
767                 { constPool, Int32ToTaggedInt(index), module });
768         } else {
769             result = CallRuntime(glue, RTSTUB_ID(GetMethodFromCache), Gate::InvalidGateRef,
770                 { constPool, Int32ToTaggedInt(index) });
771         }
772         Jump(&exit);
773     }
774     Bind(&cache);
775     {
776         if (type == ConstPoolType::METHOD) {
777             Label isInt(env_);
778             Branch(TaggedIsInt(*result), &isInt, &exit);
779             Bind(&isInt);
780             {
781                 result = CallRuntime(glue, RTSTUB_ID(GetMethodFromCache), Gate::InvalidGateRef,
782                     { constPool, Int32ToTaggedInt(index) });
783                 Jump(&exit);
784             }
785         } else if (type == ConstPoolType::ARRAY_LITERAL) {
786             Label isAOTLiteralInfo(env_);
787             Branch(IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit);
788             Bind(&isAOTLiteralInfo);
789             {
790                 result = CallRuntime(glue, RTSTUB_ID(GetArrayLiteralFromCache), Gate::InvalidGateRef,
791                     { constPool, Int32ToTaggedInt(index), module });
792                 Jump(&exit);
793             }
794         } else if (type == ConstPoolType::OBJECT_LITERAL)  {
795             Label isAOTLiteralInfo(env_);
796             Branch(IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit);
797             Bind(&isAOTLiteralInfo);
798             {
799                 result = CallRuntime(glue, RTSTUB_ID(GetObjectLiteralFromCache), Gate::InvalidGateRef,
800                     { constPool, Int32ToTaggedInt(index), module });
801                 Jump(&exit);
802             }
803         } else {
804             Jump(&exit);
805         }
806     }
807     Bind(&exit);
808     auto ret = *result;
809     SubCfgExit();
810     return ret;
811 }
812 
GetHashcodeFromString(GateRef glue,GateRef value)813 GateRef CircuitBuilder::GetHashcodeFromString(GateRef glue, GateRef value)
814 {
815     Label subentry(env_);
816     SubCfgEntry(&subentry);
817     Label noRawHashcode(env_);
818     Label exit(env_);
819     DEFVAlUE(hashcode, env_, VariableType::INT32(), Int32(0));
820     hashcode = Load(VariableType::INT32(), value, IntPtr(EcmaString::HASHCODE_OFFSET));
821     Branch(Int32Equal(*hashcode, Int32(0)), &noRawHashcode, &exit);
822     Bind(&noRawHashcode);
823     {
824         hashcode = GetInt32OfTInt(CallRuntime(glue, RTSTUB_ID(ComputeHashcode), Gate::InvalidGateRef, { value }));
825         Store(VariableType::INT32(), glue, value, IntPtr(EcmaString::HASHCODE_OFFSET), *hashcode);
826         Jump(&exit);
827     }
828     Bind(&exit);
829     auto ret = *hashcode;
830     SubCfgExit();
831     return ret;
832 }
833 
TaggedIsBigInt(GateRef obj)834 GateRef CircuitBuilder::TaggedIsBigInt(GateRef obj)
835 {
836     Label entry(env_);
837     SubCfgEntry(&entry);
838     Label exit(env_);
839     DEFVAlUE(result, env_, VariableType::BOOL(), False());
840     Label isHeapObject(env_);
841     Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
842     Bind(&isHeapObject);
843     {
844         result = Int32Equal(GetObjectType(LoadHClass(obj)),
845                             Int32(static_cast<int32_t>(JSType::BIGINT)));
846         Jump(&exit);
847     }
848     Bind(&exit);
849     auto ret = *result;
850     SubCfgExit();
851     return ret;
852 }
853 
SetLexicalEnvToFunction(GateRef glue,GateRef function,GateRef value)854 void CircuitBuilder::SetLexicalEnvToFunction(GateRef glue, GateRef function, GateRef value)
855 {
856     GateRef offset = IntPtr(JSFunction::LEXICAL_ENV_OFFSET);
857     Store(VariableType::JS_ANY(), glue, function, offset, value);
858 }
859 
GetFunctionLexicalEnv(GateRef function)860 GateRef CircuitBuilder::GetFunctionLexicalEnv(GateRef function)
861 {
862     return Load(VariableType::JS_POINTER(), function, IntPtr(JSFunction::LEXICAL_ENV_OFFSET));
863 }
864 
SetModuleToFunction(GateRef glue,GateRef function,GateRef value)865 void CircuitBuilder::SetModuleToFunction(GateRef glue, GateRef function, GateRef value)
866 {
867     GateRef offset = IntPtr(JSFunction::ECMA_MODULE_OFFSET);
868     Store(VariableType::JS_POINTER(), glue, function, offset, value);
869 }
870 
SetPropertyInlinedProps(GateRef glue,GateRef obj,GateRef hClass,GateRef value,GateRef attrOffset,VariableType type)871 void CircuitBuilder::SetPropertyInlinedProps(GateRef glue, GateRef obj, GateRef hClass,
872     GateRef value, GateRef attrOffset, VariableType type)
873 {
874     GateRef bitfield = Load(VariableType::INT32(), hClass, IntPtr(JSHClass::BIT_FIELD1_OFFSET));
875     GateRef inlinedPropsStart = Int32And(Int32LSR(bitfield,
876         Int32(JSHClass::InlinedPropsStartBits::START_BIT)),
877         Int32((1LU << JSHClass::InlinedPropsStartBits::SIZE) - 1));
878     GateRef propOffset = Int32Mul(Int32Add(inlinedPropsStart, attrOffset),
879         Int32(JSTaggedValue::TaggedTypeSize()));
880     Store(type, glue, obj, ZExtInt32ToPtr(propOffset), value);
881 }
882 
SetHomeObjectToFunction(GateRef glue,GateRef function,GateRef value)883 void CircuitBuilder::SetHomeObjectToFunction(GateRef glue, GateRef function, GateRef value)
884 {
885     GateRef offset = IntPtr(JSFunction::HOME_OBJECT_OFFSET);
886     Store(VariableType::JS_ANY(), glue, function, offset, value);
887 }
888 
GetGlobalEnvValue(VariableType type,GateRef env,size_t index)889 GateRef CircuitBuilder::GetGlobalEnvValue(VariableType type, GateRef env, size_t index)
890 {
891     auto valueIndex = IntPtr(GlobalEnv::HEADER_SIZE + JSTaggedValue::TaggedTypeSize() * index);
892     return Load(type, env, valueIndex);
893 }
894 
GetGlobalConstantValue(VariableType type,GateRef glue,ConstantIndex index)895 GateRef CircuitBuilder::GetGlobalConstantValue(VariableType type, GateRef glue, ConstantIndex index)
896 {
897     GateRef gConstAddr = PtrAdd(glue,
898         IntPtr(JSThread::GlueData::GetGlobalConstOffset(cmpCfg_->Is32Bit())));
899     auto constantIndex = IntPtr(JSTaggedValue::TaggedTypeSize() * static_cast<size_t>(index));
900     return Load(type, gConstAddr, constantIndex);
901 }
902 
GetCallBuiltinId(GateRef method)903 GateRef CircuitBuilder::GetCallBuiltinId(GateRef method)
904 {
905     GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
906     GateRef extraLiteralInfo = Load(VariableType::INT64(), method, extraLiteralInfoOffset);
907     return Int64And(
908         Int64LSR(extraLiteralInfo, Int64(MethodLiteral::BuiltinIdBits::START_BIT)),
909         Int64((1LU << MethodLiteral::BuiltinIdBits::SIZE) - 1));
910 }
911 
Environment(size_t arguments,CircuitBuilder * builder)912 Environment::Environment(size_t arguments, CircuitBuilder *builder)
913     : circuit_(builder->GetCircuit()), circuitBuilder_(builder), arguments_(arguments)
914 {
915     circuitBuilder_->SetEnvironment(this);
916     SetCompilationConfig(circuitBuilder_->GetCompilationConfig());
917     for (size_t i = 0; i < arguments; i++) {
918         arguments_[i] = circuitBuilder_->Arguments(i);
919     }
920     entry_ = Label(NewLabel(this, circuit_->GetStateRoot()));
921     currentLabel_ = &entry_;
922     currentLabel_->Seal();
923     auto depend_entry = circuit_->GetDependRoot();
924     currentLabel_->SetDepend(depend_entry);
925 }
926 
Environment(GateRef hir,Circuit * circuit,CircuitBuilder * builder)927 Environment::Environment(GateRef hir, Circuit *circuit, CircuitBuilder *builder)
928     : circuit_(circuit), circuitBuilder_(builder)
929 {
930     circuitBuilder_->SetEnvironment(this);
931     SetCompilationConfig(circuitBuilder_->GetCompilationConfig());
932     GateAccessor acc(circuit);
933     entry_ = Label(NewLabel(this, acc.GetIn(hir, 0)));
934     currentLabel_ = &entry_;
935     currentLabel_->Seal();
936     auto dependEntry = acc.GetDep(hir);
937     currentLabel_->SetDepend(dependEntry);
938     for (size_t i = 2; i < acc.GetNumIns(hir); i++) {
939         inputList_.emplace_back(acc.GetIn(hir, i));
940     }
941 }
942 
Environment(GateRef stateEntry,GateRef dependEntry,std::vector<GateRef> & inlist,Circuit * circuit,CircuitBuilder * builder)943 Environment::Environment(GateRef stateEntry, GateRef dependEntry, std::vector<GateRef>& inlist,
944     Circuit *circuit, CircuitBuilder *builder) : circuit_(circuit), circuitBuilder_(builder)
945 {
946     circuitBuilder_->SetEnvironment(this);
947     SetCompilationConfig(circuitBuilder_->GetCompilationConfig());
948     entry_ = Label(NewLabel(this, stateEntry));
949     currentLabel_ = &entry_;
950     currentLabel_->Seal();
951     currentLabel_->SetDepend(dependEntry);
952     for (auto in : inlist) {
953         inputList_.emplace_back(in);
954     }
955 }
956 
~Environment()957 Environment::~Environment()
958 {
959     circuitBuilder_->SetEnvironment(nullptr);
960     for (auto label : rawLabels_) {
961         delete label;
962     }
963 }
964 
Jump(Label * label)965 void CircuitBuilder::Jump(Label *label)
966 {
967     ASSERT(label);
968     auto currentLabel = env_->GetCurrentLabel();
969     auto currentControl = currentLabel->GetControl();
970     auto jump = Goto(currentControl);
971     currentLabel->SetControl(jump);
972     label->AppendPredecessor(currentLabel);
973     label->MergeControl(currentLabel->GetControl());
974     env_->SetCurrentLabel(nullptr);
975 }
976 
Branch(GateRef condition,Label * trueLabel,Label * falseLabel)977 void CircuitBuilder::Branch(GateRef condition, Label *trueLabel, Label *falseLabel)
978 {
979     auto currentLabel = env_->GetCurrentLabel();
980     auto currentControl = currentLabel->GetControl();
981     GateRef ifBranch = Branch(currentControl, condition);
982     currentLabel->SetControl(ifBranch);
983     GateRef ifTrue = IfTrue(ifBranch);
984     trueLabel->AppendPredecessor(GetCurrentLabel());
985     trueLabel->MergeControl(ifTrue);
986     GateRef ifFalse = IfFalse(ifBranch);
987     falseLabel->AppendPredecessor(GetCurrentLabel());
988     falseLabel->MergeControl(ifFalse);
989     env_->SetCurrentLabel(nullptr);
990 }
991 
Switch(GateRef index,Label * defaultLabel,int64_t * keysValue,Label * keysLabel,int numberOfKeys)992 void CircuitBuilder::Switch(GateRef index, Label *defaultLabel, int64_t *keysValue, Label *keysLabel, int numberOfKeys)
993 {
994     auto currentLabel = env_->GetCurrentLabel();
995     auto currentControl = currentLabel->GetControl();
996     GateRef switchBranch = SwitchBranch(currentControl, index, numberOfKeys);
997     currentLabel->SetControl(switchBranch);
998     for (int i = 0; i < numberOfKeys; i++) {
999         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1000         GateRef switchCase = SwitchCase(switchBranch, keysValue[i]);
1001         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1002         keysLabel[i].AppendPredecessor(currentLabel);
1003         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1004         keysLabel[i].MergeControl(switchCase);
1005     }
1006 
1007     GateRef defaultCase = DefaultCase(switchBranch);
1008     defaultLabel->AppendPredecessor(currentLabel);
1009     defaultLabel->MergeControl(defaultCase);
1010     env_->SetCurrentLabel(nullptr);
1011 }
1012 
LoopBegin(Label * loopHead)1013 void CircuitBuilder::LoopBegin(Label *loopHead)
1014 {
1015     ASSERT(loopHead);
1016     auto loopControl = LoopBegin(loopHead->GetControl());
1017     loopHead->SetControl(loopControl);
1018     loopHead->SetPreControl(loopControl);
1019     loopHead->Bind();
1020     env_->SetCurrentLabel(loopHead);
1021 }
1022 
LoopEnd(Label * loopHead)1023 void CircuitBuilder::LoopEnd(Label *loopHead)
1024 {
1025     ASSERT(loopHead);
1026     auto currentLabel = GetCurrentLabel();
1027     auto currentControl = currentLabel->GetControl();
1028     auto loopend = LoopEnd(currentControl);
1029     currentLabel->SetControl(loopend);
1030     loopHead->AppendPredecessor(currentLabel);
1031     loopHead->MergeControl(loopend);
1032     loopHead->Seal();
1033     loopHead->MergeAllControl();
1034     loopHead->MergeAllDepend();
1035     env_->SetCurrentLabel(nullptr);
1036 }
1037 
Label(Environment * env)1038 Label::Label(Environment *env)
1039 {
1040     impl_ = env->NewLabel(env);
1041 }
1042 
Label(CircuitBuilder * cirBuilder)1043 Label::Label(CircuitBuilder *cirBuilder)
1044 {
1045     auto env = cirBuilder->GetCurrentEnvironment();
1046     impl_ = env->NewLabel(env);
1047 }
1048 
Seal()1049 void Label::LabelImpl::Seal()
1050 {
1051     for (auto &[variable, gate] : incompletePhis_) {
1052         variable->AddPhiOperand(gate);
1053     }
1054     isSealed_ = true;
1055 }
1056 
WriteVariable(Variable * var,GateRef value)1057 void Label::LabelImpl::WriteVariable(Variable *var, GateRef value)
1058 {
1059     valueMap_[var] = value;
1060 }
1061 
ReadVariable(Variable * var)1062 GateRef Label::LabelImpl::ReadVariable(Variable *var)
1063 {
1064     if (valueMap_.find(var) != valueMap_.end()) {
1065         auto result = valueMap_.at(var);
1066         GateAccessor acc(env_->GetCircuit());
1067         if (!acc.GetMetaData(result)->IsNop()) {
1068             return result;
1069         }
1070     }
1071     return ReadVariableRecursive(var);
1072 }
1073 
ReadVariableRecursive(Variable * var)1074 GateRef Label::LabelImpl::ReadVariableRecursive(Variable *var)
1075 {
1076     GateRef val;
1077     MachineType machineType = CircuitBuilder::GetMachineTypeFromVariableType(var->Type());
1078     if (!IsSealed()) {
1079         // only loopheader gate will be not sealed
1080         int valueCounts = static_cast<int>(this->predecessors_.size()) + 1;
1081         if (machineType == MachineType::NOVALUE) {
1082             val = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR,
1083                 predeControl_, {}, valueCounts, var->Type());
1084         } else {
1085             val = env_->GetBuilder()->Selector(OpCode::VALUE_SELECTOR,
1086                 machineType, predeControl_, {}, valueCounts, var->Type());
1087         }
1088         env_->AddSelectorToLabel(val, Label(this));
1089         incompletePhis_[var] = val;
1090     } else if (predecessors_.size() == 1) {
1091         val = predecessors_[0]->ReadVariable(var);
1092     } else {
1093         if (machineType == MachineType::NOVALUE) {
1094             val = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR,
1095                 predeControl_, {}, this->predecessors_.size(), var->Type());
1096         } else {
1097             val = env_->GetBuilder()->Selector(OpCode::VALUE_SELECTOR, machineType,
1098                 predeControl_, {}, this->predecessors_.size(), var->Type());
1099         }
1100         env_->AddSelectorToLabel(val, Label(this));
1101         WriteVariable(var, val);
1102         val = var->AddPhiOperand(val);
1103     }
1104     WriteVariable(var, val);
1105     return val;
1106 }
1107 
Bind()1108 void Label::LabelImpl::Bind()
1109 {
1110     ASSERT(!predecessors_.empty());
1111     if (IsLoopHead()) {
1112         // 2 means input number of depend selector gate
1113         loopDepend_ = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR, predeControl_, {}, 2);
1114         GateAccessor(env_->GetCircuit()).NewIn(loopDepend_, 1, predecessors_[0]->GetDepend());
1115         depend_ = loopDepend_;
1116     }
1117     if (IsNeedSeal()) {
1118         Seal();
1119         MergeAllControl();
1120         MergeAllDepend();
1121     }
1122 }
1123 
MergeAllControl()1124 void Label::LabelImpl::MergeAllControl()
1125 {
1126     if (predecessors_.size() < 2) {  // 2 : Loop Head only support two predecessors_
1127         return;
1128     }
1129 
1130     if (IsLoopHead()) {
1131         ASSERT(predecessors_.size() == 2);  // 2 : Loop Head only support two predecessors_
1132         ASSERT(otherPredeControls_.size() == 1);
1133         GateAccessor(env_->GetCircuit()).NewIn(predeControl_, 1, otherPredeControls_[0]);
1134         return;
1135     }
1136 
1137     // merge all control of predecessors_
1138     std::vector<GateRef> inGates(predecessors_.size());
1139     size_t i = 0;
1140     ASSERT(predeControl_ != -1);
1141     ASSERT((otherPredeControls_.size() + 1) == predecessors_.size());
1142     inGates[i++] = predeControl_;
1143     for (auto in : otherPredeControls_) {
1144         inGates[i++] = in;
1145     }
1146 
1147     GateRef merge = env_->GetBuilder()->Merge(inGates);
1148     predeControl_ = merge;
1149     control_ = merge;
1150 }
1151 
MergeAllDepend()1152 void Label::LabelImpl::MergeAllDepend()
1153 {
1154     if (IsControlCase()) {
1155         // Add depend_relay to current label
1156         auto denpendEntry = env_->GetBuilder()->GetCircuit()->GetDependRoot();
1157         dependRelay_ = env_->GetBuilder()->DependRelay(predeControl_, denpendEntry);
1158     }
1159 
1160     if (predecessors_.size() < 2) {  // 2 : Loop Head only support two predecessors_
1161         depend_ = predecessors_[0]->GetDepend();
1162         if (dependRelay_ != -1) {
1163             depend_ = env_->GetBuilder()->DependAnd({depend_, dependRelay_});
1164         }
1165         return;
1166     }
1167     if (IsLoopHead()) {
1168         ASSERT(predecessors_.size() == 2);  // 2 : Loop Head only support two predecessors_
1169         // Add loop depend to in of depend_seclector
1170         ASSERT(loopDepend_ != -1);
1171         // 2 mean 3rd input gate for loopDepend_(depend_selector)
1172         GateAccessor(env_->GetCircuit()).NewIn(loopDepend_, 2, predecessors_[1]->GetDepend());
1173         return;
1174     }
1175 
1176     //  Merge all depends to depend_seclector
1177     std::vector<GateRef> dependsList;
1178     for (auto prede : this->GetPredecessors()) {
1179         dependsList.push_back(prede->GetDepend());
1180     }
1181     depend_ = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR,
1182         predeControl_, dependsList, dependsList.size());
1183 }
1184 
AppendPredecessor(Label::LabelImpl * predecessor)1185 void Label::LabelImpl::AppendPredecessor(Label::LabelImpl *predecessor)
1186 {
1187     if (predecessor != nullptr) {
1188         predecessors_.push_back(predecessor);
1189     }
1190 }
1191 
IsNeedSeal() const1192 bool Label::LabelImpl::IsNeedSeal() const
1193 {
1194     auto stateCount = GateAccessor(env_->GetCircuit()).GetStateCount(predeControl_);
1195     return predecessors_.size() >= stateCount;
1196 }
1197 
IsLoopHead() const1198 bool Label::LabelImpl::IsLoopHead() const
1199 {
1200     return GateAccessor(env_->GetCircuit()).IsLoopHead(predeControl_);
1201 }
1202 
IsControlCase() const1203 bool Label::LabelImpl::IsControlCase() const
1204 {
1205     return GateAccessor(env_->GetCircuit()).IsControlCase(predeControl_);
1206 }
1207 
AddPhiOperand(GateRef val)1208 GateRef Variable::AddPhiOperand(GateRef val)
1209 {
1210     ASSERT(GateAccessor(env_->GetCircuit()).IsSelector(val));
1211     Label label = env_->GetLabelFromSelector(val);
1212     size_t idx = 0;
1213     for (auto pred : label.GetPredecessors()) {
1214         auto preVal = pred.ReadVariable(this);
1215         ASSERT(!GateAccessor(env_->GetCircuit()).GetMetaData(preVal)->IsNop());
1216         idx++;
1217         val = AddOperandToSelector(val, idx, preVal);
1218     }
1219     return TryRemoveTrivialPhi(val);
1220 }
1221 
AddOperandToSelector(GateRef val,size_t idx,GateRef in)1222 GateRef Variable::AddOperandToSelector(GateRef val, size_t idx, GateRef in)
1223 {
1224     GateAccessor(env_->GetCircuit()).NewIn(val, idx, in);
1225     return val;
1226 }
1227 
TryRemoveTrivialPhi(GateRef phi)1228 GateRef Variable::TryRemoveTrivialPhi(GateRef phi)
1229 {
1230     GateAccessor acc(GetCircuit());
1231     GateRef same = Gate::InvalidGateRef;
1232     const size_t inNum = acc.GetNumIns(phi);
1233     for (size_t i = 1; i < inNum; ++i) {
1234         GateRef phiIn = acc.GetIn(phi, i);
1235         if (phiIn == same || phiIn == phi) {
1236             continue;  // unique value or self-reference
1237         }
1238         if (same != Gate::InvalidGateRef) {
1239             return phi;  // the phi merges at least two valusses: not trivial
1240         }
1241         same = phiIn;
1242     }
1243     if (same == Gate::InvalidGateRef) {
1244         // the phi is unreachable or in the start block
1245         GateType type = acc.GetGateType(phi);
1246         same = env_->GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_UNDEFINED, type);
1247     }
1248     // remove the trivial phi
1249     // get all users of phi except self
1250     std::vector<GateRef> outs;
1251     auto uses = acc.Uses(phi);
1252     for (auto use = uses.begin(); use != uses.end();) {
1253         GateRef u = *use;
1254         if (u != phi) {
1255             outs.push_back(u);
1256             use = acc.ReplaceIn(use, same);
1257         } else {
1258             use++;
1259         }
1260     }
1261     acc.DeleteGate(phi);
1262 
1263     // try to recursiveby remove all phi users, which might have vecome trivial
1264     for (auto out : outs) {
1265         if (acc.IsSelector(out)) {
1266             auto result = TryRemoveTrivialPhi(out);
1267             if (same == out) {
1268                 same = result;
1269             }
1270         }
1271     }
1272     return same;
1273 }
1274 }  // namespace panda::ecmascript::kungfu
1275