• 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/post_schedule.h"
17 
18 
19 #include "ecmascript/compiler/circuit_builder-inl.h"
20 
21 namespace panda::ecmascript::kungfu {
Run(ControlFlowGraph & cfg)22 void PostSchedule::Run(ControlFlowGraph &cfg)
23 {
24     GenerateExtraBB(cfg);
25 
26     if (IsLogEnabled()) {
27         LOG_COMPILER(INFO) << "";
28         LOG_COMPILER(INFO) << "\033[34m"
29                            << "===================="
30                            << " After post schedule "
31                            << "[" << GetMethodName() << "]"
32                            << "===================="
33                            << "\033[0m";
34         PrintGraph("Build extra basic block for scheduled gates", cfg);
35         LOG_COMPILER(INFO) << "\033[34m" << "========================= End ==========================" << "\033[0m";
36     }
37 }
38 
GenerateExtraBB(ControlFlowGraph & cfg)39 void PostSchedule::GenerateExtraBB(ControlFlowGraph &cfg)
40 {
41     size_t bbNum = cfg.size();
42     size_t bbIdx = 0;
43     while (bbIdx < bbNum) {
44         const std::vector<GateRef>& bb = cfg.at(bbIdx);
45         size_t instNum = bb.size();
46         size_t instIdx = 0;
47         while (instIdx < instNum) {
48             const std::vector<GateRef>& currentBB = cfg.at(bbIdx);
49             GateRef current = currentBB[instIdx];
50             OpCode opcode = acc_.GetOpCode(current);
51             bool needRetraverse = false;
52             switch (opcode) {
53                 case OpCode::HEAP_ALLOC: {
54                     needRetraverse = VisitHeapAlloc(current, cfg, bbIdx, instIdx);
55                     break;
56                 }
57                 case OpCode::STORE: {
58                     needRetraverse = VisitStore(current, cfg, bbIdx, instIdx);
59                     break;
60                 }
61                 default: {
62                     break;
63                 }
64             }
65             const std::vector<GateRef>& refreshedBB = cfg.at(bbIdx);
66             instNum = refreshedBB.size();
67             instIdx = needRetraverse ? 0 : (instIdx + 1);
68         }
69         bbNum = cfg.size();
70         bbIdx++;
71     }
72 }
73 
VisitHeapAlloc(GateRef gate,ControlFlowGraph & cfg,size_t bbIdx,size_t instIdx)74 bool PostSchedule::VisitHeapAlloc(GateRef gate, ControlFlowGraph &cfg, size_t bbIdx, size_t instIdx)
75 {
76     int64_t flag = static_cast<int64_t>(acc_.TryGetValue(gate));
77     ASSERT(flag == RegionSpaceFlag::IN_YOUNG_SPACE ||
78            flag == RegionSpaceFlag::IN_SHARED_OLD_SPACE ||
79            flag == RegionSpaceFlag::IN_SHARED_NON_MOVABLE ||
80            flag == RegionSpaceFlag::IN_OLD_SPACE);
81     std::vector<GateRef> currentBBGates;
82     std::vector<GateRef> successBBGates;
83     std::vector<GateRef> failBBGates;
84     std::vector<GateRef> endBBGates;
85     if (flag == RegionSpaceFlag::IN_OLD_SPACE) {
86         LoweringHeapAllocate(gate, currentBBGates, successBBGates, failBBGates, endBBGates, flag);
87         ReplaceGateDirectly(currentBBGates, cfg, bbIdx, instIdx);
88         return false;
89     } else {
90         LoweringHeapAllocAndPrepareScheduleGate(gate, currentBBGates, successBBGates, failBBGates, endBBGates, flag);
91     }
92 #ifdef ARK_ASAN_ON
93     ReplaceGateDirectly(currentBBGates, cfg, bbIdx, instIdx);
94     return false;
95 #else
96     ReplaceBBState(cfg, bbIdx, currentBBGates, endBBGates);
97     ScheduleEndBB(endBBGates, cfg, bbIdx, instIdx);
98     ScheduleNewBB(successBBGates, cfg, bbIdx);
99     ScheduleNewBB(failBBGates, cfg, bbIdx);
100     ScheduleCurrentBB(currentBBGates, cfg, bbIdx, instIdx);
101     return true;
102 #endif
103 }
104 
ReplaceGateDirectly(std::vector<GateRef> & gates,ControlFlowGraph & cfg,size_t bbIdx,size_t instIdx)105 void PostSchedule::ReplaceGateDirectly(std::vector<GateRef> &gates, ControlFlowGraph &cfg, size_t bbIdx, size_t instIdx)
106 {
107     std::vector<GateRef>& bb = cfg.at(bbIdx);
108     bb.insert(bb.begin() + instIdx, gates.begin(), gates.end());
109     bb.erase(bb.begin() + instIdx + gates.size());
110 }
111 
ScheduleEndBB(std::vector<GateRef> & gates,ControlFlowGraph & cfg,size_t bbIdx,size_t instIdx)112 void PostSchedule::ScheduleEndBB(std::vector<GateRef> &gates, ControlFlowGraph &cfg, size_t bbIdx, size_t instIdx)
113 {
114     std::vector<GateRef>& bb = cfg.at(bbIdx);
115     if (instIdx > 0) {
116         gates.insert(gates.begin() + 1, bb.begin(), bb.begin() + instIdx);  // 1: after state gate
117     }
118     cfg.insert(cfg.begin() + bbIdx + 1, std::move(gates));  // 1: after current bb
119 }
120 
ScheduleNewBB(std::vector<GateRef> & gates,ControlFlowGraph & cfg,size_t bbIdx)121 void PostSchedule::ScheduleNewBB(std::vector<GateRef> &gates, ControlFlowGraph &cfg, size_t bbIdx)
122 {
123     if (!gates.empty()) {
124         cfg.insert(cfg.begin() + bbIdx + 1, std::move(gates));
125     }
126 }
127 
ScheduleCurrentBB(const std::vector<GateRef> & gates,ControlFlowGraph & cfg,size_t bbIdx,size_t instIdx)128 void PostSchedule::ScheduleCurrentBB(const std::vector<GateRef> &gates, ControlFlowGraph &cfg, size_t bbIdx,
129                                      size_t instIdx)
130 {
131     std::vector<GateRef>& bb = cfg.at(bbIdx);
132     if (instIdx == 0) {
133         bb.erase(bb.begin());
134     } else {
135         bb.erase(bb.begin(), bb.begin() + instIdx + 1);  // 1: include current gate
136     }
137     bb.insert(bb.begin(), gates.begin(), gates.end());
138 }
139 
PrepareToScheduleNewGate(GateRef gate,std::vector<GateRef> & gates)140 void PostSchedule::PrepareToScheduleNewGate(GateRef gate, std::vector<GateRef> &gates)
141 {
142     gates.emplace_back(gate);
143 }
144 
ReplaceBBState(ControlFlowGraph & cfg,size_t bbIdx,std::vector<GateRef> & currentBBGates,std::vector<GateRef> & endBBGates)145 void PostSchedule::ReplaceBBState(ControlFlowGraph &cfg, size_t bbIdx, std::vector<GateRef> &currentBBGates,
146                                   std::vector<GateRef> &endBBGates)
147 {
148     GateRef floatBranch = currentBBGates[0];
149     ASSERT(acc_.GetOpCode(floatBranch) == OpCode::IF_BRANCH);
150     GateRef endBBState = endBBGates[0];
151     ASSERT(acc_.GetOpCode(endBBState) == OpCode::MERGE);
152     std::vector<GateRef>& bb = cfg.at(bbIdx);
153     GateRef currentBBState = bb[0];
154     ASSERT(acc_.IsState(currentBBState));
155 
156     OpCode opcode = acc_.GetOpCode(currentBBState);
157     switch (opcode) {
158         case OpCode::DEOPT_CHECK:
159         case OpCode::RETURN:
160         case OpCode::RETURN_VOID:
161         case OpCode::IF_BRANCH:
162         case OpCode::SWITCH_BRANCH: {
163             GateRef stateIn = acc_.GetState(currentBBState, 0);
164             acc_.ReplaceStateIn(floatBranch, stateIn);
165             acc_.ReplaceStateIn(currentBBState, endBBState);
166             break;
167         }
168         case OpCode::STATE_ENTRY:
169         case OpCode::ORDINARY_BLOCK:
170         case OpCode::IF_TRUE:
171         case OpCode::IF_FALSE:
172         case OpCode::SWITCH_CASE:
173         case OpCode::DEFAULT_CASE:
174         case OpCode::MERGE:
175         case OpCode::LOOP_BEGIN:
176         case OpCode::LOOP_BACK: {
177             acc_.ReplaceControlGate(currentBBState, endBBState);
178             acc_.ReplaceStateIn(floatBranch, currentBBState);
179             currentBBGates.insert(currentBBGates.begin(), currentBBState);
180             bb[0] = builder_.Nop();
181             break;
182         }
183         default: {
184             LOG_ECMA(FATAL) << "this branch is unreachable with opcode:" << opcode;
185             UNREACHABLE();
186         }
187     }
188 }
189 
LoweringHeapAllocAndPrepareScheduleGate(GateRef gate,std::vector<GateRef> & currentBBGates,std::vector<GateRef> & successBBGates,std::vector<GateRef> & failBBGates,std::vector<GateRef> & endBBGates,int64_t flag)190 void PostSchedule::LoweringHeapAllocAndPrepareScheduleGate(GateRef gate,
191                                                            std::vector<GateRef> &currentBBGates,
192                                                            std::vector<GateRef> &successBBGates,
193                                                            std::vector<GateRef> &failBBGates,
194                                                            std::vector<GateRef> &endBBGates,
195                                                            [[maybe_unused]] int64_t flag)
196 {
197 #ifdef ARK_ASAN_ON
198     LoweringHeapAllocate(gate, currentBBGates, successBBGates, failBBGates, endBBGates, flag);
199 #else
200     Environment env(gate, circuit_, &builder_);
201     Label exit(&builder_);
202     GateRef glue = acc_.GetValueIn(gate, 0);
203     GateRef size = acc_.GetValueIn(gate, 1);
204     GateRef hole = circuit_->GetConstantGateWithoutCache(
205         MachineType::I64, JSTaggedValue::VALUE_HOLE, GateType::TaggedValue());
206     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), hole);
207     Label success(&builder_);
208     Label callRuntime(&builder_);
209     size_t topOffset;
210     size_t endOffset;
211     if (flag == RegionSpaceFlag::IN_SHARED_OLD_SPACE) {
212         topOffset = JSThread::GlueData::GetSOldSpaceAllocationTopAddressOffset(false);
213         endOffset = JSThread::GlueData::GetSOldSpaceAllocationEndAddressOffset(false);
214     } else if (flag == RegionSpaceFlag::IN_SHARED_NON_MOVABLE) {
215         topOffset = JSThread::GlueData::GetSNonMovableSpaceAllocationTopAddressOffset(false);
216         endOffset = JSThread::GlueData::GetSNonMovableSpaceAllocationEndAddressOffset(false);
217     } else {
218         ASSERT(flag == RegionSpaceFlag::IN_YOUNG_SPACE);
219         topOffset = JSThread::GlueData::GetNewSpaceAllocationTopAddressOffset(false);
220         endOffset = JSThread::GlueData::GetNewSpaceAllocationEndAddressOffset(false);
221     }
222     GateRef topAddrOffset = circuit_->GetConstantGateWithoutCache(MachineType::I64, topOffset, GateType::NJSValue());
223     GateRef endAddrOffset = circuit_->GetConstantGateWithoutCache(MachineType::I64, endOffset, GateType::NJSValue());
224     GateRef topAddrAddr = builder_.PtrAdd(glue, topAddrOffset);
225     GateRef endAddrAddr = builder_.PtrAdd(glue, endAddrOffset);
226     GateRef topAddress = builder_.Load(VariableType::NATIVE_POINTER(), topAddrAddr);
227     GateRef endAddress = builder_.Load(VariableType::NATIVE_POINTER(), endAddrAddr);
228     GateRef addrOffset = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
229     GateRef rawTopAddr = builder_.PtrAdd(topAddress, addrOffset);
230     GateRef rawEndAddr = builder_.PtrAdd(endAddress, addrOffset);
231     GateRef top = builder_.Load(VariableType::JS_POINTER(), rawTopAddr);
232     GateRef end = builder_.Load(VariableType::JS_POINTER(), rawEndAddr);
233 
234     GateRef newTop = builder_.PtrAdd(top, size);
235     GateRef condition = builder_.Int64GreaterThan(newTop, end);
236     Label *currentLabel = env.GetCurrentLabel();
237     BRANCH_CIR(condition, &callRuntime, &success);
238     {
239         GateRef ifBranch = currentLabel->GetControl();
240         PrepareToScheduleNewGate(ifBranch, currentBBGates);
241         PrepareToScheduleNewGate(condition, currentBBGates);
242         PrepareToScheduleNewGate(newTop, currentBBGates);
243         PrepareToScheduleNewGate(end, currentBBGates);
244         PrepareToScheduleNewGate(top, currentBBGates);
245         PrepareToScheduleNewGate(rawEndAddr, currentBBGates);
246         PrepareToScheduleNewGate(rawTopAddr, currentBBGates);
247         PrepareToScheduleNewGate(topAddress, currentBBGates);
248         PrepareToScheduleNewGate(endAddress, currentBBGates);
249         PrepareToScheduleNewGate(addrOffset, currentBBGates);
250         PrepareToScheduleNewGate(topAddrAddr, currentBBGates);
251         PrepareToScheduleNewGate(endAddrAddr, currentBBGates);
252         PrepareToScheduleNewGate(topAddrOffset, currentBBGates);
253         PrepareToScheduleNewGate(endAddrOffset, currentBBGates);
254         PrepareToScheduleNewGate(hole, currentBBGates);
255     }
256     builder_.Bind(&success);
257     {
258         GateRef ifFalse = builder_.GetState();
259         GateRef addr = builder_.PtrAdd(topAddress, addrOffset);
260         builder_.StoreWithoutBarrier(VariableType::NATIVE_POINTER(), addr, newTop);
261         GateRef store = builder_.GetDepend();
262         result = top;
263         builder_.Jump(&exit);
264         {
265             GateRef ordinaryBlock = success.GetControl();
266             PrepareToScheduleNewGate(ordinaryBlock, successBBGates);
267             PrepareToScheduleNewGate(store, successBBGates);
268             PrepareToScheduleNewGate(addr, successBBGates);
269             PrepareToScheduleNewGate(ifFalse, successBBGates);
270         }
271     }
272     builder_.Bind(&callRuntime);
273     {
274         GateRef ifTrue = builder_.GetState();
275         GateRef taggedIntMask = circuit_->GetConstantGateWithoutCache(
276             MachineType::I64, JSTaggedValue::TAG_INT, GateType::NJSValue());
277         GateRef taggedSize = builder_.Int64Or(size, taggedIntMask);
278         GateRef target = Circuit::NullGate();
279         if (flag == RegionSpaceFlag::IN_SHARED_OLD_SPACE) {
280             target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, RTSTUB_ID(AllocateInSOld),
281                                                            GateType::NJSValue());
282         } else if (flag == RegionSpaceFlag::IN_SHARED_NON_MOVABLE) {
283             target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, RTSTUB_ID(AllocateInSNonMovable),
284                                                            GateType::NJSValue());
285         } else {
286             ASSERT(flag == RegionSpaceFlag::IN_YOUNG_SPACE);
287             target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, RTSTUB_ID(AllocateInYoung),
288                                                            GateType::NJSValue());
289         }
290         const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
291         ASSERT(cs->IsRuntimeStub());
292         GateRef reseverdFrameArgs = Circuit::NullGate();
293         GateRef reseverdPc = Circuit::NullGate();
294         std::vector<GateRef> args { taggedSize };
295         // keep same with CircuitBuilder::Call: only when condition is true, we pass the other two args.
296         if (builder_.GetCircuit()->IsOptimizedOrFastJit()) {
297             reseverdFrameArgs = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
298             reseverdPc = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
299             args.push_back(reseverdFrameArgs);
300             args.push_back(reseverdPc);
301         }
302         // here in order to schedule all the intermediate value,
303         // frameargs and pcoffset are solved out from CircuitBuilder::Call,
304         // so hirGate must be NullGate to prevent duplicated operation.
305         GateRef slowResult = builder_.Call(cs, glue, target, builder_.GetDepend(),
306                                            args, Circuit::NullGate(), "Heap alloc");
307         result = slowResult;
308         builder_.Jump(&exit);
309         {
310             GateRef ordinaryBlock = callRuntime.GetControl();
311             PrepareToScheduleNewGate(ordinaryBlock, failBBGates);
312             PrepareToScheduleNewGate(slowResult, failBBGates);
313             PrepareToScheduleNewGate(target, failBBGates);
314             PrepareToScheduleNewGate(taggedSize, failBBGates);
315             if (builder_.GetCircuit()->IsOptimizedOrFastJit()) {
316                 PrepareToScheduleNewGate(reseverdFrameArgs, failBBGates);
317                 PrepareToScheduleNewGate(reseverdPc, failBBGates);
318             }
319             PrepareToScheduleNewGate(taggedIntMask, failBBGates);
320             PrepareToScheduleNewGate(ifTrue, failBBGates);
321         }
322     }
323     builder_.Bind(&exit);
324     {
325         GateRef merge = builder_.GetState();
326         GateRef phi = *result;
327         PrepareToScheduleNewGate(merge, endBBGates);
328         PrepareToScheduleNewGate(phi, endBBGates);
329     }
330     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
331 #endif
332 }
333 
LoweringHeapAllocate(GateRef gate,std::vector<GateRef> & currentBBGates,std::vector<GateRef> & successBBGates,std::vector<GateRef> & failBBGates,std::vector<GateRef> & endBBGates,int64_t flag)334 void PostSchedule::LoweringHeapAllocate(GateRef gate,
335                                         std::vector<GateRef> &currentBBGates,
336                                         std::vector<GateRef> &successBBGates,
337                                         std::vector<GateRef> &failBBGates,
338                                         std::vector<GateRef> &endBBGates,
339                                         int64_t flag)
340 {
341     Environment env(gate, circuit_, &builder_);
342     (void)successBBGates;
343     (void)failBBGates;
344     (void)endBBGates;
345     GateRef glue = acc_.GetValueIn(gate, 0);
346     GateRef size = acc_.GetValueIn(gate, 1);
347     GateRef taggedIntMask = circuit_->GetConstantGateWithoutCache(
348         MachineType::I64, JSTaggedValue::TAG_INT, GateType::NJSValue());
349     GateRef taggedSize = builder_.Int64Or(size, taggedIntMask);
350     auto id = RTSTUB_ID(AllocateInYoung);
351     if (flag == RegionSpaceFlag::IN_SHARED_OLD_SPACE) {
352         id = RTSTUB_ID(AllocateInSOld);
353     } else if (flag == RegionSpaceFlag::IN_SHARED_NON_MOVABLE) {
354         id = RTSTUB_ID(AllocateInSNonMovable);
355     } else if (flag == RegionSpaceFlag::IN_OLD_SPACE) {
356         id = RTSTUB_ID(AllocateInOld);
357     } else {
358         ASSERT(flag == RegionSpaceFlag::IN_YOUNG_SPACE);
359     }
360     GateRef target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, id, GateType::NJSValue());
361     const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
362     ASSERT(cs->IsRuntimeStub());
363     GateRef reseverdFrameArgs = Circuit::NullGate();
364     GateRef reseverdPc = Circuit::NullGate();
365     std::vector<GateRef> args { taggedSize };
366     // keep same with CircuitBuilder::Call: only when condition is true, we pass the other two args.
367     if (builder_.GetCircuit()->IsOptimizedOrFastJit()) {
368         reseverdFrameArgs = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
369         reseverdPc = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
370         args.push_back(reseverdFrameArgs);
371         args.push_back(reseverdPc);
372     }
373     // here in order to schedule all the intermediate value,
374     // frameargs and pcoffset are solved out from CircuitBuilder::Call,
375     // so hirGate must be NullGate to prevent duplicated operation.
376     GateRef result = builder_.Call(cs, glue, target, builder_.GetDepend(), args, Circuit::NullGate(), "Heap alloc");
377     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
378 
379     // Must keep the order of value-in/depend-in
380     PrepareToScheduleNewGate(result, currentBBGates);
381     PrepareToScheduleNewGate(target, currentBBGates);
382     PrepareToScheduleNewGate(taggedSize, currentBBGates);
383     if (builder_.GetCircuit()->IsOptimizedOrFastJit()) {
384         PrepareToScheduleNewGate(reseverdFrameArgs, currentBBGates);
385         PrepareToScheduleNewGate(reseverdPc, currentBBGates);
386     }
387     PrepareToScheduleNewGate(taggedIntMask, currentBBGates);
388     return;
389 }
390 
VisitStore(GateRef gate,ControlFlowGraph & cfg,size_t bbIdx,size_t instIdx)391 bool PostSchedule::VisitStore(GateRef gate, ControlFlowGraph &cfg, size_t bbIdx, size_t instIdx)
392 {
393     std::vector<GateRef> currentBBGates;
394     std::vector<GateRef> barrierBBGates;
395     std::vector<GateRef> endBBGates;
396     MemoryAttribute::Barrier kind = GetWriteBarrierKind(gate);
397     switch (kind) {
398         case MemoryAttribute::Barrier::UNKNOWN_BARRIER: {
399             LoweringStoreUnknownBarrierAndPrepareScheduleGate(gate, currentBBGates, barrierBBGates, endBBGates);
400             ReplaceBBState(cfg, bbIdx, currentBBGates, endBBGates);
401             ScheduleEndBB(endBBGates, cfg, bbIdx, instIdx);
402             ScheduleNewBB(barrierBBGates, cfg, bbIdx);
403             ScheduleCurrentBB(currentBBGates, cfg, bbIdx, instIdx);
404             return true;
405         }
406         case MemoryAttribute::Barrier::NEED_BARRIER: {
407             LoweringStoreWithBarrierAndPrepareScheduleGate(gate, currentBBGates);
408             ReplaceGateDirectly(currentBBGates, cfg, bbIdx, instIdx);
409             return false;
410         }
411         case MemoryAttribute::Barrier::NO_BARRIER: {
412             LoweringStoreNoBarrierAndPrepareScheduleGate(gate, currentBBGates);
413             ReplaceGateDirectly(currentBBGates, cfg, bbIdx, instIdx);
414             return false;
415         }
416         default: {
417             UNREACHABLE();
418             return false;
419         }
420     }
421     return false;
422 }
423 
GetWriteBarrierKind(GateRef gate)424 MemoryAttribute::Barrier PostSchedule::GetWriteBarrierKind(GateRef gate)
425 {
426     MemoryAttribute mAttr = acc_.GetMemoryAttribute(gate);
427     if (!acc_.IsGCRelated(gate)) {
428         return MemoryAttribute::Barrier::NO_BARRIER;
429     }
430     return mAttr.GetBarrier();
431 }
432 
SelectBarrier(MemoryAttribute::ShareFlag share,const CallSignature * & cs,std::string_view & comment)433 int PostSchedule::SelectBarrier(MemoryAttribute::ShareFlag share, const CallSignature*& cs, std::string_view& comment)
434 {
435     int index = 0;
436     switch (share) {
437         case MemoryAttribute::UNKNOWN:
438             if (fastBarrier_) {
439                 index = RuntimeStubCSigns::ID_ASMFastWriteBarrier;
440                 cs = RuntimeStubCSigns::Get(index);
441                 comment = "asm store barrier\0";
442             } else {
443                 index = CommonStubCSigns::SetValueWithBarrier;
444                 cs = CommonStubCSigns::Get(index);
445                 comment = "store barrier\0";
446             }
447             break;
448         case MemoryAttribute::SHARED:
449             index = CommonStubCSigns::SetSValueWithBarrier;
450             cs = CommonStubCSigns::Get(index);
451             comment = "store share barrier\0";
452             break;
453         case MemoryAttribute::NON_SHARE:
454             index = CommonStubCSigns::SetNonSValueWithBarrier;
455             cs = CommonStubCSigns::Get(index);
456             comment = "store not share barrier\0";
457             break;
458         default:
459             UNREACHABLE();
460     }
461     return index;
462 }
463 
LoweringStoreNoBarrierAndPrepareScheduleGate(GateRef gate,std::vector<GateRef> & currentBBGates)464 void PostSchedule::LoweringStoreNoBarrierAndPrepareScheduleGate(GateRef gate, std::vector<GateRef> &currentBBGates)
465 {
466     Environment env(gate, circuit_, &builder_);
467 
468     GateRef base = acc_.GetValueIn(gate, 1);   // 1: object
469     GateRef offset = acc_.GetValueIn(gate, 2); // 2: offset
470     GateRef value = acc_.GetValueIn(gate, 3);  // 3: value
471     GateRef addr = builder_.PtrAdd(base, offset);
472     VariableType type = VariableType(acc_.GetMachineType(gate), acc_.GetGateType(gate));
473     builder_.StoreWithoutBarrier(type, addr, value, acc_.GetMemoryAttribute(gate));
474     GateRef store = builder_.GetDepend();
475     {
476         PrepareToScheduleNewGate(store, currentBBGates);
477         PrepareToScheduleNewGate(addr, currentBBGates);
478     }
479     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
480 }
481 
GetShareKind(panda::ecmascript::kungfu::GateRef gate)482 MemoryAttribute::ShareFlag PostSchedule::GetShareKind(panda::ecmascript::kungfu::GateRef gate)
483 {
484     MemoryAttribute mAttr = acc_.GetMemoryAttribute(gate);
485     return mAttr.GetShare();
486 }
487 
LoweringStoreWithBarrierAndPrepareScheduleGate(GateRef gate,std::vector<GateRef> & currentBBGates)488 void PostSchedule::LoweringStoreWithBarrierAndPrepareScheduleGate(GateRef gate, std::vector<GateRef> &currentBBGates)
489 {
490     Environment env(gate, circuit_, &builder_);
491 
492     GateRef glue = acc_.GetValueIn(gate, 0);
493     GateRef base = acc_.GetValueIn(gate, 1);   // 1: object
494     GateRef offset = acc_.GetValueIn(gate, 2); // 2: offset
495     GateRef value = acc_.GetValueIn(gate, 3);  // 3: value
496     GateRef addr = builder_.PtrAdd(base, offset);
497     VariableType type = VariableType(acc_.GetMachineType(gate), acc_.GetGateType(gate));
498     builder_.StoreWithoutBarrier(type, addr, value, acc_.GetMemoryAttribute(gate));
499     GateRef store = builder_.GetDepend();
500     MemoryAttribute::ShareFlag share = GetShareKind(gate);
501     std::string_view comment;
502     int index;
503     const CallSignature* cs = nullptr;
504     index = SelectBarrier(share, cs, comment);
505     ASSERT(cs && (cs->IsCommonStub() || cs->IsASMCallBarrierStub()) && "Invalid call signature for barrier");
506     GateRef target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, index, GateType::NJSValue());
507     GateRef reseverdFrameArgs = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
508     GateRef reseverdPc = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
509     GateRef storeBarrier = builder_.Call(cs, glue, target, builder_.GetDepend(),
510                                          {glue, base, offset, value, reseverdFrameArgs, reseverdPc},
511                                          Circuit::NullGate(), comment.data());
512     {
513         PrepareToScheduleNewGate(storeBarrier, currentBBGates);
514         PrepareToScheduleNewGate(reseverdPc, currentBBGates);
515         PrepareToScheduleNewGate(reseverdFrameArgs, currentBBGates);
516         PrepareToScheduleNewGate(target, currentBBGates);
517         PrepareToScheduleNewGate(store, currentBBGates);
518         PrepareToScheduleNewGate(addr, currentBBGates);
519     }
520     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
521 }
522 
LoweringStoreUnknownBarrierAndPrepareScheduleGate(GateRef gate,std::vector<GateRef> & currentBBGates,std::vector<GateRef> & barrierBBGates,std::vector<GateRef> & endBBGates)523 void PostSchedule::LoweringStoreUnknownBarrierAndPrepareScheduleGate(GateRef gate,
524                                                                      std::vector<GateRef> &currentBBGates,
525                                                                      std::vector<GateRef> &barrierBBGates,
526                                                                      std::vector<GateRef> &endBBGates)
527 {
528     Environment env(gate, circuit_, &builder_);
529 
530     GateRef glue = acc_.GetValueIn(gate, 0);
531     GateRef base = acc_.GetValueIn(gate, 1);   // 1: object
532     GateRef offset = acc_.GetValueIn(gate, 2); // 2: offset
533     GateRef value = acc_.GetValueIn(gate, 3);  // 3: value
534     GateRef addr = builder_.PtrAdd(base, offset);
535     VariableType type = VariableType(acc_.GetMachineType(gate), acc_.GetGateType(gate));
536     builder_.StoreWithoutBarrier(type, addr, value, acc_.GetMemoryAttribute(gate));
537     GateRef store = builder_.GetDepend();
538 
539     GateRef intVal = builder_.ChangeTaggedPointerToInt64(value);
540     GateRef objMask = circuit_->GetConstantGateWithoutCache(
541         MachineType::I64, JSTaggedValue::TAG_HEAPOBJECT_MASK, GateType::NJSValue());
542     GateRef masked = builder_.Int64And(intVal, objMask, GateType::Empty(), "checkHeapObject");
543     GateRef falseVal = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
544     GateRef condition = builder_.Equal(masked, falseVal, "checkHeapObject");
545     Label exit(&builder_);
546     Label isHeapObject(&builder_);
547     Label *currentLabel = env.GetCurrentLabel();
548     BRANCH_CIR(condition, &isHeapObject, &exit);
549     {
550         GateRef ifBranch = currentLabel->GetControl();
551         PrepareToScheduleNewGate(ifBranch, currentBBGates);
552         PrepareToScheduleNewGate(condition, currentBBGates);
553         PrepareToScheduleNewGate(falseVal, currentBBGates);
554         PrepareToScheduleNewGate(masked, currentBBGates);
555         PrepareToScheduleNewGate(intVal, currentBBGates);
556         PrepareToScheduleNewGate(objMask, currentBBGates);
557         PrepareToScheduleNewGate(store, currentBBGates);
558         PrepareToScheduleNewGate(addr, currentBBGates);
559     }
560     GateRef ifTrue = isHeapObject.GetControl();
561     GateRef ifFalse = exit.GetControl();
562     builder_.Bind(&isHeapObject);
563     {
564         MemoryAttribute::ShareFlag share = GetShareKind(gate);
565         std::string_view comment;
566         int index;
567         const CallSignature* cs = nullptr;
568         index = SelectBarrier(share, cs, comment);
569         ASSERT(cs && (cs->IsCommonStub() || cs->IsASMCallBarrierStub()) && "Invalid call signature for barrier");
570         GateRef target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, index, GateType::NJSValue());
571         GateRef reseverdFrameArgs = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
572         GateRef reseverdPc = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
573 #ifndef NDEBUG
574         GateRef verifyTarget = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, CommonStubCSigns::VerifyBarrier,
575                                                                      GateType::NJSValue());
576         const CallSignature* verifyBarrierCs = CommonStubCSigns::Get(CommonStubCSigns::VerifyBarrier);
577         GateRef verifyBarrier = builder_.Call(verifyBarrierCs, glue, verifyTarget, builder_.GetDepend(),
578                                               {glue, base, offset, value, reseverdFrameArgs, reseverdPc},
579                                               Circuit::NullGate(), "verify barrier");
580 #endif
581         GateRef storeBarrier = builder_.Call(cs, glue, target, builder_.GetDepend(),
582                                              { glue, base, offset, value, reseverdFrameArgs, reseverdPc },
583                                              Circuit::NullGate(), comment.data());
584         builder_.Jump(&exit);
585         {
586             GateRef ordinaryBlock = isHeapObject.GetControl();
587             PrepareToScheduleNewGate(ordinaryBlock, barrierBBGates);
588             PrepareToScheduleNewGate(storeBarrier, barrierBBGates);
589 #ifndef NDEBUG
590             PrepareToScheduleNewGate(verifyBarrier, barrierBBGates);
591 #endif
592             PrepareToScheduleNewGate(reseverdFrameArgs, barrierBBGates);
593             PrepareToScheduleNewGate(reseverdPc, barrierBBGates);
594             PrepareToScheduleNewGate(ifTrue, barrierBBGates);
595         }
596     }
597     builder_.Bind(&exit);
598     {
599         GateRef merge = builder_.GetState();
600         PrepareToScheduleNewGate(merge, endBBGates);
601         PrepareToScheduleNewGate(ifFalse, endBBGates);
602     }
603     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
604 }
605 
PrintGraph(const char * title,ControlFlowGraph & cfg)606 void PostSchedule::PrintGraph(const char* title, ControlFlowGraph &cfg)
607 {
608     LOG_COMPILER(INFO) << "======================== " << title << " ========================";
609     for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) {
610         LOG_COMPILER(INFO) << "B" << bbIdx << ":";
611         const std::vector<GateRef>& bb = cfg.at(bbIdx);
612         for (size_t instIdx = 0; instIdx < bb.size(); instIdx++) {
613             GateRef gate = bb[instIdx];
614             acc_.Print(gate);
615         }
616         LOG_COMPILER(INFO) << "";
617     }
618 }
619 }  // namespace panda::ecmascript::kungfu
620