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