1 /*
2 * Copyright (c) 2023-2024 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/hcr_circuit_builder.h"
17 #include "ecmascript/compiler/circuit_builder-inl.h"
18
19 namespace panda::ecmascript::kungfu {
20
NoLabelCallRuntime(GateRef glue,GateRef depend,size_t index,std::vector<GateRef> & args,GateRef hirGate)21 GateRef CircuitBuilder::NoLabelCallRuntime(GateRef glue, GateRef depend, size_t index, std::vector<GateRef> &args,
22 GateRef hirGate)
23 {
24 const std::string name = RuntimeStubCSigns::GetRTName(RTSTUB_ID(CallRuntime));
25 const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
26 GateRef target = IntPtr(index);
27 std::vector<GateRef> inputs { depend, target, glue };
28 inputs.insert(inputs.end(), args.begin(), args.end());
29 auto numValuesIn = args.size() + 2; // 2: target & glue
30 inputs.emplace_back(IntPtr(0)); // framestate slot
31 numValuesIn += 1;
32 GateRef pcOffset = Int64(acc_.TryGetPcOffset(hirGate));
33 inputs.emplace_back(pcOffset);
34 numValuesIn += 1;
35
36 const GateMetaData* meta = circuit_->RuntimeCall(numValuesIn);
37 MachineType machineType = cs->GetReturnType().GetMachineType();
38 GateType type = cs->GetReturnType().GetGateType();
39 GateRef result = circuit_->NewGate(meta, machineType, inputs.size(), inputs.data(), type, name.c_str());
40 return result;
41 }
42
ToLength(GateRef receiver)43 GateRef CircuitBuilder::ToLength(GateRef receiver)
44 {
45 auto currentLabel = env_->GetCurrentLabel();
46 auto currentControl = currentLabel->GetControl();
47 auto currentDepend = currentLabel->GetDepend();
48 auto ret = GetCircuit()->NewGate(circuit_->ToLength(), MachineType::I64,
49 { currentControl, currentDepend, receiver }, GateType::NumberType());
50 currentLabel->SetControl(ret);
51 currentLabel->SetDepend(ret);
52 return ret;
53 }
54
CallStub(GateRef glue,GateRef hirGate,int index,const std::vector<GateRef> & args,const char * comment)55 GateRef CircuitBuilder::CallStub(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args,
56 const char* comment)
57 {
58 const CallSignature *cs = env_->IsBaselineBuiltin() ? BaselineStubCSigns::Get(index) :
59 CommonStubCSigns::Get(index);
60 ASSERT(cs->IsCommonStub() || cs->IsBaselineStub());
61 GateRef target = IntPtr(index);
62 auto label = GetCurrentLabel();
63 auto depend = label->GetDepend();
64 GateRef result;
65 if (GetCircuit()->IsOptimizedOrFastJit()) {
66 ASSERT(hirGate != Circuit::NullGate());
67 result = Call(cs, glue, target, depend, args, hirGate, comment);
68 } else {
69 result = Call(cs, glue, target, depend, args, Circuit::NullGate(), comment);
70 }
71 return result;
72 }
73
CallCommonStub(GateRef glue,GateRef hirGate,int index,const std::vector<GateRef> & args,const char * comment)74 GateRef CircuitBuilder::CallCommonStub(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args,
75 const char *comment)
76 {
77 const CallSignature *cs = CommonStubCSigns::Get(index);
78 ASSERT(cs->IsCommonStub());
79 GateRef target = IntPtr(index);
80 auto label = GetCurrentLabel();
81 auto depend = label->GetDepend();
82 GateRef result;
83 if (GetCircuit()->IsOptimizedOrFastJit()) {
84 ASSERT(hirGate != Circuit::NullGate());
85 result = Call(cs, glue, target, depend, args, hirGate, comment);
86 } else {
87 result = Call(cs, glue, target, depend, args, Circuit::NullGate(), comment);
88 }
89 return result;
90 }
91
CallBuiltinRuntime(GateRef glue,GateRef depend,const std::vector<GateRef> & args,bool isNew)92 GateRef CircuitBuilder::CallBuiltinRuntime(GateRef glue, GateRef depend, const std::vector<GateRef> &args, bool isNew)
93 {
94 ASSERT(!GetCircuit()->IsOptimizedOrFastJit());
95 int index = 0;
96 if (!isNew) {
97 index = static_cast<int>(RTSTUB_ID(PushCallArgsAndDispatchNative));
98 } else {
99 index = static_cast<int>(RTSTUB_ID(PushCallNewAndDispatchNative));
100 }
101 const std::string name = RuntimeStubCSigns::GetRTName(index);
102
103 const CallSignature *cs = RuntimeStubCSigns::Get(index);
104 GateRef target = IntPtr(index);
105 auto label = GetCurrentLabel();
106 if (depend == Gate::InvalidGateRef) {
107 depend = label->GetDepend();
108 }
109 GateRef result = Call(cs, glue, target, depend, args, Circuit::NullGate(), name.c_str());
110 return result;
111 }
112
CallBuiltinRuntimeWithNewTarget(GateRef glue,GateRef depend,const std::vector<GateRef> & args)113 GateRef CircuitBuilder::CallBuiltinRuntimeWithNewTarget(GateRef glue, GateRef depend, const std::vector<GateRef> &args)
114 {
115 ASSERT(!GetCircuit()->IsOptimizedOrFastJit());
116 int index = 0;
117
118 index = static_cast<int>(RTSTUB_ID(PushNewTargetAndDispatchNative));
119 const std::string name = RuntimeStubCSigns::GetRTName(index);
120
121 const CallSignature *cs = RuntimeStubCSigns::Get(index);
122 GateRef target = IntPtr(index);
123 auto label = GetCurrentLabel();
124 if (depend == Gate::InvalidGateRef) {
125 depend = label->GetDepend();
126 }
127 GateRef result = Call(cs, glue, target, depend, args, Circuit::NullGate(), name.c_str());
128 return result;
129 }
130
Call(const CallSignature * cs,GateRef glue,GateRef target,GateRef depend,const std::vector<GateRef> & args,GateRef hirGate,const char * comment)131 GateRef CircuitBuilder::Call(const CallSignature* cs, GateRef glue, GateRef target, GateRef depend,
132 const std::vector<GateRef> &args, GateRef hirGate, const char* comment)
133 {
134 std::vector<GateRef> inputs { depend, target, glue };
135 inputs.insert(inputs.end(), args.begin(), args.end());
136 auto numValuesIn = args.size() + 2; // 2: target & glue
137 if (GetCircuit()->IsOptimizedOrFastJit() && hirGate != Circuit::NullGate()) {
138 AppendFrameState(inputs, hirGate);
139 numValuesIn += 1;
140 }
141
142 const GateMetaData* meta = nullptr;
143 if (cs->IsCommonStub()) {
144 meta = circuit_->Call(numValuesIn);
145 } else if (cs->IsRuntimeVAStub()) {
146 meta = circuit_->RuntimeCallWithArgv(numValuesIn);
147 } else if (cs->IsRuntimeStub()) {
148 meta = circuit_->RuntimeCall(numValuesIn);
149 } else if (cs->IsBCDebuggerStub()) {
150 meta = circuit_->DebuggerBytecodeCall(numValuesIn);
151 } else if (cs->IsBCHandlerStub()) {
152 meta = circuit_->BytecodeCall(numValuesIn);
153 } else if (cs->IsBuiltinsStub()) {
154 meta = circuit_->BuiltinsCall(numValuesIn);
155 } else if (cs->IsBuiltinsWithArgvStub()) {
156 meta = circuit_->BuiltinsCallWithArgv(numValuesIn);
157 } else if (cs->IsRuntimeNGCStub()) {
158 meta = circuit_->NoGcRuntimeCall(numValuesIn);
159 } else if (cs->IsOptimizedStub()) {
160 bool isNoGC = acc_.GetNoGCFlag(hirGate);
161 meta = circuit_->CallOptimized(numValuesIn, isNoGC);
162 } else if (cs->IsOptimizedFastCallStub()) {
163 bool isNoGC = acc_.GetNoGCFlag(hirGate);
164 meta = circuit_->FastCallOptimized(numValuesIn, isNoGC);
165 } else if (cs->IsBaselineStub()) {
166 meta = circuit_->BaselineCall(numValuesIn);
167 } else if (cs->IsASMCallBarrierStub()) {
168 meta = circuit_->ASMCallBarrier(numValuesIn);
169 } else {
170 LOG_ECMA(FATAL) << "unknown call operator";
171 UNREACHABLE();
172 }
173 MachineType machineType = cs->GetReturnType().GetMachineType();
174 GateType type = cs->GetReturnType().GetGateType();
175 GateRef result = GetCircuit()->NewGate(meta, machineType, inputs.size(), inputs.data(), type, comment);
176 auto label = GetCurrentLabel();
177 label->SetDepend(result);
178 return result;
179 }
180
CallBCHandler(GateRef glue,GateRef target,const std::vector<GateRef> & args,const char * comment)181 GateRef CircuitBuilder::CallBCHandler(GateRef glue, GateRef target, const std::vector<GateRef> &args,
182 const char* comment)
183 {
184 ASSERT(!GetCircuit()->IsOptimizedOrFastJit());
185 const CallSignature *cs = BytecodeStubCSigns::BCHandler();
186 ASSERT(cs->IsBCStub());
187 auto label = GetCurrentLabel();
188 auto depend = label->GetDepend();
189 GateRef result = Call(cs, glue, target, depend, args, Circuit::NullGate(), comment);
190 return result;
191 }
192
CallBuiltin(GateRef glue,GateRef target,const std::vector<GateRef> & args,GateRef hir,const char * comment)193 GateRef CircuitBuilder::CallBuiltin(GateRef glue, GateRef target, const std::vector<GateRef> &args,
194 GateRef hir, const char* comment)
195 {
196 const CallSignature *cs = BuiltinsStubCSigns::BuiltinsCSign();
197 ASSERT(cs->IsBuiltinsStub());
198 auto label = GetCurrentLabel();
199 auto depend = label->GetDepend();
200 GateRef result;
201 if (GetCircuit()->IsOptimizedOrFastJit()) {
202 ASSERT(hir != Circuit::NullGate());
203 result = Call(cs, glue, target, depend, args, hir, comment);
204 } else {
205 result = Call(cs, glue, target, depend, args, Circuit::NullGate(), comment);
206 }
207 return result;
208 }
209
CallBuiltinWithArgv(GateRef glue,GateRef target,const std::vector<GateRef> & args,const char * comment)210 GateRef CircuitBuilder::CallBuiltinWithArgv(GateRef glue, GateRef target, const std::vector<GateRef> &args,
211 const char* comment)
212 {
213 ASSERT(!GetCircuit()->IsOptimizedOrFastJit());
214 const CallSignature *cs = BuiltinsStubCSigns::BuiltinsWithArgvCSign();
215 ASSERT(cs->IsBuiltinsWithArgvStub());
216 auto label = GetCurrentLabel();
217 auto depend = label->GetDepend();
218 GateRef result = Call(cs, glue, target, depend, args, Circuit::NullGate(), comment);
219 return result;
220 }
221
CallBCDebugger(GateRef glue,GateRef target,const std::vector<GateRef> & args,const char * comment)222 GateRef CircuitBuilder::CallBCDebugger(GateRef glue, GateRef target, const std::vector<GateRef> &args,
223 const char* comment)
224 {
225 ASSERT(!GetCircuit()->IsOptimizedOrFastJit());
226 const CallSignature *cs = BytecodeStubCSigns::BCDebuggerHandler();
227 ASSERT(cs->IsBCDebuggerStub());
228 auto label = GetCurrentLabel();
229 auto depend = label->GetDepend();
230 GateRef result = Call(cs, glue, target, depend, args, Circuit::NullGate(), comment);
231 return result;
232 }
233
CallRuntime(GateRef glue,int index,GateRef depend,const std::vector<GateRef> & args,GateRef hirGate,const char * comment)234 GateRef CircuitBuilder::CallRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args,
235 GateRef hirGate, const char* comment)
236 {
237 GateRef target = IntPtr(index);
238 const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
239 ASSERT(cs->IsRuntimeStub());
240 auto label = GetCurrentLabel();
241 if (depend == Gate::InvalidGateRef) {
242 depend = label->GetDepend();
243 }
244 GateRef filteredHirGate = Circuit::NullGate();
245 if (GetCircuit()->IsOptimizedOrFastJit()) {
246 ASSERT(hirGate != Circuit::NullGate());
247 filteredHirGate = hirGate;
248 }
249 GateRef result = Call(cs, glue, target, depend, args, filteredHirGate, comment);
250 return result;
251 }
252
CallRuntimeVarargs(GateRef glue,int index,GateRef argc,GateRef argv,const char * comment)253 GateRef CircuitBuilder::CallRuntimeVarargs(GateRef glue, int index, GateRef argc, GateRef argv, const char* comment)
254 {
255 ASSERT(!GetCircuit()->IsOptimizedOrFastJit());
256 const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntimeWithArgv));
257 GateRef target = IntPtr(index);
258 auto label = GetCurrentLabel();
259 auto depend = label->GetDepend();
260 ASSERT(cs->IsRuntimeVAStub());
261 GateRef result = Call(cs, glue, target, depend, {argc, argv}, Circuit::NullGate(), comment);
262 return result;
263 }
264
CallNGCRuntime(GateRef glue,int index,GateRef depend,const std::vector<GateRef> & args,GateRef hirGate,const char * comment)265 GateRef CircuitBuilder::CallNGCRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args,
266 GateRef hirGate, const char* comment)
267 {
268 const CallSignature *cs = RuntimeStubCSigns::Get(index);
269 ASSERT(cs->IsRuntimeNGCStub());
270 GateRef target = IntPtr(index);
271 auto label = GetCurrentLabel();
272 if (depend == Gate::InvalidGateRef) {
273 depend = label->GetDepend();
274 }
275 GateRef filteredHirGate = Circuit::NullGate();
276 if (GetCircuit()->IsOptimizedOrFastJit() && RuntimeStubCSigns::IsAsmStub(index)) {
277 ASSERT(hirGate != Circuit::NullGate());
278 filteredHirGate = hirGate;
279 }
280 GateRef result = Call(cs, glue, target, depend, args, filteredHirGate, comment);
281 return result;
282 }
283
CallNGCRuntime(GateRef glue,GateRef gate,int index,const std::vector<GateRef> & args,bool useLabel)284 GateRef CircuitBuilder::CallNGCRuntime(GateRef glue, GateRef gate, int index, const std::vector<GateRef> &args,
285 bool useLabel)
286 {
287 const std::string name = RuntimeStubCSigns::GetRTName(index);
288 if (useLabel) {
289 GateRef result = CallNGCRuntime(glue, index, Gate::InvalidGateRef, args, gate, name.c_str());
290 return result;
291 } else {
292 const CallSignature *cs = RuntimeStubCSigns::Get(index);
293 GateRef target = IntPtr(index);
294 GateRef result = Call(cs, glue, target, GetDepend(), args, gate, name.c_str());
295 return result;
296 }
297 }
298
StartCallTimer(GateRef glue,GateRef gate,const std::vector<GateRef> & args,bool useLabel)299 void CircuitBuilder::StartCallTimer(GateRef glue, GateRef gate, const std::vector<GateRef> &args, bool useLabel)
300 {
301 (void)glue;
302 (void)gate;
303 (void)args;
304 (void)useLabel;
305 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
306 CallNGCRuntime(glue, gate, RTSTUB_ID(StartCallTimer), args, useLabel);
307 #endif
308 }
309
EndCallTimer(GateRef glue,GateRef gate,const std::vector<GateRef> & args,bool useLabel)310 void CircuitBuilder::EndCallTimer(GateRef glue, GateRef gate, const std::vector<GateRef> &args, bool useLabel)
311 {
312 (void)glue;
313 (void)gate;
314 (void)args;
315 (void)useLabel;
316 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
317 CallNGCRuntime(glue, gate, RTSTUB_ID(EndCallTimer), args, useLabel);
318 #endif
319 }
320
FastCallOptimized(GateRef glue,GateRef code,GateRef depend,const std::vector<GateRef> & args,GateRef hirGate)321 GateRef CircuitBuilder::FastCallOptimized(GateRef glue, GateRef code, GateRef depend, const std::vector<GateRef> &args,
322 GateRef hirGate)
323 {
324 const CallSignature *cs = RuntimeStubCSigns::GetOptimizedFastCallSign();
325 ASSERT(cs->IsOptimizedFastCallStub());
326 auto label = GetCurrentLabel();
327 if (depend == Gate::InvalidGateRef) {
328 depend = label->GetDepend();
329 }
330 GateRef filteredHirGate = Circuit::NullGate();
331 if (GetCircuit()->IsOptimizedOrFastJit()) {
332 ASSERT(hirGate != Circuit::NullGate());
333 filteredHirGate = hirGate;
334 }
335 GateRef result = Call(cs, glue, code, depend, args, filteredHirGate, "fastCallOptimized");
336 return result;
337 }
338
CallOptimized(GateRef glue,GateRef code,GateRef depend,const std::vector<GateRef> & args,GateRef hirGate)339 GateRef CircuitBuilder::CallOptimized(GateRef glue, GateRef code, GateRef depend, const std::vector<GateRef> &args,
340 GateRef hirGate)
341 {
342 const CallSignature *cs = RuntimeStubCSigns::GetOptimizedCallSign();
343 ASSERT(cs->IsOptimizedStub());
344 auto label = GetCurrentLabel();
345 if (depend == Gate::InvalidGateRef) {
346 depend = label->GetDepend();
347 }
348 GateRef filteredHirGate = Circuit::NullGate();
349 if (GetCircuit()->IsOptimizedOrFastJit()) {
350 ASSERT(hirGate != Circuit::NullGate());
351 filteredHirGate = hirGate;
352 }
353 GateRef result = Call(cs, glue, code, depend, args, filteredHirGate, "callOptimized");
354 return result;
355 }
356
GetCallBuiltinId(GateRef method)357 GateRef CircuitBuilder::GetCallBuiltinId(GateRef method)
358 {
359 GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
360 GateRef extraLiteralInfo = LoadWithoutBarrier(VariableType::INT64(), method, extraLiteralInfoOffset);
361 return Int64And(
362 Int64LSR(extraLiteralInfo, Int64(MethodLiteral::BuiltinIdBits::START_BIT)),
363 Int64((1LU << MethodLiteral::BuiltinIdBits::SIZE) - 1));
364 }
365
CallPrivateGetter(GateRef hirGate,GateRef receiver,GateRef accessor,const char * comment)366 GateRef CircuitBuilder::CallPrivateGetter(GateRef hirGate, GateRef receiver, GateRef accessor, const char* comment)
367 {
368 ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
369 uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
370 ASSERT(pcOffset != 0);
371
372 auto currentLabel = env_->GetCurrentLabel();
373 auto currentControl = currentLabel->GetControl();
374 auto currentDepend = currentLabel->GetDepend();
375 std::vector<GateRef> args = {currentControl, currentDepend, receiver, accessor};
376 AppendFrameState(args, hirGate);
377 auto callGate = GetCircuit()->NewGate(circuit_->CallPrivateGetter(pcOffset),
378 MachineType::I64,
379 args.size(),
380 args.data(),
381 GateType::AnyType(),
382 comment);
383 currentLabel->SetControl(callGate);
384 currentLabel->SetDepend(callGate);
385 return callGate;
386 }
387
CallPrivateSetter(GateRef hirGate,GateRef receiver,GateRef accessor,GateRef value,const char * comment)388 GateRef CircuitBuilder::CallPrivateSetter(
389 GateRef hirGate, GateRef receiver, GateRef accessor, GateRef value, const char* comment)
390 {
391 ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
392 uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
393 ASSERT(pcOffset != 0);
394
395 auto currentLabel = env_->GetCurrentLabel();
396 auto currentControl = currentLabel->GetControl();
397 auto currentDepend = currentLabel->GetDepend();
398 std::vector<GateRef> args = {currentControl, currentDepend, receiver, accessor, value};
399 AppendFrameState(args, hirGate);
400 auto callGate = GetCircuit()->NewGate(circuit_->CallPrivateSetter(pcOffset),
401 MachineType::I64,
402 args.size(),
403 args.data(),
404 GateType::AnyType(),
405 comment);
406 currentLabel->SetControl(callGate);
407 currentLabel->SetDepend(callGate);
408 return callGate;
409 }
410
CallGetter(GateRef hirGate,GateRef receiver,GateRef holder,GateRef propertyLookupResult,const char * comment)411 GateRef CircuitBuilder::CallGetter(GateRef hirGate, GateRef receiver, GateRef holder, GateRef propertyLookupResult,
412 const char* comment)
413 {
414 ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
415 uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
416 ASSERT(pcOffset != 0);
417
418 auto currentLabel = env_->GetCurrentLabel();
419 auto currentControl = currentLabel->GetControl();
420 auto currentDepend = currentLabel->GetDepend();
421 std::vector<GateRef> args = { currentControl, currentDepend, receiver, propertyLookupResult, holder };
422 AppendFrameState(args, hirGate);
423 auto callGate = GetCircuit()->NewGate(circuit_->CallGetter(pcOffset),
424 MachineType::I64,
425 args.size(),
426 args.data(),
427 GateType::AnyType(),
428 comment);
429 currentLabel->SetControl(callGate);
430 currentLabel->SetDepend(callGate);
431 return callGate;
432 }
433
CallSetter(GateRef hirGate,GateRef receiver,GateRef holder,GateRef propertyLookupResult,GateRef value,const char * comment)434 GateRef CircuitBuilder::CallSetter(GateRef hirGate, GateRef receiver, GateRef holder, GateRef propertyLookupResult,
435 GateRef value, const char* comment)
436 {
437 ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
438 uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
439 ASSERT(pcOffset != 0);
440
441 auto currentLabel = env_->GetCurrentLabel();
442 auto currentControl = currentLabel->GetControl();
443 auto currentDepend = currentLabel->GetDepend();
444 std::vector<GateRef> args = { currentControl, currentDepend, receiver, propertyLookupResult, holder, value };
445 AppendFrameState(args, hirGate);
446 auto callGate = GetCircuit()->NewGate(circuit_->CallSetter(pcOffset),
447 MachineType::I64,
448 args.size(),
449 args.data(),
450 GateType::AnyType(),
451 comment);
452 currentLabel->SetControl(callGate);
453 currentLabel->SetDepend(callGate);
454 return callGate;
455 }
456
Float32ArrayConstructor(GateRef hirGate,std::vector<GateRef> args)457 GateRef CircuitBuilder::Float32ArrayConstructor(GateRef hirGate, std::vector<GateRef> args)
458 {
459 ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
460 auto currentLabel = env_->GetCurrentLabel();
461 auto currentControl = currentLabel->GetControl();
462 auto currentDepend = currentLabel->GetDepend();
463 uint64_t bitfield = args.size();
464 uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
465 ASSERT(pcOffset != 0);
466 args.insert(args.begin(), currentDepend);
467 args.insert(args.begin(), currentControl);
468 AppendFrameState(args, hirGate);
469 auto callGate = GetCircuit()->NewGate(circuit_->Float32ArrayConstructor(bitfield, pcOffset),
470 MachineType::I64, args.size(), args.data(), GateType::AnyType());
471 currentLabel->SetControl(callGate);
472 currentLabel->SetDepend(callGate);
473 return callGate;
474 }
475
Construct(GateRef hirGate,std::vector<GateRef> args)476 GateRef CircuitBuilder::Construct(GateRef hirGate, std::vector<GateRef> args)
477 {
478 ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE || acc_.GetOpCode(hirGate) == OpCode::REFLECT_CONSTRUCT);
479 auto currentLabel = env_->GetCurrentLabel();
480 auto currentControl = currentLabel->GetControl();
481 auto currentDepend = currentLabel->GetDepend();
482 uint64_t bitfield = args.size();
483 uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
484 args.insert(args.begin(), currentDepend);
485 args.insert(args.begin(), currentControl);
486 AppendFrameState(args, hirGate);
487 auto callGate = GetCircuit()->NewGate(circuit_->Construct(bitfield, pcOffset), MachineType::I64,
488 args.size(), args.data(), GateType::AnyType());
489 currentLabel->SetControl(callGate);
490 currentLabel->SetDepend(callGate);
491 return callGate;
492 }
493
CallInternal(GateRef hirGate,std::vector<GateRef> args,uint64_t pcOffset)494 GateRef CircuitBuilder::CallInternal(GateRef hirGate, std::vector<GateRef> args, uint64_t pcOffset)
495 {
496 auto currentLabel = env_->GetCurrentLabel();
497 auto currentControl = currentLabel->GetControl();
498 auto currentDepend = currentLabel->GetDepend();
499 uint64_t bitfield = args.size();
500 ASSERT(pcOffset != 0);
501 args.insert(args.begin(), currentDepend);
502 args.insert(args.begin(), currentControl);
503 AppendFrameState(args, hirGate);
504 auto callGate = GetCircuit()->NewGate(
505 circuit_->CallInternal(bitfield, pcOffset), MachineType::I64, args.size(), args.data(), GateType::AnyType());
506 currentLabel->SetControl(callGate);
507 currentLabel->SetDepend(callGate);
508 return callGate;
509 }
510
CallNew(GateRef hirGate,std::vector<GateRef> args,bool needPushArgv,bool isFastCall)511 GateRef CircuitBuilder::CallNew(GateRef hirGate, std::vector<GateRef> args,
512 bool needPushArgv, bool isFastCall)
513 {
514 ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE ||
515 acc_.GetOpCode(hirGate) == OpCode::FLOAT32_ARRAY_CONSTRUCTOR);
516 auto currentLabel = env_->GetCurrentLabel();
517 auto currentControl = currentLabel->GetControl();
518 auto currentDepend = currentLabel->GetDepend();
519 uint64_t bitfield = args.size();
520 uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
521 ASSERT(pcOffset != 0);
522 args.insert(args.begin(), currentDepend);
523 args.insert(args.begin(), currentControl);
524 AppendFrameState(args, hirGate);
525 auto callGate = GetCircuit()->NewGate(circuit_->CallNew(bitfield, pcOffset, needPushArgv, isFastCall),
526 MachineType::I64, args.size(), args.data(), GateType::AnyType());
527 currentLabel->SetControl(callGate);
528 currentLabel->SetDepend(callGate);
529 return callGate;
530 }
531
CreateArray(ElementsKind kind,uint32_t arraySize,GateRef elementsLength,RegionSpaceFlag flag)532 GateRef CircuitBuilder::CreateArray(ElementsKind kind, uint32_t arraySize,
533 GateRef elementsLength, RegionSpaceFlag flag)
534 {
535 auto currentLabel = env_->GetCurrentLabel();
536 auto currentControl = currentLabel->GetControl();
537 auto currentDepend = currentLabel->GetDepend();
538 ArrayMetaDataAccessor accessor(kind, ArrayMetaDataAccessor::Mode::CREATE, arraySize, flag);
539 GateRef newGate = GetCircuit()->NewGate(circuit_->CreateArray(accessor.ToValue()), MachineType::I64,
540 { currentControl, currentDepend, elementsLength },
541 GateType::TaggedValue());
542 currentLabel->SetControl(newGate);
543 currentLabel->SetDepend(newGate);
544 return newGate;
545 }
546
CreateArrayWithBuffer(ElementsKind kind,ArrayMetaDataAccessor::Mode mode,GateRef cpId,GateRef constPoolIndex,RegionSpaceFlag flag)547 GateRef CircuitBuilder::CreateArrayWithBuffer(ElementsKind kind, ArrayMetaDataAccessor::Mode mode, GateRef cpId,
548 GateRef constPoolIndex, RegionSpaceFlag flag)
549 {
550 auto currentLabel = env_->GetCurrentLabel();
551 auto currentControl = currentLabel->GetControl();
552 auto currentDepend = currentLabel->GetDepend();
553 auto frameState = acc_.FindNearestFrameState(currentDepend);
554 ArrayMetaDataAccessor accessor(kind, mode, 0, flag);
555 GateRef newGate = GetCircuit()->NewGate(circuit_->CreateArrayWithBuffer(accessor.ToValue()),
556 MachineType::I64,
557 { currentControl, currentDepend, cpId, constPoolIndex, frameState },
558 GateType::NJSValue());
559 currentLabel->SetControl(newGate);
560 currentLabel->SetDepend(newGate);
561 return newGate;
562 }
563
CreateArguments(ElementsKind kind,CreateArgumentsAccessor::Mode mode,GateRef restIdx)564 GateRef CircuitBuilder::CreateArguments(ElementsKind kind, CreateArgumentsAccessor::Mode mode, GateRef restIdx)
565 {
566 auto currentLabel = env_->GetCurrentLabel();
567 auto currentControl = currentLabel->GetControl();
568 auto currentDepend = currentLabel->GetDepend();
569 auto frameState = acc_.FindNearestFrameState(currentDepend);
570 CreateArgumentsAccessor accessor(kind, mode);
571 GateRef newGate = GetCircuit()->NewGate(circuit_->CreateArguments(accessor.ToValue()),
572 MachineType::I64,
573 { currentControl, currentDepend, restIdx, frameState },
574 GateType::NJSValue());
575 currentLabel->SetControl(newGate);
576 currentLabel->SetDepend(newGate);
577 return newGate;
578 }
579
SetPropertyInlinedProps(GateRef glue,GateRef obj,GateRef hClass,GateRef value,GateRef attrOffset,VariableType type)580 void CircuitBuilder::SetPropertyInlinedProps(GateRef glue, GateRef obj, GateRef hClass,
581 GateRef value, GateRef attrOffset, VariableType type)
582 {
583 GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), hClass, IntPtr(JSHClass::BIT_FIELD1_OFFSET));
584 GateRef inlinedPropsStart = Int32And(Int32LSR(bitfield,
585 Int32(JSHClass::InlinedPropsStartBits::START_BIT)),
586 Int32((1LU << JSHClass::InlinedPropsStartBits::SIZE) - 1));
587 GateRef propOffset = Int32Mul(Int32Add(inlinedPropsStart, attrOffset),
588 Int32(JSTaggedValue::TaggedTypeSize()));
589 Store(type, glue, obj, ZExtInt32ToPtr(propOffset), value);
590 }
591
StoreModuleVar(GateRef jsFunc,GateRef index,GateRef value)592 GateRef CircuitBuilder::StoreModuleVar(GateRef jsFunc, GateRef index, GateRef value)
593 {
594 auto currentLabel = env_->GetCurrentLabel();
595 auto currentControl = currentLabel->GetControl();
596 auto currentDepend = currentLabel->GetDepend();
597 GateRef newGate = GetCircuit()->NewGate(circuit_->StoreModuleVar(), MachineType::I64,
598 { currentControl, currentDepend, jsFunc, index, value }, GateType::TaggedValue());
599 currentLabel->SetControl(newGate);
600 currentLabel->SetDepend(newGate);
601 return newGate;
602 }
603
LdLocalModuleVar(GateRef jsFunc,GateRef index)604 GateRef CircuitBuilder::LdLocalModuleVar(GateRef jsFunc, GateRef index)
605 {
606 auto currentLabel = env_->GetCurrentLabel();
607 auto currentControl = currentLabel->GetControl();
608 auto currentDepend = currentLabel->GetDepend();
609 GateRef newGate = GetCircuit()->NewGate(circuit_->LdLocalModuleVar(), MachineType::I64,
610 { currentControl, currentDepend, jsFunc, index}, GateType::TaggedValue());
611 currentLabel->SetControl(newGate);
612 currentLabel->SetDepend(newGate);
613 return newGate;
614 }
615
LdExternalModuleVar(GateRef jsFunc,GateRef index)616 GateRef CircuitBuilder::LdExternalModuleVar(GateRef jsFunc, GateRef index)
617 {
618 auto currentLabel = env_->GetCurrentLabel();
619 auto currentControl = currentLabel->GetControl();
620 auto currentDepend = currentLabel->GetDepend();
621 GateRef newGate = GetCircuit()->NewGate(circuit_->LdExternalModuleVar(), MachineType::I64,
622 {currentControl, currentDepend, jsFunc, index}, GateType::TaggedValue());
623 currentLabel->SetControl(newGate);
624 currentLabel->SetDepend(newGate);
625 return newGate;
626 }
627
BuiltinConstructor(BuiltinsStubCSigns::ID id,GateRef gate)628 GateRef CircuitBuilder::BuiltinConstructor(BuiltinsStubCSigns::ID id, GateRef gate)
629 {
630 auto currentLabel = env_->GetCurrentLabel();
631 auto currentControl = currentLabel->GetControl();
632 auto currentDepend = currentLabel->GetDepend();
633 GateRef newGate = Circuit::NullGate();
634 switch (id) {
635 case BuiltinsStubCSigns::ID::ArrayConstructor: {
636 if (acc_.GetNumValueIn(gate) == 1) {
637 newGate = GetCircuit()->NewGate(circuit_->ArrayConstructor(1), MachineType::I64,
638 { currentControl, currentDepend, acc_.GetValueIn(gate, 0)},
639 GateType::TaggedValue());
640 } else {
641 ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: num value in
642 newGate = GetCircuit()->NewGate(circuit_->ArrayConstructor(2), MachineType::I64,
643 { currentControl, currentDepend, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1)},
644 GateType::TaggedValue());
645 }
646 break;
647 }
648 case BuiltinsStubCSigns::ID::ObjectConstructor: {
649 if (acc_.GetNumValueIn(gate) == 1) {
650 newGate = GetCircuit()->NewGate(circuit_->ObjectConstructor(1), MachineType::I64,
651 { currentControl, currentDepend, acc_.GetValueIn(gate, 0)},
652 GateType::TaggedValue());
653 } else {
654 ASSERT(acc_.GetNumValueIn(gate) >= 2); // 2: num value in
655 newGate = GetCircuit()->NewGate(circuit_->ObjectConstructor(2), MachineType::I64,
656 { currentControl, currentDepend, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1)},
657 GateType::TaggedValue());
658 }
659 break;
660 }
661 case BuiltinsStubCSigns::ID::BooleanConstructor: {
662 if (acc_.GetNumValueIn(gate) == 1) {
663 newGate = GetCircuit()->NewGate(circuit_->BooleanConstructor(1), MachineType::I64,
664 { currentControl, currentDepend, acc_.GetValueIn(gate, 0)},
665 GateType::TaggedValue());
666 } else {
667 ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: num value in
668 newGate = GetCircuit()->NewGate(circuit_->BooleanConstructor(2), MachineType::I64,
669 { currentControl, currentDepend, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1)},
670 GateType::TaggedValue());
671 }
672 break;
673 }
674 case BuiltinsStubCSigns::ID::Float32ArrayConstructor: {
675 if (acc_.GetNumValueIn(gate) == 1) {
676 newGate = Float32ArrayConstructor(gate, { acc_.GetValueIn(gate, 0)});
677 } else {
678 ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: num value in
679 newGate = Float32ArrayConstructor(gate, { acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1)});
680 }
681 break;
682 }
683 default:
684 LOG_ECMA(FATAL) << "this branch is unreachable";
685 UNREACHABLE();
686 break;
687 }
688 currentLabel->SetControl(newGate);
689 currentLabel->SetDepend(newGate);
690 return newGate;
691 }
692
SetExtensibleToBitfield(GateRef glue,GateRef obj,bool isExtensible)693 void CircuitBuilder::SetExtensibleToBitfield(GateRef glue, GateRef obj, bool isExtensible)
694 {
695 GateRef jsHclass = LoadHClass(glue, obj);
696 GateRef bitfield = LoadWithoutBarrier(VariableType::INT32(), jsHclass, IntPtr(JSHClass::BIT_FIELD_OFFSET));
697 GateRef boolVal = Boolean(isExtensible);
698 GateRef boolToInt32 = ZExtInt1ToInt32(boolVal);
699 GateRef encodeValue = Int32LSL(boolToInt32, Int32(JSHClass::ExtensibleBit::START_BIT));
700 GateRef mask = Int32(((1LU << JSHClass::ExtensibleBit::SIZE) - 1) << JSHClass::ExtensibleBit::START_BIT);
701 bitfield = Int32Or(Int32And(bitfield, Int32Not(mask)), encodeValue);
702 Store(VariableType::INT32(), glue, jsHclass, IntPtr(JSHClass::BIT_FIELD_OFFSET), bitfield);
703 }
704
OrdinaryHasInstance(GateRef obj,GateRef target)705 GateRef CircuitBuilder::OrdinaryHasInstance(GateRef obj, GateRef target)
706 {
707 auto currentLabel = env_->GetCurrentLabel();
708 auto currentControl = currentLabel->GetControl();
709 auto currentDepend = currentLabel->GetDepend();
710 GateRef frameState = acc_.FindNearestFrameState(currentDepend);
711 auto ret = GetCircuit()->NewGate(circuit_->OrdinaryHasInstance(),
712 MachineType::I64,
713 {currentControl, currentDepend, obj, target, frameState},
714 GateType::TaggedNPointer());
715 acc_.ReplaceInAfterInsert(currentControl, currentDepend, ret);
716 currentLabel->SetControl(ret);
717 currentLabel->SetDepend(ret);
718 return ret;
719 }
720
MigrateArrayWithKind(GateRef receiver,GateRef oldElementsKind,GateRef newElementsKind)721 GateRef CircuitBuilder::MigrateArrayWithKind(GateRef receiver, GateRef oldElementsKind,
722 GateRef newElementsKind)
723 {
724 auto currentLabel = env_->GetCurrentLabel();
725 auto currentControl = currentLabel->GetControl();
726 auto currentDepend = currentLabel->GetDepend();
727 GateRef newGate = GetCircuit()->NewGate(circuit_->MigrateArrayWithKind(), MachineType::I64,
728 { currentControl, currentDepend, receiver, oldElementsKind,
729 newElementsKind },
730 GateType::TaggedValue());
731 currentLabel->SetControl(newGate);
732 currentLabel->SetDepend(newGate);
733 return newGate;
734 }
735
736 // left and right both utf-8 or utf-16 and both linestring can be concat.
CanBeConcat(GateRef glue,GateRef leftString,GateRef rightString,GateRef isValidOpt)737 GateRef CircuitBuilder::CanBeConcat(GateRef glue, GateRef leftString, GateRef rightString, GateRef isValidOpt)
738 {
739 return LogicAndBuilder(env_).And(isValidOpt).And(IsLineString(glue, leftString))
740 .And(IsLineString(glue, rightString)).Done();
741 }
742
743 // left and right both utf-8 or utf-16 and right is linestring can back store.
CanBackStore(GateRef glue,GateRef rightString,GateRef isValidOpt)744 GateRef CircuitBuilder::CanBackStore(GateRef glue, GateRef rightString, GateRef isValidOpt)
745 {
746 return LogicAndBuilder(env_).And(isValidOpt).And(IsLineString(glue, rightString)).Done();
747 }
748
NumberToString(GateRef number)749 GateRef CircuitBuilder::NumberToString(GateRef number)
750 {
751 auto currentLabel = env_->GetCurrentLabel();
752 auto currentControl = currentLabel->GetControl();
753 auto currentDepend = currentLabel->GetDepend();
754 GateRef newGate = GetCircuit()->NewGate(circuit_->NumberToString(), MachineType::I64,
755 { currentControl, currentDepend, number }, GateType::StringType());
756 currentLabel->SetControl(newGate);
757 currentLabel->SetDepend(newGate);
758 return newGate;
759 }
760 }
761