• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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/mcr_circuit_builder.h"
17 #include "ecmascript/message_string.h"
18 #include "ecmascript/stubs/runtime_stubs-inl.h"
19 #include "ecmascript/stubs/runtime_stubs.h"
20 
21 #include "ecmascript/compiler/circuit_builder-inl.h"
22 #include "ecmascript/global_env.h"
23 #include "ecmascript/js_object.h"
24 #include "ecmascript/marker_cell.h"
25 
26 namespace panda::ecmascript::kungfu {
27 
ObjectTypeCheck(GateType type,bool isHeapObject,GateRef gate,GateRef hclassIndex,GateRef frameState)28 GateRef CircuitBuilder::ObjectTypeCheck(GateType type, bool isHeapObject, GateRef gate, GateRef hclassIndex,
29                                         GateRef frameState)
30 {
31     auto currentLabel = env_->GetCurrentLabel();
32     auto currentControl = currentLabel->GetControl();
33     auto currentDepend = currentLabel->GetDepend();
34     if (frameState == Circuit::NullGate()) {
35         frameState = acc_.FindNearestFrameState(currentDepend);
36     }
37     ObjectTypeAccessor accessor(type, isHeapObject);
38     GateRef ret = GetCircuit()->NewGate(circuit_->ObjectTypeCheck(accessor.ToValue()), MachineType::I1,
39         {currentControl, currentDepend, gate, hclassIndex, frameState}, GateType::NJSValue());
40     currentLabel->SetControl(ret);
41     currentLabel->SetDepend(ret);
42     return ret;
43 }
44 
ObjectTypeCompare(GateType type,bool isHeapObject,GateRef gate,GateRef hclassIndex)45 GateRef CircuitBuilder::ObjectTypeCompare(GateType type, bool isHeapObject, GateRef gate, GateRef hclassIndex)
46 {
47     auto currentLabel = env_->GetCurrentLabel();
48     auto currentControl = currentLabel->GetControl();
49     auto currentDepend = currentLabel->GetDepend();
50     auto frameState = acc_.FindNearestFrameState(currentDepend);
51     ObjectTypeAccessor accessor(type, isHeapObject);
52     GateRef ret = GetCircuit()->NewGate(circuit_->ObjectTypeCompare(accessor.ToValue()), MachineType::I1,
53         {currentControl, currentDepend, gate, hclassIndex, frameState}, GateType::NJSValue());
54     currentLabel->SetControl(ret);
55     currentLabel->SetDepend(ret);
56     return ret;
57 }
58 
HeapObjectCheck(GateRef gate,GateRef frameState)59 GateRef CircuitBuilder::HeapObjectCheck(GateRef gate, GateRef frameState)
60 {
61     auto currentLabel = env_->GetCurrentLabel();
62     auto currentControl = currentLabel->GetControl();
63     auto currentDepend = currentLabel->GetDepend();
64     GateRef ret = GetCircuit()->NewGate(circuit_->HeapObjectCheck(),
65                                         MachineType::I1,
66                                         {currentControl, currentDepend, gate, frameState},
67                                         GateType::NJSValue());
68     currentLabel->SetControl(ret);
69     currentLabel->SetDepend(ret);
70     return ret;
71 }
72 
ProtoChangeMarkerCheck(GateRef gate,GateRef frameState)73 GateRef CircuitBuilder::ProtoChangeMarkerCheck(GateRef gate, GateRef frameState)
74 {
75     auto currentLabel = env_->GetCurrentLabel();
76     auto currentControl = currentLabel->GetControl();
77     auto currentDepend = currentLabel->GetDepend();
78     if (frameState == Circuit::NullGate()) {
79         frameState = acc_.FindNearestFrameState(currentDepend);
80     }
81     GateRef ret = GetCircuit()->NewGate(circuit_->ProtoChangeMarkerCheck(),
82                                         MachineType::I1,
83                                         {currentControl, currentDepend, gate, frameState},
84                                         GateType::NJSValue());
85     currentLabel->SetControl(ret);
86     currentLabel->SetDepend(ret);
87     return ret;
88 }
89 
StableArrayCheck(GateRef gate,ElementsKind kind,ArrayMetaDataAccessor::Mode mode)90 GateRef CircuitBuilder::StableArrayCheck(GateRef gate, ElementsKind kind, ArrayMetaDataAccessor::Mode mode)
91 {
92     auto currentLabel = env_->GetCurrentLabel();
93     auto currentControl = currentLabel->GetControl();
94     auto currentDepend = currentLabel->GetDepend();
95     auto frameState = acc_.FindNearestFrameState(currentDepend);
96     ArrayMetaDataAccessor accessor(kind, mode);
97     GateRef ret = GetCircuit()->NewGate(circuit_->StableArrayCheck(accessor.ToValue()),
98         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
99     currentLabel->SetControl(ret);
100     currentLabel->SetDepend(ret);
101     return ret;
102 }
103 
COWArrayCheck(GateRef gate)104 GateRef CircuitBuilder::COWArrayCheck(GateRef gate)
105 {
106     auto currentLabel = env_->GetCurrentLabel();
107     auto currentControl = currentLabel->GetControl();
108     auto currentDepend = currentLabel->GetDepend();
109     auto frameState = acc_.FindNearestFrameState(currentDepend);
110     GateRef ret = GetCircuit()->NewGate(circuit_->COWArrayCheck(),
111         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
112     currentLabel->SetControl(ret);
113     currentLabel->SetDepend(ret);
114     return ret;
115 }
116 
EcmaStringCheck(GateRef gate)117 GateRef CircuitBuilder::EcmaStringCheck(GateRef gate)
118 {
119     auto currentLabel = env_->GetCurrentLabel();
120     auto currentControl = currentLabel->GetControl();
121     auto currentDepend = currentLabel->GetDepend();
122     auto frameState = acc_.FindNearestFrameState(currentDepend);
123     GateRef ret = GetCircuit()->NewGate(circuit_->EcmaStringCheck(),
124         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
125     currentLabel->SetControl(ret);
126     currentLabel->SetDepend(ret);
127     return ret;
128 }
129 
FlattenTreeStringCheck(GateRef gate)130 GateRef CircuitBuilder::FlattenTreeStringCheck(GateRef gate)
131 {
132     auto currentLabel = env_->GetCurrentLabel();
133     auto currentControl = currentLabel->GetControl();
134     auto currentDepend = currentLabel->GetDepend();
135     auto frameState = acc_.FindNearestFrameState(currentDepend);
136     GateRef ret = GetCircuit()->NewGate(circuit_->FlattenTreeStringCheck(),
137         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
138     currentLabel->SetControl(ret);
139     currentLabel->SetDepend(ret);
140     return ret;
141 }
142 
HClassStableArrayCheck(GateRef gate,GateRef frameState,ArrayMetaDataAccessor accessor)143 GateRef CircuitBuilder::HClassStableArrayCheck(GateRef gate, GateRef frameState, ArrayMetaDataAccessor accessor)
144 {
145     auto currentLabel = env_->GetCurrentLabel();
146     auto currentControl = currentLabel->GetControl();
147     auto currentDepend = currentLabel->GetDepend();
148     GateRef ret = GetCircuit()->NewGate(circuit_->HClassStableArrayCheck(accessor.ToValue()),
149         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
150     currentLabel->SetControl(ret);
151     currentLabel->SetDepend(ret);
152     return ret;
153 }
154 
ArrayGuardianCheck(GateRef frameState)155 GateRef CircuitBuilder::ArrayGuardianCheck(GateRef frameState)
156 {
157     auto currentLabel = env_->GetCurrentLabel();
158     auto currentControl = currentLabel->GetControl();
159     auto currentDepend = currentLabel->GetDepend();
160     GateRef ret = GetCircuit()->NewGate(circuit_->ArrayGuardianCheck(),
161         MachineType::I1, {currentControl, currentDepend, frameState}, GateType::NJSValue());
162     currentLabel->SetControl(ret);
163     currentLabel->SetDepend(ret);
164     return ret;
165 }
166 
TypedArrayCheck(GateRef gate,GateType type,TypedArrayMetaDateAccessor::Mode mode,OnHeapMode onHeap)167 GateRef CircuitBuilder::TypedArrayCheck(GateRef gate, GateType type, TypedArrayMetaDateAccessor::Mode mode,
168                                         OnHeapMode onHeap)
169 {
170     auto currentLabel = env_->GetCurrentLabel();
171     auto currentControl = currentLabel->GetControl();
172     auto currentDepend = currentLabel->GetDepend();
173     auto frameState = acc_.FindNearestFrameState(currentDepend);
174     TypedArrayMetaDateAccessor accessor(type, mode, onHeap);
175     GateRef ret = GetCircuit()->NewGate(circuit_->TypedArrayCheck(accessor.ToValue()), MachineType::I1,
176                                         {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
177     currentLabel->SetControl(ret);
178     currentLabel->SetDepend(ret);
179     return ret;
180 }
181 
LoadTypedArrayLength(GateRef gate,GateType type,OnHeapMode onHeap)182 GateRef CircuitBuilder::LoadTypedArrayLength(GateRef gate, GateType type, OnHeapMode onHeap)
183 {
184     auto currentLabel = env_->GetCurrentLabel();
185     auto currentControl = currentLabel->GetControl();
186     auto currentDepend = currentLabel->GetDepend();
187     TypedArrayMetaDateAccessor accessor(type, TypedArrayMetaDateAccessor::Mode::LOAD_LENGTH, onHeap);
188     GateRef ret = GetCircuit()->NewGate(circuit_->LoadTypedArrayLength(accessor.ToValue()), MachineType::I64,
189                                         {currentControl, currentDepend, gate}, GateType::IntType());
190     currentLabel->SetControl(ret);
191     currentLabel->SetDepend(ret);
192     return ret;
193 }
194 
StringEqual(GateRef x,GateRef y)195 GateRef CircuitBuilder::StringEqual(GateRef x, GateRef y)
196 {
197     auto currentLabel = env_->GetCurrentLabel();
198     auto currentControl = currentLabel->GetControl();
199     auto currentDepend = currentLabel->GetDepend();
200     auto ret = GetCircuit()->NewGate(circuit_->StringEqual(), MachineType::I1,
201                                      { currentControl, currentDepend, x, y }, GateType::BooleanType());
202     currentLabel->SetControl(ret);
203     currentLabel->SetDepend(ret);
204     return ret;
205 }
206 
StringAdd(GateRef x,GateRef y,uint32_t stringStatus)207 GateRef CircuitBuilder::StringAdd(GateRef x, GateRef y, uint32_t stringStatus)
208 {
209     auto currentLabel = env_->GetCurrentLabel();
210     auto currentControl = currentLabel->GetControl();
211     auto currentDepend = currentLabel->GetDepend();
212     StringStatusAccessor accessor(stringStatus);
213     auto ret = GetCircuit()->NewGate(circuit_->StringAdd(accessor.ToValue()), MachineType::I64,
214                                      { currentControl, currentDepend, x, y }, GateType::AnyType());
215     currentLabel->SetControl(ret);
216     currentLabel->SetDepend(ret);
217     return ret;
218 }
219 
RangeGuard(GateRef gate,uint32_t left,uint32_t right)220 GateRef CircuitBuilder::RangeGuard(GateRef gate, uint32_t left, uint32_t right)
221 {
222     auto currentLabel = env_->GetCurrentLabel();
223     auto currentControl = currentLabel->GetControl();
224     auto currentDepend = currentLabel->GetDepend();
225     UInt32PairAccessor accessor(left, right);
226     GateRef ret = GetCircuit()->NewGate(circuit_->RangeGuard(accessor.ToValue()),
227         MachineType::I64, {currentControl, currentDepend, gate}, GateType::IntType());
228     currentLabel->SetControl(ret);
229     currentLabel->SetDepend(ret);
230     return ret;
231 }
232 
BuiltinPrototypeHClassCheck(GateRef gate,BuiltinTypeId type)233 GateRef CircuitBuilder::BuiltinPrototypeHClassCheck(GateRef gate, BuiltinTypeId type)
234 {
235     auto currentLabel = env_->GetCurrentLabel();
236     auto currentControl = currentLabel->GetControl();
237     auto currentDepend = currentLabel->GetDepend();
238     auto frameState = acc_.FindNearestFrameState(currentDepend);
239     BuiltinPrototypeHClassAccessor accessor(type);
240     GateRef ret = GetCircuit()->NewGate(circuit_->BuiltinPrototypeHClassCheck(accessor.ToValue()),
241         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
242     currentLabel->SetControl(ret);
243     currentLabel->SetDepend(ret);
244     return ret;
245 }
246 
IndexCheck(GateRef gate,GateRef index)247 GateRef CircuitBuilder::IndexCheck(GateRef gate, GateRef index)
248 {
249     auto currentLabel = env_->GetCurrentLabel();
250     auto currentControl = currentLabel->GetControl();
251     auto currentDepend = currentLabel->GetDepend();
252     auto frameState = acc_.FindNearestFrameState(currentDepend);
253     GateRef ret = GetCircuit()->NewGate(circuit_->IndexCheck(),
254         MachineType::I64, {currentControl, currentDepend, gate, index, frameState}, GateType::IntType());
255     currentLabel->SetControl(ret);
256     currentLabel->SetDepend(ret);
257     return ret;
258 }
259 
TypeOfCheck(GateRef gate,GateType type)260 GateRef CircuitBuilder::TypeOfCheck(GateRef gate, GateType type)
261 {
262     auto currentLabel = env_->GetCurrentLabel();
263     auto currentControl = currentLabel->GetControl();
264     auto currentDepend = currentLabel->GetDepend();
265     auto frameState = acc_.FindNearestFrameState(currentDepend);
266     GateRef ret = GetCircuit()->NewGate(circuit_->TypeOfCheck(static_cast<size_t>(type.Value())),
267         MachineType::I64, {currentControl, currentDepend, gate, frameState}, GateType::IntType());
268     currentLabel->SetControl(ret);
269     currentLabel->SetDepend(ret);
270     return ret;
271 }
272 
TypedTypeOf(GateType type)273 GateRef CircuitBuilder::TypedTypeOf(GateType type)
274 {
275     auto currentLabel = env_->GetCurrentLabel();
276     auto currentControl = currentLabel->GetControl();
277     auto currentDepend = currentLabel->GetDepend();
278     GateRef ret = GetCircuit()->NewGate(circuit_->TypeOf(static_cast<size_t>(type.Value())),
279         MachineType::I64, {currentControl, currentDepend}, GateType::AnyType());
280     currentLabel->SetControl(ret);
281     currentLabel->SetDepend(ret);
282     return ret;
283 }
284 
IsMarkerCellValid(GateRef cell)285 GateRef CircuitBuilder::IsMarkerCellValid(GateRef cell)
286 {
287     GateRef bitfield = Load(VariableType::INT32(), cell, IntPtr(MarkerCell::BIT_FIELD_OFFSET));
288     return Int32Equal(
289         Int32And(Int32LSR(bitfield, Int32(MarkerCell::IsDetectorInvalidBits::START_BIT)),
290                  Int32((1LU << MarkerCell::IsDetectorInvalidBits::SIZE) - 1)),
291         Int32(0));
292 }
293 
CheckAndConvert(GateRef gate,ValueType src,ValueType dst,ConvertSupport support)294 GateRef CircuitBuilder::CheckAndConvert(GateRef gate, ValueType src, ValueType dst, ConvertSupport support)
295 {
296     auto currentLabel = env_->GetCurrentLabel();
297     auto currentControl = currentLabel->GetControl();
298     auto currentDepend = currentLabel->GetDepend();
299     auto stateSplit = acc_.FindNearestStateSplit(currentDepend);
300     auto frameState = acc_.GetFrameState(stateSplit);
301     MachineType machineType = GetMachineTypeOfValueType(dst);
302     GateType gateType = GetGateTypeOfValueType(dst);
303     uint64_t value = ValuePairTypeAccessor::ToValue(src, dst, support);
304     GateRef ret = GetCircuit()->NewGate(circuit_->CheckAndConvert(value),
305         machineType, {currentControl, currentDepend, gate, frameState}, gateType);
306     currentLabel->SetControl(ret);
307     currentLabel->SetDepend(ret);
308     return ret;
309 }
310 
Convert(GateRef gate,ValueType src,ValueType dst)311 GateRef CircuitBuilder::Convert(GateRef gate, ValueType src, ValueType dst)
312 {
313     MachineType machineType = GetMachineTypeOfValueType(dst);
314     GateType gateType = GetGateTypeOfValueType(dst);
315     uint64_t value = ValuePairTypeAccessor::ToValue(src, dst);
316     GateRef ret = GetCircuit()->NewGate(circuit_->Convert(value), machineType, {gate}, gateType);
317     return ret;
318 }
319 
ConvertBoolToInt32(GateRef gate,ConvertSupport support)320 GateRef CircuitBuilder::ConvertBoolToInt32(GateRef gate, ConvertSupport support)
321 {
322     return CheckAndConvert(gate, ValueType::BOOL, ValueType::INT32, support);
323 }
324 
ConvertBoolToFloat64(GateRef gate,ConvertSupport support)325 GateRef CircuitBuilder::ConvertBoolToFloat64(GateRef gate, ConvertSupport support)
326 {
327     return CheckAndConvert(gate, ValueType::BOOL, ValueType::FLOAT64, support);
328 }
329 
ConvertCharToEcmaString(GateRef gate)330 GateRef CircuitBuilder::ConvertCharToEcmaString(GateRef gate)
331 {
332     return Convert(gate, ValueType::CHAR, ValueType::ECMA_STRING);
333 }
334 
ConvertInt32ToFloat64(GateRef gate)335 GateRef CircuitBuilder::ConvertInt32ToFloat64(GateRef gate)
336 {
337     return Convert(gate, ValueType::INT32, ValueType::FLOAT64);
338 }
339 
ConvertUInt32ToFloat64(GateRef gate)340 GateRef CircuitBuilder::ConvertUInt32ToFloat64(GateRef gate)
341 {
342     return Convert(gate, ValueType::UINT32, ValueType::FLOAT64);
343 }
344 
ConvertFloat64ToInt32(GateRef gate)345 GateRef CircuitBuilder::ConvertFloat64ToInt32(GateRef gate)
346 {
347     return Convert(gate, ValueType::FLOAT64, ValueType::INT32);
348 }
349 
ConvertBoolToTaggedBoolean(GateRef gate)350 GateRef CircuitBuilder::ConvertBoolToTaggedBoolean(GateRef gate)
351 {
352     return Convert(gate, ValueType::BOOL, ValueType::TAGGED_BOOLEAN);
353 }
354 
ConvertTaggedBooleanToBool(GateRef gate)355 GateRef CircuitBuilder::ConvertTaggedBooleanToBool(GateRef gate)
356 {
357     return Convert(gate, ValueType::TAGGED_BOOLEAN, ValueType::BOOL);
358 }
359 
ConvertInt32ToTaggedInt(GateRef gate)360 GateRef CircuitBuilder::ConvertInt32ToTaggedInt(GateRef gate)
361 {
362     return Convert(gate, ValueType::INT32, ValueType::TAGGED_INT);
363 }
364 
ConvertUInt32ToTaggedNumber(GateRef gate)365 GateRef CircuitBuilder::ConvertUInt32ToTaggedNumber(GateRef gate)
366 {
367     return Convert(gate, ValueType::UINT32, ValueType::TAGGED_NUMBER);
368 }
369 
ConvertInt32ToBool(GateRef gate)370 GateRef CircuitBuilder::ConvertInt32ToBool(GateRef gate)
371 {
372     return Convert(gate, ValueType::INT32, ValueType::BOOL);
373 }
374 
ConvertUInt32ToBool(GateRef gate)375 GateRef CircuitBuilder::ConvertUInt32ToBool(GateRef gate)
376 {
377     return Convert(gate, ValueType::UINT32, ValueType::BOOL);
378 }
379 
ConvertFloat64ToBool(GateRef gate)380 GateRef CircuitBuilder::ConvertFloat64ToBool(GateRef gate)
381 {
382     return Convert(gate, ValueType::FLOAT64, ValueType::BOOL);
383 }
384 
CheckTaggedBooleanAndConvertToBool(GateRef gate)385 GateRef CircuitBuilder::CheckTaggedBooleanAndConvertToBool(GateRef gate)
386 {
387     return CheckAndConvert(gate, ValueType::TAGGED_BOOLEAN, ValueType::BOOL);
388 }
389 
CheckTaggedNumberAndConvertToBool(GateRef gate)390 GateRef CircuitBuilder::CheckTaggedNumberAndConvertToBool(GateRef gate)
391 {
392     return CheckAndConvert(gate, ValueType::TAGGED_NUMBER, ValueType::BOOL);
393 }
394 
ConvertFloat64ToTaggedDouble(GateRef gate)395 GateRef CircuitBuilder::ConvertFloat64ToTaggedDouble(GateRef gate)
396 {
397     return Convert(gate, ValueType::FLOAT64, ValueType::TAGGED_DOUBLE);
398 }
399 
CheckUInt32AndConvertToInt32(GateRef gate)400 GateRef CircuitBuilder::CheckUInt32AndConvertToInt32(GateRef gate)
401 {
402     return CheckAndConvert(gate, ValueType::UINT32, ValueType::INT32);
403 }
404 
CheckTaggedIntAndConvertToInt32(GateRef gate)405 GateRef CircuitBuilder::CheckTaggedIntAndConvertToInt32(GateRef gate)
406 {
407     return CheckAndConvert(gate, ValueType::TAGGED_INT, ValueType::INT32);
408 }
409 
CheckTaggedDoubleAndConvertToInt32(GateRef gate)410 GateRef CircuitBuilder::CheckTaggedDoubleAndConvertToInt32(GateRef gate)
411 {
412     return CheckAndConvert(gate, ValueType::TAGGED_DOUBLE, ValueType::INT32);
413 }
414 
CheckTaggedNumberAndConvertToInt32(GateRef gate)415 GateRef CircuitBuilder::CheckTaggedNumberAndConvertToInt32(GateRef gate)
416 {
417     return CheckAndConvert(gate, ValueType::TAGGED_NUMBER, ValueType::INT32);
418 }
419 
CheckTaggedIntAndConvertToFloat64(GateRef gate)420 GateRef CircuitBuilder::CheckTaggedIntAndConvertToFloat64(GateRef gate)
421 {
422     return CheckAndConvert(gate, ValueType::TAGGED_INT, ValueType::FLOAT64);
423 }
424 
CheckTaggedDoubleAndConvertToFloat64(GateRef gate)425 GateRef CircuitBuilder::CheckTaggedDoubleAndConvertToFloat64(GateRef gate)
426 {
427     return CheckAndConvert(gate, ValueType::TAGGED_DOUBLE, ValueType::FLOAT64);
428 }
429 
CheckTaggedNumberAndConvertToFloat64(GateRef gate)430 GateRef CircuitBuilder::CheckTaggedNumberAndConvertToFloat64(GateRef gate)
431 {
432     return CheckAndConvert(gate, ValueType::TAGGED_NUMBER, ValueType::FLOAT64);
433 }
434 
CheckNullAndConvertToInt32(GateRef gate)435 GateRef CircuitBuilder::CheckNullAndConvertToInt32(GateRef gate)
436 {
437     return CheckAndConvert(gate, ValueType::TAGGED_NULL, ValueType::INT32);
438 }
439 
CheckTaggedBooleanAndConvertToInt32(GateRef gate)440 GateRef CircuitBuilder::CheckTaggedBooleanAndConvertToInt32(GateRef gate)
441 {
442     return CheckAndConvert(gate, ValueType::TAGGED_BOOLEAN, ValueType::INT32);
443 }
444 
CheckNullAndConvertToFloat64(GateRef gate)445 GateRef CircuitBuilder::CheckNullAndConvertToFloat64(GateRef gate)
446 {
447     return CheckAndConvert(gate, ValueType::TAGGED_NULL, ValueType::FLOAT64);
448 }
449 
CheckTaggedBooleanAndConvertToFloat64(GateRef gate)450 GateRef CircuitBuilder::CheckTaggedBooleanAndConvertToFloat64(GateRef gate)
451 {
452     return CheckAndConvert(gate, ValueType::TAGGED_BOOLEAN, ValueType::FLOAT64);
453 }
454 
CheckUndefinedAndConvertToFloat64(GateRef gate)455 GateRef CircuitBuilder::CheckUndefinedAndConvertToFloat64(GateRef gate)
456 {
457     return CheckAndConvert(gate, ValueType::UNDEFINED, ValueType::FLOAT64);
458 }
459 
CheckUndefinedAndConvertToBool(GateRef gate)460 GateRef CircuitBuilder::CheckUndefinedAndConvertToBool(GateRef gate)
461 {
462     return CheckAndConvert(gate, ValueType::UNDEFINED, ValueType::BOOL);
463 }
464 
CheckNullAndConvertToBool(GateRef gate)465 GateRef CircuitBuilder::CheckNullAndConvertToBool(GateRef gate)
466 {
467     return CheckAndConvert(gate, ValueType::TAGGED_NULL, ValueType::BOOL);
468 }
469 
CheckUndefinedAndConvertToInt32(GateRef gate)470 GateRef CircuitBuilder::CheckUndefinedAndConvertToInt32(GateRef gate)
471 {
472     return CheckAndConvert(gate, ValueType::UNDEFINED, ValueType::INT32);
473 }
474 
TryPrimitiveTypeCheck(GateType type,GateRef gate)475 GateRef CircuitBuilder::TryPrimitiveTypeCheck(GateType type, GateRef gate)
476 {
477     if (acc_.GetOpCode(gate) == OpCode::CONSTANT) {
478         return Circuit::NullGate();
479     }
480     auto currentLabel = env_->GetCurrentLabel();
481     auto currentControl = currentLabel->GetControl();
482     auto currentDepend = currentLabel->GetDepend();
483     auto frameState = acc_.FindNearestFrameState(currentDepend);
484     GateRef ret = GetCircuit()->NewGate(circuit_->PrimitiveTypeCheck(static_cast<size_t>(type.Value())),
485         MachineType::I1, {currentControl, currentDepend, gate, frameState}, GateType::NJSValue());
486     currentLabel->SetControl(ret);
487     currentLabel->SetDepend(ret);
488     return ret;
489 }
490 
CallTargetCheck(GateRef gate,GateRef function,GateRef id,GateRef param,const char * comment)491 GateRef CircuitBuilder::CallTargetCheck(GateRef gate, GateRef function, GateRef id, GateRef param, const char* comment)
492 {
493     auto currentLabel = env_->GetCurrentLabel();
494     auto currentControl = currentLabel->GetControl();
495     auto currentDepend = currentLabel->GetDepend();
496     GateRef frameState;
497     if (Bytecodes::IsCallOp(acc_.GetByteCodeOpcode(gate))) {
498         frameState = acc_.GetFrameState(gate);
499     } else {
500         frameState = acc_.FindNearestFrameState(currentDepend);
501     }
502     GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallCheck(),
503                                         MachineType::I1,
504                                         { currentControl, currentDepend, function, id, param, frameState},
505                                         GateType::NJSValue(),
506                                         comment);
507     currentLabel->SetControl(ret);
508     currentLabel->SetDepend(ret);
509     return ret;
510 }
511 
JSCallTargetFromDefineFuncCheck(GateType type,GateRef func,GateRef gate)512 GateRef CircuitBuilder::JSCallTargetFromDefineFuncCheck(GateType type, GateRef func, GateRef gate)
513 {
514     auto currentLabel = env_->GetCurrentLabel();
515     auto currentControl = currentLabel->GetControl();
516     auto currentDepend = currentLabel->GetDepend();
517     auto frameState = acc_.GetFrameState(gate);
518     GateRef ret = GetCircuit()->NewGate(circuit_->TypedCallTargetCheckOp(1, static_cast<size_t>(type.Value()),
519         TypedCallTargetCheckOp::JSCALL_IMMEDIATE_AFTER_FUNC_DEF),
520         MachineType::I1, {currentControl, currentDepend, func, frameState}, GateType::NJSValue());
521     currentLabel->SetControl(ret);
522     currentLabel->SetDepend(ret);
523     return ret;
524 }
TypedCallOperator(GateRef hirGate,MachineType type,const std::vector<GateRef> & inList)525 GateRef CircuitBuilder::TypedCallOperator(GateRef hirGate, MachineType type, const std::vector<GateRef> &inList)
526 {
527     ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
528     auto numValueIn = inList.size() - 3; // 3: state & depend & frame state
529     uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
530     ASSERT(pcOffset != 0);
531     return GetCircuit()->NewGate(circuit_->TypedCallBuiltin(numValueIn, pcOffset), type, inList.size(), inList.data(),
532                                  GateType::AnyType());
533 }
534 
535 
TypedNewAllocateThis(GateRef ctor,GateRef hclassIndex,GateRef frameState)536 GateRef CircuitBuilder::TypedNewAllocateThis(GateRef ctor, GateRef hclassIndex, GateRef frameState)
537 {
538     auto currentLabel = env_->GetCurrentLabel();
539     auto currentControl = currentLabel->GetControl();
540     auto currentDepend = currentLabel->GetDepend();
541     GateRef ret = GetCircuit()->NewGate(circuit_->TypedNewAllocateThis(),
542         MachineType::ANYVALUE, {currentControl, currentDepend, ctor, hclassIndex, frameState}, GateType::TaggedValue());
543     currentLabel->SetControl(ret);
544     currentLabel->SetDepend(ret);
545     return ret;
546 }
547 
TypedSuperAllocateThis(GateRef superCtor,GateRef newTarget,GateRef frameState)548 GateRef CircuitBuilder::TypedSuperAllocateThis(GateRef superCtor, GateRef newTarget, GateRef frameState)
549 {
550     auto currentLabel = env_->GetCurrentLabel();
551     auto currentControl = currentLabel->GetControl();
552     auto currentDepend = currentLabel->GetDepend();
553     GateRef ret = GetCircuit()->NewGate(circuit_->TypedSuperAllocateThis(), MachineType::ANYVALUE,
554         {currentControl, currentDepend, superCtor, newTarget, frameState}, GateType::TaggedValue());
555     currentLabel->SetControl(ret);
556     currentLabel->SetDepend(ret);
557     return ret;
558 }
559 
560 
Int32CheckRightIsZero(GateRef right)561 GateRef CircuitBuilder::Int32CheckRightIsZero(GateRef right)
562 {
563     auto currentLabel = env_->GetCurrentLabel();
564     auto currentControl = currentLabel->GetControl();
565     auto currentDepend = currentLabel->GetDepend();
566     auto frameState = acc_.FindNearestFrameState(currentDepend);
567     GateRef ret = GetCircuit()->NewGate(circuit_->Int32CheckRightIsZero(),
568     MachineType::I1, {currentControl, currentDepend, right, frameState}, GateType::NJSValue());
569     currentLabel->SetControl(ret);
570     currentLabel->SetDepend(ret);
571     return ret;
572 }
573 
RemainderIsNegativeZero(GateRef left,GateRef right)574 GateRef CircuitBuilder::RemainderIsNegativeZero(GateRef left, GateRef right)
575 {
576     auto currentLabel = env_->GetCurrentLabel();
577     auto currentControl = currentLabel->GetControl();
578     auto currentDepend = currentLabel->GetDepend();
579     auto frameState = acc_.FindNearestFrameState(currentDepend);
580     GateRef ret = GetCircuit()->NewGate(circuit_->RemainderIsNegativeZero(),
581                                         MachineType::I1,
582                                         {currentControl, currentDepend, left, right, frameState},
583                                         GateType::NJSValue());
584     currentLabel->SetControl(ret);
585     currentLabel->SetDepend(ret);
586     return ret;
587 }
588 
Float64CheckRightIsZero(GateRef right)589 GateRef CircuitBuilder::Float64CheckRightIsZero(GateRef right)
590 {
591     auto currentLabel = env_->GetCurrentLabel();
592     auto currentControl = currentLabel->GetControl();
593     auto currentDepend = currentLabel->GetDepend();
594     auto frameState = acc_.FindNearestFrameState(currentDepend);
595     GateRef ret = GetCircuit()->NewGate(circuit_->Float64CheckRightIsZero(),
596     MachineType::I1, {currentControl, currentDepend, right, frameState}, GateType::NJSValue());
597     currentLabel->SetControl(ret);
598     currentLabel->SetDepend(ret);
599     return ret;
600 }
601 
LexVarIsHoleCheck(GateRef value)602 GateRef CircuitBuilder::LexVarIsHoleCheck(GateRef value)
603 {
604     auto currentLabel = env_->GetCurrentLabel();
605     auto currentControl = currentLabel->GetControl();
606     auto currentDepend = currentLabel->GetDepend();
607     auto frameState = acc_.FindNearestFrameState(currentDepend);
608     GateRef ret = GetCircuit()->NewGate(circuit_->LexVarIsHoleCheck(),
609     MachineType::I1, {currentControl, currentDepend, value, frameState}, GateType::NJSValue());
610     currentLabel->SetControl(ret);
611     currentLabel->SetDepend(ret);
612     return ret;
613 }
614 
ValueCheckNegOverflow(GateRef value)615 GateRef CircuitBuilder::ValueCheckNegOverflow(GateRef value)
616 {
617     auto currentLabel = env_->GetCurrentLabel();
618     auto currentControl = currentLabel->GetControl();
619     auto currentDepend = currentLabel->GetDepend();
620     auto frameState = acc_.FindNearestFrameState(currentDepend);
621     GateRef ret = GetCircuit()->NewGate(circuit_->ValueCheckNegOverflow(),
622     MachineType::I1, {currentControl, currentDepend, value, frameState}, GateType::NJSValue());
623     currentLabel->SetControl(ret);
624     currentLabel->SetDepend(ret);
625     return ret;
626 }
627 
OverflowCheck(GateRef value)628 GateRef CircuitBuilder::OverflowCheck(GateRef value)
629 {
630     auto currentLabel = env_->GetCurrentLabel();
631     auto currentControl = currentLabel->GetControl();
632     auto currentDepend = currentLabel->GetDepend();
633     auto frameState = acc_.FindNearestFrameState(currentDepend);
634     GateRef ret = GetCircuit()->NewGate(circuit_->OverflowCheck(),
635         MachineType::I1, {currentControl, currentDepend, value, frameState}, GateType::IntType());
636     currentLabel->SetControl(ret);
637     currentLabel->SetDepend(ret);
638     return ret;
639 }
640 
Int32UnsignedUpperBoundCheck(GateRef value,GateRef upperBound)641 GateRef CircuitBuilder::Int32UnsignedUpperBoundCheck(GateRef value, GateRef upperBound)
642 {
643     auto currentLabel = env_->GetCurrentLabel();
644     auto currentControl = currentLabel->GetControl();
645     auto currentDepend = currentLabel->GetDepend();
646     auto frameState = acc_.FindNearestFrameState(currentDepend);
647     GateRef ret = GetCircuit()->NewGate(circuit_->Int32UnsignedUpperBoundCheck(),
648         MachineType::I1, {currentControl, currentDepend, value, upperBound, frameState}, GateType::IntType());
649     currentLabel->SetControl(ret);
650     currentLabel->SetDepend(ret);
651     return ret;
652 }
653 
Int32DivWithCheck(GateRef left,GateRef right)654 GateRef CircuitBuilder::Int32DivWithCheck(GateRef left, GateRef right)
655 {
656     auto currentLabel = env_->GetCurrentLabel();
657     auto currentControl = currentLabel->GetControl();
658     auto currentDepend = currentLabel->GetDepend();
659     auto frameState = acc_.FindNearestFrameState(currentDepend);
660     GateRef ret = GetCircuit()->NewGate(circuit_->Int32DivWithCheck(),
661         MachineType::I32, {currentControl, currentDepend, left, right, frameState}, GateType::NJSValue());
662     currentLabel->SetControl(ret);
663     currentLabel->SetDepend(ret);
664     return ret;
665 }
666 
TypedConditionJump(MachineType type,TypedJumpOp jumpOp,uint32_t weight,GateType typeVal,const std::vector<GateRef> & inList)667 GateRef CircuitBuilder::TypedConditionJump(MachineType type, TypedJumpOp jumpOp, uint32_t weight,
668     GateType typeVal, const std::vector<GateRef>& inList)
669 {
670     uint64_t value = TypedJumpAccessor::ToValue(typeVal, jumpOp, weight);
671     return GetCircuit()->NewGate(circuit_->TypedConditionJump(value),
672         type, inList.size(), inList.data(), GateType::Empty());
673 }
674 
TypeConvert(MachineType type,GateType typeFrom,GateType typeTo,const std::vector<GateRef> & inList)675 GateRef CircuitBuilder::TypeConvert(MachineType type, GateType typeFrom, GateType typeTo,
676                                     const std::vector<GateRef>& inList)
677 {
678     // merge types of valueIns before and after convertion
679     uint64_t operandTypes = GatePairTypeAccessor::ToValue(typeFrom, typeTo);
680     return GetCircuit()->NewGate(circuit_->TypedConvert(operandTypes),
681         type, inList.size(), inList.data(), GateType::AnyType());
682 }
683 
StoreMemory(MemoryType Op,VariableType type,GateRef receiver,GateRef index,GateRef value)684 GateRef CircuitBuilder::StoreMemory(MemoryType Op, VariableType type, GateRef receiver, GateRef index, GateRef value)
685 {
686     auto opIdx = static_cast<uint64_t>(Op);
687     auto currentLabel = env_->GetCurrentLabel();
688     auto currentControl = currentLabel->GetControl();
689     auto currentDepend = currentLabel->GetDepend();
690     auto ret = GetCircuit()->NewGate(GetCircuit()->StoreMemory(opIdx), type.GetMachineType(),
691         {currentControl, currentDepend, receiver, index, value}, type.GetGateType());
692     currentLabel->SetControl(ret);
693     currentLabel->SetDepend(ret);
694     return ret;
695 }
696 
LoadProperty(GateRef receiver,GateRef propertyLookupResult,bool isFunction)697 GateRef CircuitBuilder::LoadProperty(GateRef receiver, GateRef propertyLookupResult, bool isFunction)
698 {
699     auto currentLabel = env_->GetCurrentLabel();
700     auto currentControl = currentLabel->GetControl();
701     auto currentDepend = currentLabel->GetDepend();
702     auto ret = GetCircuit()->NewGate(circuit_->LoadProperty(isFunction), MachineType::I64,
703                                      { currentControl, currentDepend, receiver, propertyLookupResult },
704                                      GateType::AnyType());
705     currentLabel->SetControl(ret);
706     currentLabel->SetDepend(ret);
707     return ret;
708 }
709 
StoreProperty(GateRef receiver,GateRef propertyLookupResult,GateRef value,uint32_t receiverHClassIndex)710 GateRef CircuitBuilder::StoreProperty(GateRef receiver, GateRef propertyLookupResult, GateRef value,
711                                       uint32_t receiverHClassIndex)
712 {
713     auto currentLabel = env_->GetCurrentLabel();
714     auto currentControl = currentLabel->GetControl();
715     auto currentDepend = currentLabel->GetDepend();
716     auto ret = GetCircuit()->NewGate(circuit_->StoreProperty(receiverHClassIndex), MachineType::I64,
717                                      { currentControl, currentDepend, receiver, propertyLookupResult, value },
718                                      GateType::AnyType());
719     currentLabel->SetControl(ret);
720     currentLabel->SetDepend(ret);
721     return ret;
722 }
723 
LoadArrayLength(GateRef array)724 GateRef CircuitBuilder::LoadArrayLength(GateRef array)
725 {
726     auto currentLabel = env_->GetCurrentLabel();
727     auto currentControl = currentLabel->GetControl();
728     auto currentDepend = currentLabel->GetDepend();
729     auto ret = GetCircuit()->NewGate(circuit_->LoadArrayLength(), MachineType::I64,
730                                      { currentControl, currentDepend, array }, GateType::IntType());
731     currentLabel->SetControl(ret);
732     currentLabel->SetDepend(ret);
733     return ret;
734 }
735 
LoadStringLength(GateRef string)736 GateRef CircuitBuilder::LoadStringLength(GateRef string)
737 {
738     auto currentLabel = env_->GetCurrentLabel();
739     auto currentControl = currentLabel->GetControl();
740     auto currentDepend = currentLabel->GetDepend();
741     auto ret = GetCircuit()->NewGate(circuit_->LoadStringLength(), MachineType::I64,
742                                      { currentControl, currentDepend, string }, GateType::IntType());
743     currentLabel->SetControl(ret);
744     currentLabel->SetDepend(ret);
745     return ret;
746 }
747 
LoadConstOffset(VariableType type,GateRef receiver,size_t offset,MemoryOrder order)748 GateRef CircuitBuilder::LoadConstOffset(VariableType type, GateRef receiver, size_t offset, MemoryOrder order)
749 {
750     auto currentLabel = env_->GetCurrentLabel();
751     auto currentDepend = currentLabel->GetDepend();
752     auto bits = LoadStoreConstOffsetAccessor::ToValue(offset, order);
753     auto ret = GetCircuit()->NewGate(circuit_->LoadConstOffset(bits), type.GetMachineType(),
754                                      { currentDepend, receiver }, type.GetGateType());
755     currentLabel->SetDepend(ret);
756     return ret;
757 }
758 
LoadHClassFromConstpool(GateRef constpool,size_t index)759 GateRef CircuitBuilder::LoadHClassFromConstpool(GateRef constpool, size_t index)
760 {
761     auto currentLabel = env_->GetCurrentLabel();
762     auto currentDepend = currentLabel->GetDepend();
763     auto ret = GetCircuit()->NewGate(circuit_->LoadHClassFromConstpool(index), MachineType::I64,
764                                      { currentDepend, constpool }, GateType::AnyType());
765     currentLabel->SetDepend(ret);
766     return ret;
767 }
768 
StoreConstOffset(VariableType type,GateRef receiver,size_t offset,GateRef value,MemoryOrder order)769 GateRef CircuitBuilder::StoreConstOffset(VariableType type,
770     GateRef receiver, size_t offset, GateRef value, MemoryOrder order)
771 {
772     auto currentLabel = env_->GetCurrentLabel();
773     auto currentControl = currentLabel->GetControl();
774     auto currentDepend = currentLabel->GetDepend();
775     auto bits = LoadStoreConstOffsetAccessor::ToValue(offset, order);
776     auto ret = GetCircuit()->NewGate(circuit_->StoreConstOffset(bits), type.GetMachineType(),
777         { currentControl, currentDepend, receiver, value }, type.GetGateType());
778     currentLabel->SetControl(ret);
779     currentLabel->SetDepend(ret);
780     return ret;
781 }
782 
TaggedIsHeapObjectOp(GateRef value)783 GateRef CircuitBuilder::TaggedIsHeapObjectOp(GateRef value)
784 {
785     auto currentLabel = env_->GetCurrentLabel();
786     auto currentControl = currentLabel->GetControl();
787     auto currentDepend = currentLabel->GetDepend();
788     auto newGate = GetCircuit()->NewGate(circuit_->TaggedIsHeapObject(), MachineType::I1,
789                                          { currentControl, currentDepend, value },
790                                          GateType::NJSValue());
791     currentLabel->SetDepend(newGate);
792     return newGate;
793 }
794 
IsSpecificObjectType(GateRef obj,JSType type)795 GateRef CircuitBuilder::IsSpecificObjectType(GateRef obj, JSType type)
796 {
797     auto currentLabel = env_->GetCurrentLabel();
798     auto currentControl = currentLabel->GetControl();
799     auto currentDepend = currentLabel->GetDepend();
800     auto newGate = GetCircuit()->NewGate(circuit_->IsSpecificObjectType(static_cast<int32_t>(type)), MachineType::I1,
801                                          { currentControl, currentDepend, obj },
802                                          GateType::NJSValue());
803     currentLabel->SetDepend(newGate);
804     return newGate;
805 }
806 
IsMarkerCellValidOp(GateRef cell)807 GateRef CircuitBuilder::IsMarkerCellValidOp(GateRef cell)
808 {
809     auto currentLabel = env_->GetCurrentLabel();
810     auto currentControl = currentLabel->GetControl();
811     auto currentDepend = currentLabel->GetDepend();
812     auto newGate = GetCircuit()->NewGate(circuit_->IsMarkerCellValid(), MachineType::I1,
813                                          { currentControl, currentDepend, cell },
814                                          GateType::NJSValue());
815     currentLabel->SetDepend(newGate);
816     return newGate;
817 }
818 
ConvertHoleAsUndefined(GateRef receiver)819 GateRef CircuitBuilder::ConvertHoleAsUndefined(GateRef receiver)
820 {
821     auto currentLabel = env_->GetCurrentLabel();
822     auto currentControl = currentLabel->GetControl();
823     auto currentDepend = currentLabel->GetDepend();
824 
825     auto ret = GetCircuit()->NewGate(circuit_->ConvertHoleAsUndefined(),
826         MachineType::I64, { currentControl, currentDepend, receiver }, GateType::AnyType());
827     currentLabel->SetControl(ret);
828     currentLabel->SetDepend(ret);
829     return ret;
830 }
831 
TypedCall(GateRef hirGate,std::vector<GateRef> args,bool isNoGC)832 GateRef CircuitBuilder::TypedCall(GateRef hirGate, std::vector<GateRef> args, bool isNoGC)
833 {
834     ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
835     auto currentLabel = env_->GetCurrentLabel();
836     auto currentControl = currentLabel->GetControl();
837     auto currentDepend = currentLabel->GetDepend();
838     uint64_t bitfield = args.size();
839     uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
840     ASSERT(pcOffset != 0);
841     args.insert(args.begin(), currentDepend);
842     args.insert(args.begin(), currentControl);
843     AppendFrameArgs(args, hirGate);
844     auto callGate = GetCircuit()->NewGate(circuit_->TypedCall(bitfield, pcOffset, isNoGC), MachineType::I64,
845                                           args.size(), args.data(), GateType::AnyType());
846     currentLabel->SetControl(callGate);
847     currentLabel->SetDepend(callGate);
848     return callGate;
849 }
850 
TypedFastCall(GateRef hirGate,std::vector<GateRef> args,bool isNoGC)851 GateRef CircuitBuilder::TypedFastCall(GateRef hirGate, std::vector<GateRef> args, bool isNoGC)
852 {
853     ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
854     auto currentLabel = env_->GetCurrentLabel();
855     auto currentControl = currentLabel->GetControl();
856     auto currentDepend = currentLabel->GetDepend();
857     uint64_t bitfield = args.size();
858     uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
859     ASSERT(pcOffset != 0);
860     args.insert(args.begin(), currentDepend);
861     args.insert(args.begin(), currentControl);
862     AppendFrameArgs(args, hirGate);
863     auto callGate = GetCircuit()->NewGate(circuit_->TypedFastCall(bitfield, pcOffset, isNoGC), MachineType::I64,
864                                           args.size(), args.data(), GateType::AnyType());
865     currentLabel->SetControl(callGate);
866     currentLabel->SetDepend(callGate);
867     return callGate;
868 }
869 
StartAllocate()870 GateRef CircuitBuilder::StartAllocate()
871 {
872     auto currentLabel = env_->GetCurrentLabel();
873     auto currentDepend = currentLabel->GetDepend();
874     GateRef newGate = GetCircuit()->NewGate(circuit_->StartAllocate(),  MachineType::I64,
875                                             { currentDepend }, GateType::NJSValue());
876     currentLabel->SetDepend(newGate);
877     return newGate;
878 }
879 
FinishAllocate(GateRef value)880 GateRef CircuitBuilder::FinishAllocate(GateRef value)
881 {
882     auto currentLabel = env_->GetCurrentLabel();
883     auto currentDepend = currentLabel->GetDepend();
884     GateRef newGate = GetCircuit()->NewGate(circuit_->FinishAllocate(),  MachineType::I64,
885                                             { currentDepend, value }, acc_.GetGateType(value));
886     currentLabel->SetDepend(newGate);
887     return newGate;
888 }
889 
HeapAlloc(GateRef size,GateType type,RegionSpaceFlag flag)890 GateRef CircuitBuilder::HeapAlloc(GateRef size, GateType type, RegionSpaceFlag flag)
891 {
892     auto currentLabel = env_->GetCurrentLabel();
893     auto currentControl = currentLabel->GetControl();
894     auto currentDepend = currentLabel->GetDepend();
895     auto ret = GetCircuit()->NewGate(circuit_->HeapAlloc(flag), MachineType::I64,
896                                      { currentControl, currentDepend, size }, type);
897     currentLabel->SetControl(ret);
898     currentLabel->SetDepend(ret);
899     return ret;
900 }
901 
GetGateTypeOfValueType(ValueType type)902 GateType CircuitBuilder::GetGateTypeOfValueType(ValueType type)
903 {
904     switch (type) {
905         case ValueType::BOOL:
906         case ValueType::INT32:
907         case ValueType::FLOAT64:
908             return GateType::NJSValue();
909         case ValueType::TAGGED_BOOLEAN:
910             return GateType::BooleanType();
911         case ValueType::TAGGED_INT:
912             return GateType::IntType();
913         case ValueType::TAGGED_DOUBLE:
914             return GateType::DoubleType();
915         case ValueType::TAGGED_NUMBER:
916             return GateType::NumberType();
917         default:
918             return GateType::Empty();
919     }
920 }
921 
InsertTypedBinaryop(GateRef left,GateRef right,GateType leftType,GateType rightType,GateType gateType,PGOTypeRef pgoType,TypedBinOp op)922 GateRef CircuitBuilder::InsertTypedBinaryop(GateRef left, GateRef right, GateType leftType, GateType rightType,
923                                             GateType gateType, PGOTypeRef pgoType, TypedBinOp op)
924 {
925     auto currentLabel = env_->GetCurrentLabel();
926     auto currentControl = currentLabel->GetControl();
927     auto currentDepend = currentLabel->GetDepend();
928     uint64_t operandTypes = GatePairTypeAccessor::ToValue(leftType, rightType);
929     auto ret = GetCircuit()->NewGate(circuit_->TypedBinaryOp(operandTypes, op, pgoType),
930                                      MachineType::I64,
931                                      {currentControl, currentDepend, left, right},
932                                      gateType);
933     acc_.ReplaceInAfterInsert(currentControl, currentDepend, ret);
934     currentLabel->SetControl(ret);
935     currentLabel->SetDepend(ret);
936     return ret;
937 }
938 
InsertRangeCheckPredicate(GateRef left,TypedBinOp cond,GateRef right)939 GateRef CircuitBuilder::InsertRangeCheckPredicate(GateRef left, TypedBinOp cond, GateRef right)
940 {
941     auto currentLabel = env_->GetCurrentLabel();
942     auto currentControl = currentLabel->GetControl();
943     auto currentDepend = currentLabel->GetDepend();
944     auto frameState = acc_.FindNearestFrameState(currentDepend);
945     TypedBinaryAccessor accessor(GateType::IntType(), cond);
946     auto ret = GetCircuit()->NewGate(circuit_->RangeCheckPredicate(accessor.ToValue()),
947                                      MachineType::I32,
948                                      {currentControl, currentDepend, left, right, frameState},
949                                      GateType::IntType());
950     acc_.ReplaceInAfterInsert(currentControl, currentDepend, ret);
951     currentLabel->SetControl(ret);
952     currentLabel->SetDepend(ret);
953     return ret;
954 }
955 
InsertStableArrayCheck(GateRef array)956 GateRef CircuitBuilder::InsertStableArrayCheck(GateRef array)
957 {
958     auto currentLabel = env_->GetCurrentLabel();
959     auto currentControl = currentLabel->GetControl();
960     auto currentDepend = currentLabel->GetDepend();
961     GateRef frameState = acc_.FindNearestFrameState(currentDepend);
962     ElementsKind kind = acc_.TryGetElementsKind(array);
963     ArrayMetaDataAccessor::Mode mode = ArrayMetaDataAccessor::Mode::LOAD_LENGTH;
964     ArrayMetaDataAccessor accessor(kind, mode);
965     auto ret = GetCircuit()->NewGate(circuit_->StableArrayCheck(accessor.ToValue()),
966                                      MachineType::I1,
967                                      {currentControl, currentDepend, array, frameState},
968                                      GateType::NJSValue());
969     acc_.ReplaceInAfterInsert(currentControl, currentDepend, ret);
970     currentLabel->SetControl(ret);
971     currentLabel->SetDepend(ret);
972     return ret;
973 }
974 
InsertTypedArrayCheck(GateType type,GateRef array)975 GateRef CircuitBuilder::InsertTypedArrayCheck(GateType type, GateRef array)
976 {
977     auto currentLabel = env_->GetCurrentLabel();
978     auto currentControl = currentLabel->GetControl();
979     auto currentDepend = currentLabel->GetDepend();
980     GateRef frameState = acc_.FindNearestFrameState(currentDepend);
981     auto ret = GetCircuit()->NewGate(circuit_->TypedArrayCheck(static_cast<size_t>(type.Value())),
982                                      MachineType::I1,
983                                      {currentControl, currentDepend, array, frameState},
984                                      GateType::NJSValue());
985     acc_.ReplaceInAfterInsert(currentControl, currentDepend, ret);
986     currentLabel->SetControl(ret);
987     currentLabel->SetDepend(ret);
988     return ret;
989 }
990 
InsertLoadArrayLength(GateRef array,bool isTypedArray)991 GateRef CircuitBuilder::InsertLoadArrayLength(GateRef array, bool isTypedArray)
992 {
993     auto currentLabel = env_->GetCurrentLabel();
994     auto currentControl = currentLabel->GetControl();
995     auto currentDepend = currentLabel->GetDepend();
996     GateType arrayType = acc_.GetGateType(array);
997     if (isTypedArray) {
998         InsertTypedArrayCheck(arrayType, array);
999         currentControl = currentLabel->GetControl();
1000         currentDepend = currentLabel->GetDepend();
1001         auto ret = GetCircuit()->NewGate(circuit_->LoadTypedArrayLength(static_cast<size_t>(arrayType.Value())),
1002                                          MachineType::I64,
1003                                          { currentControl, currentDepend, array },
1004                                          GateType::IntType());
1005         acc_.ReplaceInAfterInsert(currentControl, currentDepend, ret);
1006         currentLabel->SetControl(ret);
1007         currentLabel->SetDepend(ret);
1008         return ret;
1009     } else {
1010         InsertStableArrayCheck(array);
1011         currentControl = currentLabel->GetControl();
1012         currentDepend = currentLabel->GetDepend();
1013         auto ret = GetCircuit()->NewGate(circuit_->LoadArrayLength(),
1014                                          MachineType::I64,
1015                                          { currentControl, currentDepend, array },
1016                                          GateType::IntType());
1017         acc_.ReplaceInAfterInsert(currentControl, currentDepend, ret);
1018         currentLabel->SetControl(ret);
1019         currentLabel->SetDepend(ret);
1020         return ret;
1021     }
1022     UNREACHABLE();
1023     return Circuit::NullGate();
1024 }
1025 
IsIntegerString(GateRef string)1026 GateRef CircuitBuilder::IsIntegerString(GateRef string)
1027 {
1028     // compressedStringsEnabled fixed to true constant
1029     GateRef hash = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_HASHCODE_OFFSET));
1030     return Int32Equal(
1031         Int32And(hash, Int32(EcmaString::IS_INTEGER_MASK)),
1032         Int32(EcmaString::IS_INTEGER_MASK));
1033 }
1034 
GetRawHashFromString(GateRef value)1035 GateRef CircuitBuilder::GetRawHashFromString(GateRef value)
1036 {
1037     GateRef hash = Load(VariableType::INT32(), value, IntPtr(EcmaString::MIX_HASHCODE_OFFSET));
1038     return Int32And(hash, Int32(~EcmaString::IS_INTEGER_MASK));
1039 }
1040 
SetRawHashcode(GateRef glue,GateRef str,GateRef rawHashcode,GateRef isInteger)1041 void CircuitBuilder::SetRawHashcode(GateRef glue, GateRef str, GateRef rawHashcode, GateRef isInteger)
1042 {
1043     Label subentry(env_);
1044     SubCfgEntry(&subentry);
1045     Label integer(env_);
1046     Label notInteger(env_);
1047     Label exit(env_);
1048 
1049     DEFVALUE(hash, env_, VariableType::INT32(), Int32(0));
1050     Branch(isInteger, &integer, &notInteger);
1051     Bind(&integer);
1052     {
1053         hash = Int32Or(rawHashcode, Int32(EcmaString::IS_INTEGER_MASK));
1054         Jump(&exit);
1055     }
1056     Bind(&notInteger);
1057     {
1058         hash = Int32And(rawHashcode, Int32(~EcmaString::IS_INTEGER_MASK));
1059         Jump(&exit);
1060     }
1061     Bind(&exit);
1062     Store(VariableType::INT32(), glue, str, IntPtr(EcmaString::MIX_HASHCODE_OFFSET), *hash);
1063     SubCfgExit();
1064     return;
1065 }
1066 
GetLengthFromString(GateRef value)1067 GateRef CircuitBuilder::GetLengthFromString(GateRef value)
1068 {
1069     GateRef len = Load(VariableType::INT32(), value, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
1070     return Int32LSR(len, Int32(EcmaString::STRING_LENGTH_SHIFT_COUNT));
1071 }
1072 
GetHashcodeFromString(GateRef glue,GateRef value)1073 GateRef CircuitBuilder::GetHashcodeFromString(GateRef glue, GateRef value)
1074 {
1075     ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame());
1076     Label subentry(env_);
1077     SubCfgEntry(&subentry);
1078     Label noRawHashcode(env_);
1079     Label exit(env_);
1080     DEFVALUE(hashcode, env_, VariableType::INT32(), Int32(0));
1081     hashcode = Load(VariableType::INT32(), value, IntPtr(EcmaString::MIX_HASHCODE_OFFSET));
1082     Branch(Int32Equal(*hashcode, Int32(0)), &noRawHashcode, &exit);
1083     Bind(&noRawHashcode);
1084     {
1085         hashcode = GetInt32OfTInt(
1086             CallRuntime(glue, RTSTUB_ID(ComputeHashcode), Gate::InvalidGateRef, { value }, Circuit::NullGate()));
1087         Store(VariableType::INT32(), glue, value, IntPtr(EcmaString::MIX_HASHCODE_OFFSET), *hashcode);
1088         Jump(&exit);
1089     }
1090     Bind(&exit);
1091     auto ret = *hashcode;
1092     SubCfgExit();
1093     return ret;
1094 }
1095 
TryGetHashcodeFromString(GateRef string)1096 GateRef CircuitBuilder::TryGetHashcodeFromString(GateRef string)
1097 {
1098     Label subentry(env_);
1099     SubCfgEntry(&subentry);
1100     Label noRawHashcode(env_);
1101     Label storeHash(env_);
1102     Label exit(env_);
1103     DEFVALUE(result, env_, VariableType::INT64(), Int64(-1));
1104     GateRef hashCode = ZExtInt32ToInt64(Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_HASHCODE_OFFSET)));
1105     Branch(Int64Equal(hashCode, Int64(0)), &noRawHashcode, &storeHash);
1106     Bind(&noRawHashcode);
1107     {
1108         GateRef length = GetLengthFromString(string);
1109         Label lengthNotZero(env_);
1110         Branch(Int32Equal(length, Int32(0)), &storeHash, &exit);
1111     }
1112     Bind(&storeHash);
1113     result = hashCode;
1114     Jump(&exit);
1115     Bind(&exit);
1116     auto ret = *result;
1117     SubCfgExit();
1118     return ret;
1119 }
1120 
GetStringDataFromLineOrConstantString(GateRef str)1121 GateRef CircuitBuilder::GetStringDataFromLineOrConstantString(GateRef str)
1122 {
1123     Label subentry(env_);
1124     SubCfgEntry(&subentry);
1125     Label exit(env_);
1126     Label isConstantString(env_);
1127     Label isLineString(env_);
1128     DEFVALUE(result, env_, VariableType::NATIVE_POINTER(), IntPtr(0));
1129     Branch(IsConstantString(str), &isConstantString, &isLineString);
1130     Bind(&isConstantString);
1131     {
1132         GateRef address = ChangeTaggedPointerToInt64(PtrAdd(str, IntPtr(ConstantString::CONSTANT_DATA_OFFSET)));
1133         result = Load(VariableType::NATIVE_POINTER(), address, IntPtr(0));
1134         Jump(&exit);
1135     }
1136     Bind(&isLineString);
1137     {
1138         result = ChangeTaggedPointerToInt64(PtrAdd(str, IntPtr(LineEcmaString::DATA_OFFSET)));
1139         Jump(&exit);
1140     }
1141     Bind(&exit);
1142     auto ret = *result;
1143     SubCfgExit();
1144     return ret;
1145 }
1146 
CopyChars(GateRef glue,GateRef dst,GateRef source,GateRef sourceLength,GateRef charSize,VariableType type)1147 void CircuitBuilder::CopyChars(GateRef glue, GateRef dst, GateRef source,
1148     GateRef sourceLength, GateRef charSize, VariableType type)
1149 {
1150     Label subentry(env_);
1151     SubCfgEntry(&subentry);
1152     DEFVALUE(dstTmp, env_, VariableType::NATIVE_POINTER(), dst);
1153     DEFVALUE(sourceTmp, env_, VariableType::NATIVE_POINTER(), source);
1154     DEFVALUE(len, env_, VariableType::INT32(), sourceLength);
1155     Label loopHead(env_);
1156     Label loopEnd(env_);
1157     Label next(env_);
1158     Label exit(env_);
1159     Jump(&loopHead);
1160 
1161     LoopBegin(&loopHead);
1162     {
1163         Branch(Int32GreaterThan(*len, Int32(0)), &next, &exit);
1164         Bind(&next);
1165         {
1166             len = Int32Sub(*len, Int32(1));
1167             GateRef i = Load(type, *sourceTmp, IntPtr(0));
1168             Store(type, glue, *dstTmp, IntPtr(0), i);
1169             Jump(&loopEnd);
1170         }
1171     }
1172     Bind(&loopEnd);
1173     sourceTmp = PtrAdd(*sourceTmp, charSize);
1174     dstTmp = PtrAdd(*dstTmp, charSize);
1175     LoopEnd(&loopHead);
1176 
1177     Bind(&exit);
1178     SubCfgExit();
1179     return;
1180 }
1181 
1182 // source is utf8, dst is utf16
CopyUtf8AsUtf16(GateRef glue,GateRef dst,GateRef src,GateRef sourceLength)1183 void CircuitBuilder::CopyUtf8AsUtf16(GateRef glue, GateRef dst, GateRef src,
1184 
1185     GateRef sourceLength)
1186 {
1187     Label subentry(env_);
1188     SubCfgEntry(&subentry);
1189     DEFVALUE(dstTmp, env_, VariableType::NATIVE_POINTER(), dst);
1190     DEFVALUE(sourceTmp, env_, VariableType::NATIVE_POINTER(), src);
1191     DEFVALUE(len, env_, VariableType::INT32(), sourceLength);
1192     Label loopHead(env_);
1193     Label loopEnd(env_);
1194     Label next(env_);
1195     Label exit(env_);
1196     Jump(&loopHead);
1197     LoopBegin(&loopHead);
1198     {
1199         Branch(Int32GreaterThan(*len, Int32(0)), &next, &exit);
1200         Bind(&next);
1201         {
1202             len = Int32Sub(*len, Int32(1));
1203             GateRef i = Load(VariableType::INT8(), *sourceTmp, IntPtr(0));
1204             Store(VariableType::INT16(), glue, *dstTmp, IntPtr(0), ZExtInt8ToInt16(i));
1205             Jump(&loopEnd);
1206         }
1207     }
1208 
1209     Bind(&loopEnd);
1210     sourceTmp = PtrAdd(*sourceTmp, IntPtr(sizeof(uint8_t)));
1211     dstTmp = PtrAdd(*dstTmp, IntPtr(sizeof(uint16_t)));
1212     LoopEnd(&loopHead);
1213 
1214     Bind(&exit);
1215     SubCfgExit();
1216     return;
1217 }
1218 
TaggedPointerToInt64(GateRef x)1219 GateRef CircuitBuilder::TaggedPointerToInt64(GateRef x)
1220 {
1221     return ChangeTaggedPointerToInt64(x);
1222 }
1223 
ComputeTaggedArraySize(GateRef length)1224 GateRef CircuitBuilder::ComputeTaggedArraySize(GateRef length)
1225 {
1226     return PtrAdd(IntPtr(TaggedArray::DATA_OFFSET),
1227         PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()), length));
1228 }
1229 
GetEnumCacheKind(GateRef glue,GateRef enumCache)1230 GateRef CircuitBuilder::GetEnumCacheKind(GateRef glue, GateRef enumCache)
1231 {
1232     Label entry(env_);
1233     SubCfgEntry(&entry);
1234     Label exit(env_);
1235     DEFVALUE(result, env_, VariableType::INT32(), Int32(static_cast<int32_t>(EnumCacheKind::NONE)));
1236 
1237     Label enumCacheIsArray(env_);
1238     Label isEmptyArray(env_);
1239     Label notEmptyArray(env_);
1240 
1241     Branch(TaggedIsUndefinedOrNull(enumCache), &exit, &enumCacheIsArray);
1242     Bind(&enumCacheIsArray);
1243     GateRef emptyArray = GetEmptyArray(glue);
1244     Branch(Int64Equal(enumCache, emptyArray), &isEmptyArray, &notEmptyArray);
1245     Bind(&isEmptyArray);
1246     {
1247         result = Int32(static_cast<int32_t>(EnumCacheKind::SIMPLE));
1248         Jump(&exit);
1249     }
1250     Bind(&notEmptyArray);
1251     {
1252         GateRef taggedKind = GetValueFromTaggedArray(enumCache, Int32(EnumCache::ENUM_CACHE_KIND_OFFSET));
1253         result = TaggedGetInt(taggedKind);
1254         Jump(&exit);
1255     }
1256 
1257     Bind(&exit);
1258     auto ret = *result;
1259     SubCfgExit();
1260     return ret;
1261 }
1262 
IsEnumCacheValid(GateRef receiver,GateRef cachedHclass,GateRef kind)1263 GateRef CircuitBuilder::IsEnumCacheValid(GateRef receiver, GateRef cachedHclass, GateRef kind)
1264 {
1265     Label entry(env_);
1266     SubCfgEntry(&entry);
1267     Label exit(env_);
1268     DEFVALUE(result, env_, VariableType::BOOL(), False());
1269 
1270     Label isSameHclass(env_);
1271     Label isSimpleEnumCache(env_);
1272     Label notSimpleEnumCache(env_);
1273     Label prototypeIsEcmaObj(env_);
1274     Label isProtoChangeMarker(env_);
1275     Label protoNotChanged(env_);
1276 
1277     GateRef hclass = LoadHClass(receiver);
1278     Branch(Int64Equal(hclass, cachedHclass), &isSameHclass, &exit);
1279     Bind(&isSameHclass);
1280     Branch(Int32Equal(kind, Int32(static_cast<int32_t>(EnumCacheKind::SIMPLE))),
1281            &isSimpleEnumCache, &notSimpleEnumCache);
1282     Bind(&isSimpleEnumCache);
1283     {
1284         result = True();
1285         Jump(&exit);
1286     }
1287     Bind(&notSimpleEnumCache);
1288     GateRef prototype = GetPrototypeFromHClass(hclass);
1289     Branch(IsEcmaObject(prototype), &prototypeIsEcmaObj, &exit);
1290     Bind(&prototypeIsEcmaObj);
1291     GateRef protoChangeMarker = GetProtoChangeMarkerFromHClass(hclass);
1292     Branch(TaggedIsProtoChangeMarker(protoChangeMarker), &isProtoChangeMarker, &exit);
1293     Bind(&isProtoChangeMarker);
1294     Branch(GetHasChanged(protoChangeMarker), &exit, &protoNotChanged);
1295     Bind(&protoNotChanged);
1296     {
1297         result = True();
1298         Jump(&exit);
1299     }
1300     Bind(&exit);
1301     auto ret = *result;
1302     SubCfgExit();
1303     return ret;
1304 }
1305 
NeedCheckProperty(GateRef receiver)1306 GateRef CircuitBuilder::NeedCheckProperty(GateRef receiver)
1307 {
1308     Label entry(env_);
1309     SubCfgEntry(&entry);
1310     Label exit(env_);
1311 
1312     Label loopHead(env_);
1313     Label loopEnd(env_);
1314     Label afterLoop(env_);
1315     Label isJSObject(env_);
1316     Label hasNoDeleteProperty(env_);
1317 
1318     DEFVALUE(result, env_, VariableType::BOOL(), True());
1319     DEFVALUE(current, env_, VariableType::JS_ANY(), receiver);
1320 
1321     Branch(TaggedIsHeapObject(*current), &loopHead, &afterLoop);
1322     LoopBegin(&loopHead);
1323     {
1324         Branch(IsJSObject(*current), &isJSObject, &exit);
1325         Bind(&isJSObject);
1326         GateRef hclass = LoadHClass(*current);
1327         Branch(HasDeleteProperty(hclass), &exit, &hasNoDeleteProperty);
1328         Bind(&hasNoDeleteProperty);
1329         current = GetPrototypeFromHClass(hclass);
1330         Branch(TaggedIsHeapObject(*current), &loopEnd, &afterLoop);
1331     }
1332     Bind(&loopEnd);
1333     LoopEnd(&loopHead);
1334     Bind(&afterLoop);
1335     {
1336         result = False();
1337         Jump(&exit);
1338     }
1339     Bind(&exit);
1340     auto ret = *result;
1341     SubCfgExit();
1342     return ret;
1343 }
1344 
ArrayConstructorCheck(GateRef gate)1345 GateRef CircuitBuilder::ArrayConstructorCheck(GateRef gate)
1346 {
1347     auto currentLabel = env_->GetCurrentLabel();
1348     auto currentControl = currentLabel->GetControl();
1349     auto currentDepend = currentLabel->GetDepend();
1350     auto frameState = acc_.FindNearestFrameState(currentDepend);
1351     GateRef ret = GetCircuit()->NewGate(circuit_->ArrayConstructorCheck(),
1352         MachineType::I64, {currentControl, currentDepend, gate, frameState}, GateType::IntType());
1353     currentLabel->SetControl(ret);
1354     currentLabel->SetDepend(ret);
1355     return ret;
1356 }
1357 
ObjectConstructorCheck(GateRef gate)1358 GateRef CircuitBuilder::ObjectConstructorCheck(GateRef gate)
1359 {
1360     auto currentLabel = env_->GetCurrentLabel();
1361     auto currentControl = currentLabel->GetControl();
1362     auto currentDepend = currentLabel->GetDepend();
1363     auto frameState = acc_.FindNearestFrameState(currentDepend);
1364     GateRef ret = GetCircuit()->NewGate(circuit_->ObjectConstructorCheck(),
1365         MachineType::I64, {currentControl, currentDepend, gate, frameState}, GateType::IntType());
1366     currentLabel->SetControl(ret);
1367     currentLabel->SetDepend(ret);
1368     return ret;
1369 }
1370 
MonoLoadPropertyOnProto(GateRef receiver,GateRef plrGate,GateRef jsFunc,size_t hclassIndex)1371 GateRef CircuitBuilder::MonoLoadPropertyOnProto(GateRef receiver, GateRef plrGate, GateRef jsFunc, size_t hclassIndex)
1372 {
1373     auto currentLabel = env_->GetCurrentLabel();
1374     auto currentControl = currentLabel->GetControl();
1375     auto currentDepend = currentLabel->GetDepend();
1376     auto frameState = acc_.FindNearestFrameState(currentDepend);
1377     auto ret = GetCircuit()->NewGate(circuit_->MonoLoadPropertyOnProto(), MachineType::I64,
1378                                      { currentControl, currentDepend, receiver, plrGate, Int32(hclassIndex), jsFunc,
1379                                        frameState },
1380                                      GateType::AnyType());
1381     currentLabel->SetControl(ret);
1382     currentLabel->SetDepend(ret);
1383     return ret;
1384 }
1385 
MonoCallGetterOnProto(GateRef gate,GateRef receiver,GateRef plrGate,GateRef jsFunc,size_t hclassIndex)1386 GateRef CircuitBuilder::MonoCallGetterOnProto(GateRef gate, GateRef receiver, GateRef plrGate, GateRef jsFunc,
1387                                               size_t hclassIndex)
1388 {
1389     uint64_t pcOffset = acc_.TryGetPcOffset(gate);
1390     ASSERT(pcOffset != 0);
1391 
1392     auto currentLabel = env_->GetCurrentLabel();
1393     auto currentControl = currentLabel->GetControl();
1394     auto currentDepend = currentLabel->GetDepend();
1395     auto frameState = acc_.FindNearestFrameState(currentDepend);
1396     std::vector<GateRef> args = { currentControl, currentDepend, receiver, plrGate, Int32(hclassIndex), jsFunc,
1397                                   frameState };
1398     auto callGate = GetCircuit()->NewGate(circuit_->MonoCallGetterOnProto(pcOffset),
1399                                           MachineType::I64,
1400                                           args.size(),
1401                                           args.data(),
1402                                           GateType::AnyType());
1403     currentLabel->SetControl(callGate);
1404     currentLabel->SetDepend(callGate);
1405     return callGate;
1406 }
1407 
MonoStorePropertyLookUpProto(GateRef receiver,GateRef plrGate,GateRef jsFunc,size_t hclassIndex,GateRef value)1408 GateRef CircuitBuilder::MonoStorePropertyLookUpProto(GateRef receiver, GateRef plrGate, GateRef jsFunc,
1409                                                      size_t hclassIndex, GateRef value)
1410 {
1411     auto currentLabel = env_->GetCurrentLabel();
1412     auto currentControl = currentLabel->GetControl();
1413     auto currentDepend = currentLabel->GetDepend();
1414     auto frameState = acc_.FindNearestFrameState(currentDepend);
1415     auto ret = GetCircuit()->NewGate(circuit_->MonoStorePropertyLookUpProto(false), MachineType::I64,
1416         { currentControl, currentDepend, receiver, plrGate, Int32(hclassIndex), jsFunc, value, frameState},
1417         GateType::AnyType());
1418     currentLabel->SetControl(ret);
1419     currentLabel->SetDepend(ret);
1420     return ret;
1421 }
1422 
MonoStoreProperty(GateRef receiver,GateRef plrGate,GateRef jsFunc,size_t hclassIndex,GateRef value,GateRef key)1423 GateRef CircuitBuilder::MonoStoreProperty(GateRef receiver, GateRef plrGate, GateRef jsFunc, size_t hclassIndex,
1424                                           GateRef value, GateRef key)
1425 {
1426     auto currentLabel = env_->GetCurrentLabel();
1427     auto currentControl = currentLabel->GetControl();
1428     auto currentDepend = currentLabel->GetDepend();
1429     auto ret = GetCircuit()->NewGate(circuit_->MonoStoreProperty(false), MachineType::I64,
1430         { currentControl, currentDepend, receiver, plrGate, Int32(hclassIndex), jsFunc, value, key },
1431         GateType::AnyType());
1432     currentLabel->SetControl(ret);
1433     currentLabel->SetDepend(ret);
1434     return ret;
1435 }
1436 
TypedCreateObjWithBuffer(std::vector<GateRef> & valueIn)1437 GateRef CircuitBuilder::TypedCreateObjWithBuffer(std::vector<GateRef> &valueIn)
1438 {
1439     auto currentLabel = env_->GetCurrentLabel();
1440     auto currentControl = currentLabel->GetControl();
1441     auto currentDepend = currentLabel->GetDepend();
1442     std::vector<GateRef> vec { currentControl, currentDepend };
1443     vec.insert(vec.end(), valueIn.begin(), valueIn.end());
1444     GateRef ret = GetCircuit()->NewGate(circuit_->TypedCreateObjWithBuffer(valueIn.size()),
1445         MachineType::I64, vec, GateType::AnyType());
1446     currentLabel->SetControl(ret);
1447     currentLabel->SetDepend(ret);
1448     return ret;
1449 }
1450 
ToNumber(GateRef gate,GateRef value,GateRef glue)1451 GateRef CircuitBuilder::ToNumber(GateRef gate, GateRef value, GateRef glue)
1452 {
1453     Label entry(env_);
1454     env_->SubCfgEntry(&entry);
1455     Label exit(env_);
1456     Label isNumber(env_);
1457     Label notNumber(env_);
1458     DEFVALUE(result, env_, VariableType::JS_ANY(), Hole());
1459     Branch(TaggedIsNumber(value), &isNumber, &notNumber);
1460     Bind(&isNumber);
1461     {
1462         result = value;
1463         Jump(&exit);
1464     }
1465     Bind(&notNumber);
1466     {
1467         result = CallRuntime(glue, RTSTUB_ID(ToNumber), Gate::InvalidGateRef, { value }, gate);
1468         Jump(&exit);
1469     }
1470     Bind(&exit);
1471     auto ret = *result;
1472     env_->SubCfgExit();
1473     return ret;
1474 }
1475 
StringFromSingleCharCode(GateRef gate)1476 GateRef CircuitBuilder::StringFromSingleCharCode(GateRef gate)
1477 {
1478     auto currentLabel = env_->GetCurrentLabel();
1479     auto currentControl = currentLabel->GetControl();
1480     auto currentDepend = currentLabel->GetDepend();
1481     GateRef ret =
1482         GetCircuit()->NewGate(circuit_->StringFromSingleCharCode(), MachineType::I64,
1483             { currentControl, currentDepend, gate }, GateType::AnyType());
1484     currentLabel->SetControl(ret);
1485     currentLabel->SetDepend(ret);
1486     return ret;
1487 }
1488 
IsASCIICharacter(GateRef gate)1489 GateRef CircuitBuilder::IsASCIICharacter(GateRef gate)
1490 {
1491     return Int32UnsignedLessThan(Int32Sub(gate, Int32(1)), Int32(base::utf_helper::UTF8_1B_MAX));
1492 }
1493 }
1494