• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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