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, ¬String);
681 Bind(¬String);
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