• 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 #include "ecmascript/mem/region.h"
21 
22 namespace panda::ecmascript::kungfu {
Run(ControlFlowGraph & cfg)23 void PostSchedule::Run(ControlFlowGraph &cfg)
24 {
25     GenerateExtraBB(cfg);
26 
27     if (IsLogEnabled()) {
28         LOG_COMPILER(INFO) << "";
29         LOG_COMPILER(INFO) << "\033[34m"
30                            << "===================="
31                            << " After post schedule "
32                            << "[" << GetMethodName() << "]"
33                            << "===================="
34                            << "\033[0m";
35         PrintGraph("Build extra basic block for scheduled gates", cfg);
36         LOG_COMPILER(INFO) << "\033[34m" << "========================= End ==========================" << "\033[0m";
37     }
38 }
39 
GenerateExtraBB(ControlFlowGraph & cfg)40 void PostSchedule::GenerateExtraBB(ControlFlowGraph &cfg)
41 {
42     size_t bbNum = cfg.size();
43     size_t bbIdx = 0;
44     while (bbIdx < bbNum) {
45         const std::vector<GateRef>& bb = cfg.at(bbIdx);
46         size_t instNum = bb.size();
47         size_t instIdx = 0;
48         while (instIdx < instNum) {
49             const std::vector<GateRef>& currentBB = cfg.at(bbIdx);
50             GateRef current = currentBB[instIdx];
51             OpCode opcode = acc_.GetOpCode(current);
52             bool needRetraverse = false;
53             switch (opcode) {
54                 case OpCode::HEAP_ALLOC: {
55                     if (isStwCopyStub_) {
56                         needRetraverse = VisitHeapAlloc(current, cfg, bbIdx, instIdx);
57                     } else {
58                         needRetraverse = VisitHeapAllocForCMCGC(current, cfg, bbIdx, instIdx);
59                     }
60 
61                     break;
62                 }
63                 case OpCode::STORE: {
64                     needRetraverse = VisitStore(current, cfg, bbIdx, instIdx);
65                     break;
66                 }
67                 case OpCode::LOAD: {
68                     needRetraverse = VisitLoad(current, cfg, bbIdx, instIdx);
69                     break;
70                 }
71                 case OpCode::LOAD_HCLASS_OPCODE: {
72                     needRetraverse = VisitLoad(current, cfg, bbIdx, instIdx, true);
73                     break;
74                 }
75                 default: {
76                     break;
77                 }
78             }
79             const std::vector<GateRef>& refreshedBB = cfg.at(bbIdx);
80             instNum = refreshedBB.size();
81             instIdx = needRetraverse ? 0 : (instIdx + 1);
82         }
83         bbNum = cfg.size();
84         bbIdx++;
85     }
86 }
87 
VisitHeapAlloc(GateRef gate,ControlFlowGraph & cfg,size_t bbIdx,size_t instIdx)88 bool PostSchedule::VisitHeapAlloc(GateRef gate, ControlFlowGraph &cfg, size_t bbIdx, size_t instIdx)
89 {
90     int64_t flag = static_cast<int64_t>(acc_.TryGetValue(gate));
91     ASSERT(flag == RegionSpaceFlag::IN_YOUNG_SPACE ||
92            flag == RegionSpaceFlag::IN_SHARED_OLD_SPACE ||
93            flag == RegionSpaceFlag::IN_SHARED_NON_MOVABLE ||
94            flag == RegionSpaceFlag::IN_OLD_SPACE);
95     std::vector<GateRef> currentBBGates;
96     std::vector<GateRef> successBBGates;
97     std::vector<GateRef> failBBGates;
98     std::vector<GateRef> endBBGates;
99     if (flag == RegionSpaceFlag::IN_OLD_SPACE) {
100         LoweringHeapAllocate(gate, currentBBGates, successBBGates, failBBGates, endBBGates, flag);
101         ReplaceGateDirectly(currentBBGates, cfg, bbIdx, instIdx);
102         return false;
103     } else {
104         LoweringHeapAllocAndPrepareScheduleGate(gate, currentBBGates, successBBGates, failBBGates, endBBGates, flag);
105     }
106 #if defined(ARK_ASAN_ON)
107     ReplaceGateDirectly(currentBBGates, cfg, bbIdx, instIdx);
108     return false;
109 #else
110     ReplaceBBState(cfg, bbIdx, currentBBGates, endBBGates);
111     ScheduleEndBB(endBBGates, cfg, bbIdx, instIdx);
112     ScheduleNewBB(successBBGates, cfg, bbIdx);
113     ScheduleNewBB(failBBGates, cfg, bbIdx);
114     ScheduleCurrentBB(currentBBGates, cfg, bbIdx, instIdx);
115     return true;
116 #endif
117 }
118 
VisitHeapAllocForCMCGC(GateRef gate,ControlFlowGraph & cfg,size_t bbIdx,size_t instIdx)119 bool PostSchedule::VisitHeapAllocForCMCGC(GateRef gate, ControlFlowGraph &cfg, size_t bbIdx, size_t instIdx)
120 {
121     int64_t flag = static_cast<int64_t>(acc_.TryGetValue(gate));
122     ASSERT(flag == RegionSpaceFlag::IN_YOUNG_SPACE ||
123            flag == RegionSpaceFlag::IN_SHARED_OLD_SPACE ||
124            flag == RegionSpaceFlag::IN_SHARED_NON_MOVABLE ||
125            flag == RegionSpaceFlag::IN_OLD_SPACE);
126     std::vector<GateRef> currentBBGates;
127     std::vector<GateRef> successBBGates;
128     std::vector<GateRef> failBBGates;
129     std::vector<GateRef> endBBGates;
130     if (flag == RegionSpaceFlag::IN_OLD_SPACE ||
131         flag == RegionSpaceFlag::IN_SHARED_OLD_SPACE ||
132         flag == RegionSpaceFlag::IN_SHARED_NON_MOVABLE) {
133         LoweringHeapAllocate(gate, currentBBGates, successBBGates, failBBGates, endBBGates, flag);
134         ReplaceGateDirectly(currentBBGates, cfg, bbIdx, instIdx);
135         return false;
136     } else {
137         LoweringHeapAllocAndPrepareScheduleGateForCMCGC(
138             gate, currentBBGates, successBBGates, failBBGates, endBBGates, flag);
139     }
140 #if defined(ARK_ASAN_ON)
141     ReplaceGateDirectly(currentBBGates, cfg, bbIdx, instIdx);
142     return false;
143 #else
144     ReplaceBBState(cfg, bbIdx, currentBBGates, endBBGates);
145     ScheduleEndBB(endBBGates, cfg, bbIdx, instIdx);
146     ScheduleNewBB(successBBGates, cfg, bbIdx);
147     ScheduleNewBB(failBBGates, cfg, bbIdx);
148     ScheduleCurrentBB(currentBBGates, cfg, bbIdx, instIdx);
149     return true;
150 #endif
151 }
152 
ReplaceGateDirectly(std::vector<GateRef> & gates,ControlFlowGraph & cfg,size_t bbIdx,size_t instIdx)153 void PostSchedule::ReplaceGateDirectly(std::vector<GateRef> &gates, ControlFlowGraph &cfg, size_t bbIdx, size_t instIdx)
154 {
155     std::vector<GateRef>& bb = cfg.at(bbIdx);
156     bb.insert(bb.begin() + instIdx, gates.begin(), gates.end());
157     bb.erase(bb.begin() + instIdx + gates.size());
158 }
159 
ScheduleEndBB(std::vector<GateRef> & gates,ControlFlowGraph & cfg,size_t bbIdx,size_t instIdx)160 void PostSchedule::ScheduleEndBB(std::vector<GateRef> &gates, ControlFlowGraph &cfg, size_t bbIdx, size_t instIdx)
161 {
162     std::vector<GateRef>& bb = cfg.at(bbIdx);
163     if (instIdx > 0) {
164         gates.insert(gates.begin() + 1, bb.begin(), bb.begin() + instIdx);  // 1: after state gate
165     }
166     cfg.insert(cfg.begin() + bbIdx + 1, std::move(gates));  // 1: after current bb
167 }
168 
ScheduleNewBB(std::vector<GateRef> & gates,ControlFlowGraph & cfg,size_t bbIdx)169 void PostSchedule::ScheduleNewBB(std::vector<GateRef> &gates, ControlFlowGraph &cfg, size_t bbIdx)
170 {
171     if (!gates.empty()) {
172         cfg.insert(cfg.begin() + bbIdx + 1, std::move(gates));
173     }
174 }
175 
ScheduleCurrentBB(const std::vector<GateRef> & gates,ControlFlowGraph & cfg,size_t bbIdx,size_t instIdx)176 void PostSchedule::ScheduleCurrentBB(const std::vector<GateRef> &gates, ControlFlowGraph &cfg, size_t bbIdx,
177                                      size_t instIdx)
178 {
179     std::vector<GateRef>& bb = cfg.at(bbIdx);
180     if (instIdx == 0) {
181         bb.erase(bb.begin());
182     } else {
183         bb.erase(bb.begin(), bb.begin() + instIdx + 1);  // 1: include current gate
184     }
185     bb.insert(bb.begin(), gates.begin(), gates.end());
186 }
187 
PrepareToScheduleNewGate(GateRef gate,std::vector<GateRef> & gates)188 void PostSchedule::PrepareToScheduleNewGate(GateRef gate, std::vector<GateRef> &gates)
189 {
190     gates.emplace_back(gate);
191 }
192 
ReplaceBBState(ControlFlowGraph & cfg,size_t bbIdx,std::vector<GateRef> & currentBBGates,std::vector<GateRef> & endBBGates)193 void PostSchedule::ReplaceBBState(ControlFlowGraph &cfg, size_t bbIdx, std::vector<GateRef> &currentBBGates,
194                                   std::vector<GateRef> &endBBGates)
195 {
196     GateRef floatBranch = currentBBGates[0];
197     ASSERT(acc_.GetOpCode(floatBranch) == OpCode::IF_BRANCH);
198     GateRef endBBState = endBBGates[0];
199     ASSERT(acc_.GetOpCode(endBBState) == OpCode::MERGE);
200     std::vector<GateRef>& bb = cfg.at(bbIdx);
201     GateRef currentBBState = bb[0];
202     ASSERT(acc_.IsState(currentBBState));
203 
204     OpCode opcode = acc_.GetOpCode(currentBBState);
205     switch (opcode) {
206         case OpCode::DEOPT_CHECK:
207         case OpCode::RETURN:
208         case OpCode::RETURN_VOID:
209         case OpCode::IF_BRANCH:
210         case OpCode::SWITCH_BRANCH: {
211             GateRef stateIn = acc_.GetState(currentBBState, 0);
212             acc_.ReplaceStateIn(floatBranch, stateIn);
213             acc_.ReplaceStateIn(currentBBState, endBBState);
214             break;
215         }
216         case OpCode::STATE_ENTRY:
217         case OpCode::ORDINARY_BLOCK:
218         case OpCode::IF_TRUE:
219         case OpCode::IF_FALSE:
220         case OpCode::SWITCH_CASE:
221         case OpCode::DEFAULT_CASE:
222         case OpCode::MERGE:
223         case OpCode::LOOP_BEGIN:
224         case OpCode::LOOP_BACK: {
225             acc_.ReplaceControlGate(currentBBState, endBBState);
226             acc_.ReplaceStateIn(floatBranch, currentBBState);
227             currentBBGates.insert(currentBBGates.begin(), currentBBState);
228             bb[0] = builder_.Nop();
229             break;
230         }
231         default: {
232             LOG_ECMA(FATAL) << "this branch is unreachable with opcode:" << opcode;
233             UNREACHABLE();
234         }
235     }
236 }
237 
LoweringHeapAllocAndPrepareScheduleGate(GateRef gate,std::vector<GateRef> & currentBBGates,std::vector<GateRef> & successBBGates,std::vector<GateRef> & failBBGates,std::vector<GateRef> & endBBGates,int64_t flag)238 void PostSchedule::LoweringHeapAllocAndPrepareScheduleGate(GateRef gate,
239                                                            std::vector<GateRef> &currentBBGates,
240                                                            std::vector<GateRef> &successBBGates,
241                                                            std::vector<GateRef> &failBBGates,
242                                                            std::vector<GateRef> &endBBGates,
243                                                            [[maybe_unused]] int64_t flag)
244 {
245 #if defined(ARK_ASAN_ON)
246     LoweringHeapAllocate(gate, currentBBGates, successBBGates, failBBGates, endBBGates, flag);
247 #else
248     Environment env(gate, circuit_, &builder_);
249     Label exit(&builder_);
250     GateRef glue = acc_.GetValueIn(gate, 0);
251     GateRef size = acc_.GetValueIn(gate, 1);
252     GateRef hole = circuit_->GetConstantGateWithoutCache(
253         MachineType::I64, JSTaggedValue::VALUE_HOLE, GateType::TaggedValue());
254     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), hole);
255     Label success(&builder_);
256     Label callRuntime(&builder_);
257 
258     size_t topOffset;
259     size_t endOffset;
260     if (flag == RegionSpaceFlag::IN_SHARED_OLD_SPACE) {
261         topOffset = JSThread::GlueData::GetSOldSpaceAllocationTopAddressOffset(false);
262         endOffset = JSThread::GlueData::GetSOldSpaceAllocationEndAddressOffset(false);
263     } else if (flag == RegionSpaceFlag::IN_SHARED_NON_MOVABLE) {
264         topOffset = JSThread::GlueData::GetSNonMovableSpaceAllocationTopAddressOffset(false);
265         endOffset = JSThread::GlueData::GetSNonMovableSpaceAllocationEndAddressOffset(false);
266     } else {
267         ASSERT(flag == RegionSpaceFlag::IN_YOUNG_SPACE);
268         topOffset = JSThread::GlueData::GetNewSpaceAllocationTopAddressOffset(false);
269         endOffset = JSThread::GlueData::GetNewSpaceAllocationEndAddressOffset(false);
270     }
271     GateRef topAddrOffset = circuit_->GetConstantGateWithoutCache(MachineType::I64, topOffset, GateType::NJSValue());
272     GateRef endAddrOffset = circuit_->GetConstantGateWithoutCache(MachineType::I64, endOffset, GateType::NJSValue());
273     GateRef topAddrAddr = builder_.PtrAdd(glue, topAddrOffset);
274     GateRef endAddrAddr = builder_.PtrAdd(glue, endAddrOffset);
275     GateRef topAddress = builder_.LoadFromAddressWithoutBarrier(VariableType::NATIVE_POINTER(), topAddrAddr);
276     GateRef endAddress = builder_.LoadFromAddressWithoutBarrier(VariableType::NATIVE_POINTER(), endAddrAddr);
277     GateRef addrOffset = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
278     GateRef rawTopAddr = builder_.PtrAdd(topAddress, addrOffset);
279     GateRef rawEndAddr = builder_.PtrAdd(endAddress, addrOffset);
280     GateRef top = builder_.LoadFromAddressWithoutBarrier(VariableType::JS_POINTER(), rawTopAddr);
281     GateRef end = builder_.LoadFromAddressWithoutBarrier(VariableType::JS_POINTER(), rawEndAddr);
282 
283     GateRef newTop = builder_.PtrAdd(top, size);
284     GateRef condition = builder_.Int64GreaterThan(newTop, end);
285     Label *currentLabel = env.GetCurrentLabel();
286     BRANCH_CIR(condition, &callRuntime, &success);
287     {
288         GateRef ifBranch = currentLabel->GetControl();
289         PrepareToScheduleNewGate(ifBranch, currentBBGates);
290         PrepareToScheduleNewGate(condition, currentBBGates);
291         PrepareToScheduleNewGate(newTop, currentBBGates);
292         PrepareToScheduleNewGate(end, currentBBGates);
293         PrepareToScheduleNewGate(top, currentBBGates);
294         PrepareToScheduleNewGate(rawEndAddr, currentBBGates);
295         PrepareToScheduleNewGate(rawTopAddr, currentBBGates);
296         PrepareToScheduleNewGate(topAddress, currentBBGates);
297         PrepareToScheduleNewGate(endAddress, currentBBGates);
298         PrepareToScheduleNewGate(addrOffset, currentBBGates);
299         PrepareToScheduleNewGate(topAddrAddr, currentBBGates);
300         PrepareToScheduleNewGate(endAddrAddr, currentBBGates);
301         PrepareToScheduleNewGate(topAddrOffset, currentBBGates);
302         PrepareToScheduleNewGate(endAddrOffset, currentBBGates);
303         PrepareToScheduleNewGate(hole, currentBBGates);
304     }
305     builder_.Bind(&success);
306     {
307         GateRef ifFalse = builder_.GetState();
308         GateRef addr = builder_.PtrAdd(topAddress, addrOffset);
309         builder_.StoreWithoutBarrier(VariableType::NATIVE_POINTER(), addr, newTop);
310         GateRef store = builder_.GetDepend();
311         result = top;
312         builder_.Jump(&exit);
313         {
314             GateRef ordinaryBlock = success.GetControl();
315             PrepareToScheduleNewGate(ordinaryBlock, successBBGates);
316             PrepareToScheduleNewGate(store, successBBGates);
317             PrepareToScheduleNewGate(addr, successBBGates);
318             PrepareToScheduleNewGate(ifFalse, successBBGates);
319         }
320     }
321     builder_.Bind(&callRuntime);
322     {
323         GateRef ifTrue = builder_.GetState();
324         GateRef taggedIntMask = circuit_->GetConstantGateWithoutCache(
325             MachineType::I64, JSTaggedValue::TAG_INT, GateType::NJSValue());
326         GateRef taggedSize = builder_.Int64Or(size, taggedIntMask);
327         GateRef target = Circuit::NullGate();
328         if (flag == RegionSpaceFlag::IN_SHARED_OLD_SPACE) {
329             target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, RTSTUB_ID(AllocateInSOld),
330                                                            GateType::NJSValue());
331         } else if (flag == RegionSpaceFlag::IN_SHARED_NON_MOVABLE) {
332             target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, RTSTUB_ID(AllocateInSNonMovable),
333                                                            GateType::NJSValue());
334         } else {
335             ASSERT(flag == RegionSpaceFlag::IN_YOUNG_SPACE);
336             target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, RTSTUB_ID(AllocateInYoung),
337                                                            GateType::NJSValue());
338         }
339         const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
340         ASSERT(cs->IsRuntimeStub());
341         GateRef reseverdFrameState = Circuit::NullGate();
342         std::vector<GateRef> args { taggedSize };
343         // keep same with CircuitBuilder::Call: only when condition is true, we pass FrameState.
344         if (builder_.GetCircuit()->IsOptimizedOrFastJit()) {
345             reseverdFrameState = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
346             args.push_back(reseverdFrameState);
347         }
348         // here in order to schedule all the intermediate value,
349         // framestate is solved out from CircuitBuilder::Call,
350         // so hirGate must be NullGate to prevent duplicated operation.
351         GateRef slowResult = builder_.Call(cs, glue, target, builder_.GetDepend(),
352                                            args, Circuit::NullGate(), "Heap alloc");
353         result = slowResult;
354         builder_.Jump(&exit);
355         {
356             GateRef ordinaryBlock = callRuntime.GetControl();
357             PrepareToScheduleNewGate(ordinaryBlock, failBBGates);
358             PrepareToScheduleNewGate(slowResult, failBBGates);
359             PrepareToScheduleNewGate(target, failBBGates);
360             PrepareToScheduleNewGate(taggedSize, failBBGates);
361             if (builder_.GetCircuit()->IsOptimizedOrFastJit()) {
362                 PrepareToScheduleNewGate(reseverdFrameState, failBBGates);
363             }
364             PrepareToScheduleNewGate(taggedIntMask, failBBGates);
365             PrepareToScheduleNewGate(ifTrue, failBBGates);
366         }
367     }
368     builder_.Bind(&exit);
369     {
370         GateRef merge = builder_.GetState();
371         GateRef phi = *result;
372         PrepareToScheduleNewGate(merge, endBBGates);
373         PrepareToScheduleNewGate(phi, endBBGates);
374     }
375     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
376 #endif
377 }
378 
LoweringHeapAllocAndPrepareScheduleGateForCMCGC(GateRef gate,std::vector<GateRef> & currentBBGates,std::vector<GateRef> & successBBGates,std::vector<GateRef> & failBBGates,std::vector<GateRef> & endBBGates,int64_t flag)379 void PostSchedule::LoweringHeapAllocAndPrepareScheduleGateForCMCGC(GateRef gate,
380                                                                    std::vector<GateRef> &currentBBGates,
381                                                                    std::vector<GateRef> &successBBGates,
382                                                                    std::vector<GateRef> &failBBGates,
383                                                                    std::vector<GateRef> &endBBGates,
384                                                                    [[maybe_unused]] int64_t flag)
385 {
386 #if defined(ARK_ASAN_ON)
387     LoweringHeapAllocate(gate, currentBBGates, successBBGates, failBBGates, endBBGates, flag);
388 #else
389     Environment env(gate, circuit_, &builder_);
390     Label exit(&builder_);
391     GateRef glue = acc_.GetValueIn(gate, 0);
392     GateRef size = acc_.GetValueIn(gate, 1);
393     GateRef hole = circuit_->GetConstantGateWithoutCache(
394         MachineType::I64, JSTaggedValue::VALUE_HOLE, GateType::TaggedValue());
395     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), hole);
396     Label success(&builder_);
397     Label callRuntime(&builder_);
398 
399     ASSERT(flag == RegionSpaceFlag::IN_YOUNG_SPACE);
400     size_t allocBufferOffset = JSThread::GlueData::GetAllocBufferOffset(false);
401     GateRef allocBufferAddrOffset = circuit_->GetConstantGateWithoutCache(
402         MachineType::I64, allocBufferOffset, GateType::NJSValue());
403     GateRef allocBufferAddr = builder_.PtrAdd(glue, allocBufferAddrOffset);
404     GateRef allocBufferAddress =
405         builder_.LoadFromAddressWithoutBarrier(VariableType::NATIVE_POINTER(), allocBufferAddr);
406 
407     GateRef addrOffset = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
408     GateRef tlRegionAddr = builder_.PtrAdd(allocBufferAddress, addrOffset);
409     GateRef tlRegionAddress = builder_.LoadFromAddressWithoutBarrier(VariableType::NATIVE_POINTER(), tlRegionAddr);
410     GateRef allocPtrAddr = builder_.PtrAdd(tlRegionAddress, addrOffset);
411     GateRef allocPtr = builder_.LoadFromAddressWithoutBarrier(VariableType::JS_POINTER(), allocPtrAddr);
412     GateRef regionEndOffset = circuit_->GetConstantGateWithoutCache(MachineType::I64, 8, GateType::NJSValue());
413     GateRef regionEndAddr = builder_.PtrAdd(tlRegionAddress, regionEndOffset);
414     GateRef regionEnd = builder_.LoadFromAddressWithoutBarrier(VariableType::JS_POINTER(), regionEndAddr);
415 
416     GateRef newAllocPtr = builder_.PtrAdd(allocPtr, size);
417     GateRef condition = builder_.Int64GreaterThan(newAllocPtr, regionEnd);
418     Label *currentLabel = env.GetCurrentLabel();
419     BRANCH_CIR(condition, &callRuntime, &success);
420     {
421         GateRef ifBranch = currentLabel->GetControl();
422         PrepareToScheduleNewGate(ifBranch, currentBBGates);
423         PrepareToScheduleNewGate(condition, currentBBGates);
424         PrepareToScheduleNewGate(newAllocPtr, currentBBGates);
425         PrepareToScheduleNewGate(regionEnd, currentBBGates);
426         PrepareToScheduleNewGate(allocPtr, currentBBGates);
427         PrepareToScheduleNewGate(regionEndAddr, currentBBGates);
428         PrepareToScheduleNewGate(regionEndOffset, currentBBGates);
429         PrepareToScheduleNewGate(allocPtrAddr, currentBBGates);
430         PrepareToScheduleNewGate(tlRegionAddress, currentBBGates);
431         PrepareToScheduleNewGate(tlRegionAddr, currentBBGates);
432         PrepareToScheduleNewGate(addrOffset, currentBBGates);
433         PrepareToScheduleNewGate(allocBufferAddress, currentBBGates);
434         PrepareToScheduleNewGate(allocBufferAddr, currentBBGates);
435         PrepareToScheduleNewGate(allocBufferAddrOffset, currentBBGates);
436         PrepareToScheduleNewGate(hole, currentBBGates);
437     }
438     builder_.Bind(&success);
439     {
440         GateRef ifFalse = builder_.GetState();
441         GateRef addr = builder_.PtrAdd(allocPtrAddr, addrOffset);
442         builder_.StoreWithoutBarrier(VariableType::NATIVE_POINTER(), addr, newAllocPtr);
443         GateRef store = builder_.GetDepend();
444         result = allocPtr;
445         builder_.Jump(&exit);
446         {
447             GateRef ordinaryBlock = success.GetControl();
448             PrepareToScheduleNewGate(ordinaryBlock, successBBGates);
449             PrepareToScheduleNewGate(store, successBBGates);
450             PrepareToScheduleNewGate(addr, successBBGates);
451             PrepareToScheduleNewGate(ifFalse, successBBGates);
452         }
453     }
454     builder_.Bind(&callRuntime);
455     {
456         GateRef ifTrue = builder_.GetState();
457         GateRef taggedIntMask = circuit_->GetConstantGateWithoutCache(
458             MachineType::I64, JSTaggedValue::TAG_INT, GateType::NJSValue());
459         GateRef taggedSize = builder_.Int64Or(size, taggedIntMask);
460         GateRef target = Circuit::NullGate();
461         if (flag == RegionSpaceFlag::IN_SHARED_OLD_SPACE) {
462             target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, RTSTUB_ID(AllocateInSOld),
463                                                            GateType::NJSValue());
464         } else if (flag == RegionSpaceFlag::IN_SHARED_NON_MOVABLE) {
465             target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, RTSTUB_ID(AllocateInSNonMovable),
466                                                            GateType::NJSValue());
467         } else {
468             ASSERT(flag == RegionSpaceFlag::IN_YOUNG_SPACE);
469             target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, RTSTUB_ID(AllocateInYoung),
470                                                            GateType::NJSValue());
471         }
472         const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
473         ASSERT(cs->IsRuntimeStub());
474         GateRef reseverdFrameState = Circuit::NullGate();
475         std::vector<GateRef> args { taggedSize };
476         // keep same with CircuitBuilder::Call: only when condition is true, we pass FrameState.
477         if (builder_.GetCircuit()->IsOptimizedOrFastJit()) {
478             reseverdFrameState = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
479             args.push_back(reseverdFrameState);
480         }
481         // here in order to schedule all the intermediate value,
482         // framestate is solved out from CircuitBuilder::Call,
483         // so hirGate must be NullGate to prevent duplicated operation.
484         GateRef slowResult = builder_.Call(cs, glue, target, builder_.GetDepend(),
485                                            args, Circuit::NullGate(), "Heap alloc");
486         result = slowResult;
487         builder_.Jump(&exit);
488         {
489             GateRef ordinaryBlock = callRuntime.GetControl();
490             PrepareToScheduleNewGate(ordinaryBlock, failBBGates);
491             PrepareToScheduleNewGate(slowResult, failBBGates);
492             PrepareToScheduleNewGate(target, failBBGates);
493             PrepareToScheduleNewGate(taggedSize, failBBGates);
494             if (builder_.GetCircuit()->IsOptimizedOrFastJit()) {
495                 PrepareToScheduleNewGate(reseverdFrameState, failBBGates);
496             }
497             PrepareToScheduleNewGate(taggedIntMask, failBBGates);
498             PrepareToScheduleNewGate(ifTrue, failBBGates);
499         }
500     }
501     builder_.Bind(&exit);
502     {
503         GateRef merge = builder_.GetState();
504         GateRef phi = *result;
505         PrepareToScheduleNewGate(merge, endBBGates);
506         PrepareToScheduleNewGate(phi, endBBGates);
507     }
508     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
509 #endif
510 }
511 
LoweringHeapAllocate(GateRef gate,std::vector<GateRef> & currentBBGates,std::vector<GateRef> & successBBGates,std::vector<GateRef> & failBBGates,std::vector<GateRef> & endBBGates,int64_t flag)512 void PostSchedule::LoweringHeapAllocate(GateRef gate,
513                                         std::vector<GateRef> &currentBBGates,
514                                         std::vector<GateRef> &successBBGates,
515                                         std::vector<GateRef> &failBBGates,
516                                         std::vector<GateRef> &endBBGates,
517                                         int64_t flag)
518 {
519     Environment env(gate, circuit_, &builder_);
520     (void)successBBGates;
521     (void)failBBGates;
522     (void)endBBGates;
523     GateRef glue = acc_.GetValueIn(gate, 0);
524     GateRef size = acc_.GetValueIn(gate, 1);
525     GateRef taggedIntMask = circuit_->GetConstantGateWithoutCache(
526         MachineType::I64, JSTaggedValue::TAG_INT, GateType::NJSValue());
527     GateRef taggedSize = builder_.Int64Or(size, taggedIntMask);
528     auto id = RTSTUB_ID(AllocateInYoung);
529     if (flag == RegionSpaceFlag::IN_SHARED_OLD_SPACE) {
530         id = RTSTUB_ID(AllocateInSOld);
531     } else if (flag == RegionSpaceFlag::IN_SHARED_NON_MOVABLE) {
532         id = RTSTUB_ID(AllocateInSNonMovable);
533     } else if (flag == RegionSpaceFlag::IN_OLD_SPACE) {
534         id = RTSTUB_ID(AllocateInOld);
535     } else {
536         ASSERT(flag == RegionSpaceFlag::IN_YOUNG_SPACE);
537     }
538     GateRef target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, id, GateType::NJSValue());
539     const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
540     ASSERT(cs->IsRuntimeStub());
541     GateRef reseverdFrameState = Circuit::NullGate();
542     std::vector<GateRef> args { taggedSize };
543     // keep same with CircuitBuilder::Call: only when condition is true, we pass the other two args.
544     if (builder_.GetCircuit()->IsOptimizedOrFastJit()) {
545         reseverdFrameState = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
546         args.push_back(reseverdFrameState);
547     }
548     // here in order to schedule all the intermediate value,
549     // framestate is solved out from CircuitBuilder::Call,
550     // so hirGate must be NullGate to prevent duplicated operation.
551     GateRef result = builder_.Call(cs, glue, target, builder_.GetDepend(), args, Circuit::NullGate(), "Heap alloc");
552     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
553 
554     // Must keep the order of value-in/depend-in
555     PrepareToScheduleNewGate(result, currentBBGates);
556     PrepareToScheduleNewGate(target, currentBBGates);
557     PrepareToScheduleNewGate(taggedSize, currentBBGates);
558     if (builder_.GetCircuit()->IsOptimizedOrFastJit()) {
559         PrepareToScheduleNewGate(reseverdFrameState, currentBBGates);
560     }
561     PrepareToScheduleNewGate(taggedIntMask, currentBBGates);
562     return;
563 }
564 
VisitStore(GateRef gate,ControlFlowGraph & cfg,size_t bbIdx,size_t instIdx)565 bool PostSchedule::VisitStore(GateRef gate, ControlFlowGraph &cfg, size_t bbIdx, size_t instIdx)
566 {
567     std::vector<GateRef> currentBBGates;
568     std::vector<GateRef> barrierBBGates;
569     std::vector<GateRef> endBBGates;
570 #ifndef ARK_USE_SATB_BARRIER
571     MemoryAttribute::Barrier kind = GetBarrierKind(gate);
572 #else
573     GateRef value = acc_.GetValueIn(gate, 3);  // 3: value
574     MemoryAttribute::Barrier kind = GetBarrierKind(gate);
575     if (acc_.GetMachineType(value) == MachineType::ANYVALUE ||
576         acc_.GetMachineType(value) == MachineType::ARCH ||
577         acc_.GetMachineType(value) == MachineType::I64) {
578         kind = MemoryAttribute::Barrier::NEED_BARRIER;
579     }
580 #endif
581     switch (kind) {
582         case MemoryAttribute::Barrier::UNKNOWN_BARRIER: {
583             LoweringStoreUnknownBarrierAndPrepareScheduleGate(gate, currentBBGates, barrierBBGates, endBBGates);
584             ReplaceBBState(cfg, bbIdx, currentBBGates, endBBGates);
585             ScheduleEndBB(endBBGates, cfg, bbIdx, instIdx);
586             ScheduleNewBB(barrierBBGates, cfg, bbIdx);
587             ScheduleCurrentBB(currentBBGates, cfg, bbIdx, instIdx);
588             return true;
589         }
590         case MemoryAttribute::Barrier::NEED_BARRIER: {
591             LoweringStoreWithBarrierAndPrepareScheduleGate(gate, currentBBGates);
592             ReplaceGateDirectly(currentBBGates, cfg, bbIdx, instIdx);
593             return false;
594         }
595         case MemoryAttribute::Barrier::NO_BARRIER: {
596             LoweringStoreNoBarrierAndPrepareScheduleGate(gate, currentBBGates);
597             ReplaceGateDirectly(currentBBGates, cfg, bbIdx, instIdx);
598             return false;
599         }
600         default: {
601             UNREACHABLE();
602             return false;
603         }
604     }
605     return false;
606 }
607 
GetBarrierKind(GateRef gate)608 MemoryAttribute::Barrier PostSchedule::GetBarrierKind(GateRef gate)
609 {
610     MemoryAttribute mAttr = acc_.GetMemoryAttribute(gate);
611     if (!acc_.IsGCRelated(gate)) {
612         return MemoryAttribute::Barrier::NO_BARRIER;
613     }
614     return mAttr.GetBarrier();
615 }
616 
SelectBarrier(MemoryAttribute::ShareFlag share,const CallSignature * & cs,std::string_view & comment)617 int PostSchedule::SelectBarrier(MemoryAttribute::ShareFlag share, const CallSignature*& cs, std::string_view& comment)
618 {
619     int index = 0;
620     if (!isStwCopyStub_) {
621         index = CommonStubCSigns::SetValueWithBarrier;
622         cs = CommonStubCSigns::Get(index);
623         comment = "cmcgc store barrier\0";
624         return index;
625     }
626     switch (share) {
627         case MemoryAttribute::UNKNOWN:
628             if (fastBarrier_) {
629                 index = RuntimeStubCSigns::ID_ASMFastWriteBarrier;
630                 cs = RuntimeStubCSigns::Get(index);
631                 comment = "asm store barrier\0";
632             } else {
633                 index = CommonStubCSigns::SetValueWithBarrier;
634                 cs = CommonStubCSigns::Get(index);
635                 comment = "store barrier\0";
636             }
637             break;
638         case MemoryAttribute::SHARED:
639             index = CommonStubCSigns::SetSValueWithBarrier;
640             cs = CommonStubCSigns::Get(index);
641             comment = "store share barrier\0";
642             break;
643         case MemoryAttribute::NON_SHARE:
644             index = CommonStubCSigns::SetNonSValueWithBarrier;
645             cs = CommonStubCSigns::Get(index);
646             comment = "store not share barrier\0";
647             break;
648         default:
649             UNREACHABLE();
650     }
651     return index;
652 }
653 
LoweringStoreNoBarrierAndPrepareScheduleGate(GateRef gate,std::vector<GateRef> & currentBBGates)654 void PostSchedule::LoweringStoreNoBarrierAndPrepareScheduleGate(GateRef gate, std::vector<GateRef> &currentBBGates)
655 {
656     Environment env(gate, circuit_, &builder_);
657 
658     GateRef base = acc_.GetValueIn(gate, 1);   // 1: object
659     GateRef offset = acc_.GetValueIn(gate, 2); // 2: offset
660     GateRef addr = builder_.PtrAdd(base, offset);
661     GateRef compValue = acc_.GetValueIn(gate, 4);  // 3: value
662     VariableType type = VariableType(acc_.GetMachineType(compValue), acc_.GetGateType(compValue));
663     builder_.StoreWithoutBarrier(type, addr, compValue, acc_.GetMemoryAttribute(gate));
664     GateRef store = builder_.GetDepend();
665     {
666         PrepareToScheduleNewGate(store, currentBBGates);
667         PrepareToScheduleNewGate(addr, currentBBGates);
668     }
669     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
670 }
671 
GetShareKind(panda::ecmascript::kungfu::GateRef gate)672 MemoryAttribute::ShareFlag PostSchedule::GetShareKind(panda::ecmascript::kungfu::GateRef gate)
673 {
674     MemoryAttribute mAttr = acc_.GetMemoryAttribute(gate);
675     return mAttr.GetShare();
676 }
677 #ifndef ARK_USE_SATB_BARRIER
LoweringStoreWithBarrierAndPrepareScheduleGate(GateRef gate,std::vector<GateRef> & currentBBGates)678 void PostSchedule::LoweringStoreWithBarrierAndPrepareScheduleGate(GateRef gate, std::vector<GateRef> &currentBBGates)
679 {
680     Environment env(gate, circuit_, &builder_);
681 
682     GateRef glue = acc_.GetValueIn(gate, 0);
683     GateRef base = acc_.GetValueIn(gate, 1);   // 1: object
684     GateRef offset = acc_.GetValueIn(gate, 2); // 2: offset
685     GateRef value = acc_.GetValueIn(gate, 3);  // 3: value
686     GateRef compValue = acc_.GetValueIn(gate, 4);  // 3: value
687     GateRef addr = builder_.PtrAdd(base, offset);
688     // If value isn't equal to compValue, It uses to store compress pointer.
689     VariableType type = VariableType(acc_.GetMachineType(compValue), acc_.GetGateType(compValue));
690     builder_.StoreWithoutBarrier(type, addr, compValue, acc_.GetMemoryAttribute(gate));
691     GateRef store = builder_.GetDepend();
692     MemoryAttribute::ShareFlag share = GetShareKind(gate);
693     std::string_view comment;
694     int index;
695     const CallSignature* cs = nullptr;
696     index = SelectBarrier(share, cs, comment);
697     ASSERT(cs && (cs->IsCommonStub() || cs->IsASMCallBarrierStub()) && "Invalid call signature for barrier");
698     GateRef target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, index, GateType::NJSValue());
699     GateRef reseverdFrameState = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
700     GateRef storeBarrier = builder_.Call(cs, glue, target, builder_.GetDepend(),
701                                          {glue, base, offset, value, reseverdFrameState},
702                                          Circuit::NullGate(), comment.data());
703     {
704         PrepareToScheduleNewGate(storeBarrier, currentBBGates);
705         PrepareToScheduleNewGate(reseverdFrameState, currentBBGates);
706         PrepareToScheduleNewGate(target, currentBBGates);
707         PrepareToScheduleNewGate(store, currentBBGates);
708         PrepareToScheduleNewGate(addr, currentBBGates);
709     }
710     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
711 }
712 #else
LoweringStoreWithBarrierAndPrepareScheduleGate(GateRef gate,std::vector<GateRef> & currentBBGates)713 void PostSchedule::LoweringStoreWithBarrierAndPrepareScheduleGate(GateRef gate, std::vector<GateRef> &currentBBGates)
714 {
715     Environment env(gate, circuit_, &builder_);
716 
717     GateRef glue = acc_.GetValueIn(gate, 0);
718     GateRef base = acc_.GetValueIn(gate, 1);   // 1: object
719     GateRef offset = acc_.GetValueIn(gate, 2); // 2: offset
720     GateRef value = acc_.GetValueIn(gate, 3);  // 3: value
721     GateRef hole = circuit_->GetConstantGateWithoutCache(
722         MachineType::I64, JSTaggedValue::VALUE_HOLE, GateType::TaggedValue());
723     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), hole);
724     GateRef addr = builder_.PtrAdd(base, offset);
725     VariableType type = VariableType(acc_.GetMachineType(gate), acc_.GetGateType(gate));
726     MemoryAttribute::ShareFlag share = GetShareKind(gate);
727     std::string_view comment;
728     int index;
729     const CallSignature* cs = nullptr;
730     index = SelectBarrier(share, cs, comment);
731     ASSERT(cs && (cs->IsCommonStub() || cs->IsASMCallBarrierStub()) && "Invalid call signature for barrier");
732     GateRef target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, index, GateType::NJSValue());
733     GateRef reseverdFrameArgs = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
734     GateRef reseverdPc = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
735     bool isfloat32 = acc_.GetMachineType(value) == F32;
736 
737     GateRef newvalue;
738     if (isfloat32) {
739         newvalue = builder_.ExtFloat32ToDouble(value);
740         result = newvalue;
741     } else {
742         result = value;
743     }
744     GateRef storeBarrier = builder_.Call(cs, glue, target, builder_.GetDepend(),
745                                          {glue, base, offset, *result, reseverdFrameArgs, reseverdPc},
746                                          Circuit::NullGate(), comment.data());
747     builder_.StoreWithoutBarrier(type, addr, value, acc_.GetMemoryAttribute(gate));
748     GateRef store = builder_.GetDepend();
749     {
750         PrepareToScheduleNewGate(store, currentBBGates);
751         PrepareToScheduleNewGate(storeBarrier, currentBBGates);
752         if (isfloat32) {
753             PrepareToScheduleNewGate(newvalue, currentBBGates);
754         }
755         PrepareToScheduleNewGate(reseverdPc, currentBBGates);
756         PrepareToScheduleNewGate(reseverdFrameArgs, currentBBGates);
757         PrepareToScheduleNewGate(target, currentBBGates);
758         PrepareToScheduleNewGate(addr, currentBBGates);
759         PrepareToScheduleNewGate(hole, currentBBGates);
760     }
761     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
762 }
763 #endif
LoweringStoreUnknownBarrierAndPrepareScheduleGate(GateRef gate,std::vector<GateRef> & currentBBGates,std::vector<GateRef> & barrierBBGates,std::vector<GateRef> & endBBGates)764 void PostSchedule::LoweringStoreUnknownBarrierAndPrepareScheduleGate(GateRef gate,
765                                                                      std::vector<GateRef> &currentBBGates,
766                                                                      std::vector<GateRef> &barrierBBGates,
767                                                                      std::vector<GateRef> &endBBGates)
768 {
769     Environment env(gate, circuit_, &builder_);
770 
771     GateRef glue = acc_.GetValueIn(gate, 0);
772     GateRef base = acc_.GetValueIn(gate, 1);   // 1: object
773     GateRef offset = acc_.GetValueIn(gate, 2); // 2: offset
774     GateRef value = acc_.GetValueIn(gate, 3);  // 3: value
775     GateRef compValue = acc_.GetValueIn(gate, 4);  // 3: value
776     GateRef addr = builder_.PtrAdd(base, offset);
777     VariableType type = VariableType(acc_.GetMachineType(compValue), acc_.GetGateType(compValue));
778     builder_.StoreWithoutBarrier(type, addr, compValue, acc_.GetMemoryAttribute(gate));
779     GateRef store = builder_.GetDepend();
780 
781     Label exit(&builder_);
782     Label isHeapObject(&builder_);
783     Label *currentLabel = env.GetCurrentLabel();
784     if (compilationEnv_ != nullptr && compilationEnv_->SupportIntrinsic() && !acc_.IsConstant(value)) {
785         GateRef heapObjectCheck = builder_.TaggedIsHeapObject(value, compilationEnv_);
786         BRANCH_CIR(heapObjectCheck, &isHeapObject, &exit);
787         {
788             GateRef ifBranch = currentLabel->GetControl();
789             PrepareToScheduleNewGate(ifBranch, currentBBGates);
790             PrepareToScheduleNewGate(heapObjectCheck, currentBBGates);
791             PrepareToScheduleNewGate(store, currentBBGates);
792             PrepareToScheduleNewGate(addr, currentBBGates);
793         }
794     } else {
795         GateRef intVal = builder_.ChangeTaggedPointerToInt64(value);
796         GateRef objMask = circuit_->GetConstantGateWithoutCache(
797             MachineType::I64, JSTaggedValue::TAG_HEAPOBJECT_MASK, GateType::NJSValue());
798         GateRef masked = builder_.Int64And(intVal, objMask, GateType::Empty(), "checkHeapObject");
799         GateRef falseVal = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
800         GateRef condition = builder_.Equal(masked, falseVal, "checkHeapObject");
801         BRANCH_CIR(condition, &isHeapObject, &exit);
802         {
803             GateRef ifBranch = currentLabel->GetControl();
804             PrepareToScheduleNewGate(ifBranch, currentBBGates);
805             PrepareToScheduleNewGate(condition, currentBBGates);
806             PrepareToScheduleNewGate(falseVal, currentBBGates);
807             PrepareToScheduleNewGate(masked, currentBBGates);
808             PrepareToScheduleNewGate(intVal, currentBBGates);
809             PrepareToScheduleNewGate(objMask, currentBBGates);
810             PrepareToScheduleNewGate(store, currentBBGates);
811             PrepareToScheduleNewGate(addr, currentBBGates);
812         }
813     }
814 
815     GateRef ifTrue = isHeapObject.GetControl();
816     GateRef ifFalse = exit.GetControl();
817     builder_.Bind(&isHeapObject);
818     {
819         MemoryAttribute::ShareFlag share = GetShareKind(gate);
820         std::string_view comment;
821         int index;
822         const CallSignature* cs = nullptr;
823         index = SelectBarrier(share, cs, comment);
824         ASSERT(cs && (cs->IsCommonStub() || cs->IsASMCallBarrierStub()) && "Invalid call signature for barrier");
825         GateRef target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, index, GateType::NJSValue());
826         GateRef reseverdFrameState = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
827 #ifndef NDEBUG
828         GateRef verifyTarget = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, CommonStubCSigns::VerifyBarrier,
829                                                                      GateType::NJSValue());
830         const CallSignature* verifyBarrierCs = CommonStubCSigns::Get(CommonStubCSigns::VerifyBarrier);
831         GateRef verifyBarrier = builder_.Call(verifyBarrierCs, glue, verifyTarget, builder_.GetDepend(),
832                                               {glue, base, offset, value, reseverdFrameState},
833                                               Circuit::NullGate(), "verify barrier");
834 #endif
835         GateRef storeBarrier = builder_.Call(cs, glue, target, builder_.GetDepend(),
836                                              { glue, base, offset, value, reseverdFrameState},
837                                              Circuit::NullGate(), comment.data());
838         builder_.Jump(&exit);
839         {
840             GateRef ordinaryBlock = isHeapObject.GetControl();
841             PrepareToScheduleNewGate(ordinaryBlock, barrierBBGates);
842             PrepareToScheduleNewGate(storeBarrier, barrierBBGates);
843 #ifndef NDEBUG
844             PrepareToScheduleNewGate(verifyBarrier, barrierBBGates);
845 #endif
846             PrepareToScheduleNewGate(reseverdFrameState, barrierBBGates);
847             PrepareToScheduleNewGate(ifTrue, barrierBBGates);
848         }
849     }
850     builder_.Bind(&exit);
851     {
852         GateRef merge = builder_.GetState();
853         PrepareToScheduleNewGate(merge, endBBGates);
854         PrepareToScheduleNewGate(ifFalse, endBBGates);
855     }
856     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
857 }
858 
VisitLoad(GateRef gate,ControlFlowGraph & cfg,size_t bbIdx,size_t instIdx,bool isLoadHClass)859 bool PostSchedule::VisitLoad(GateRef gate, ControlFlowGraph &cfg, size_t bbIdx, size_t instIdx, bool isLoadHClass)
860 {
861     std::vector<GateRef> currentBBGates;
862     std::vector<GateRef> successBBGates;
863     std::vector<GateRef> failBBGates;
864     std::vector<GateRef> endBBGates;
865     MemoryAttribute::Barrier kind = GetBarrierKind(gate);
866     if (isStwCopyStub_) {
867         kind = MemoryAttribute::Barrier::NO_BARRIER;
868     } else if (isLoadHClass) {
869         LoweringLoadHClassAndPrepareScheduleGate(gate, currentBBGates);
870         ReplaceGateDirectly(currentBBGates, cfg, bbIdx, instIdx);
871         return false;
872     }
873     switch (kind) {
874         case MemoryAttribute::Barrier::UNKNOWN_BARRIER:
875         case MemoryAttribute::Barrier::NEED_BARRIER: {
876             LoweringLoadWithBarrierAndPrepareScheduleGate(gate, currentBBGates, successBBGates,
877                                                           failBBGates, endBBGates);
878             ReplaceBBState(cfg, bbIdx, currentBBGates, endBBGates);
879             ScheduleEndBB(endBBGates, cfg, bbIdx, instIdx);
880             ScheduleNewBB(successBBGates, cfg, bbIdx);
881             ScheduleNewBB(failBBGates, cfg, bbIdx);
882             ScheduleCurrentBB(currentBBGates, cfg, bbIdx, instIdx);
883             return true;
884         }
885         case MemoryAttribute::Barrier::NO_BARRIER: {
886             LoweringLoadNoBarrierAndPrepareScheduleGate(gate, currentBBGates);
887             ReplaceGateDirectly(currentBBGates, cfg, bbIdx, instIdx);
888             return false;
889         }
890         default:
891             UNREACHABLE();
892             break;
893     }
894     return false;
895 }
896 
LoweringLoadWithBarrierAndPrepareScheduleGate(GateRef gate,std::vector<GateRef> & currentBBGates,std::vector<GateRef> & successBBGates,std::vector<GateRef> & failBBGates,std::vector<GateRef> & endBBGates)897 void PostSchedule::LoweringLoadWithBarrierAndPrepareScheduleGate(GateRef gate,
898                                                                  std::vector<GateRef> &currentBBGates,
899                                                                  std::vector<GateRef> &successBBGates,
900                                                                  std::vector<GateRef> &failBBGates,
901                                                                  std::vector<GateRef> &endBBGates)
902 {
903     Environment env(gate, circuit_, &builder_);
904     Label exit(&builder_);
905     GateRef glue = acc_.GetValueIn(gate, 0);
906     GateRef addr = acc_.GetValueIn(gate, 1);
907     VariableType type = VariableType(acc_.GetMachineType(gate), acc_.GetGateType(gate));
908 
909     GateRef hole = circuit_->GetConstantGateWithoutCache(
910         MachineType::I64, JSTaggedValue::VALUE_HOLE, GateType::TaggedValue());
911     DEFVALUE(result, (&builder_), type, hole);
912 
913     Label callRuntime(&builder_);
914     Label noBarrier(&builder_);
915     GateRef bitOffset = circuit_->GetConstantGateWithoutCache(
916         MachineType::I64, JSThread::GlueData::GetSharedGCStateBitFieldOffset(false), GateType::NJSValue());
917     GateRef bitAddr = builder_.PtrAdd(glue, bitOffset);
918     GateRef gcStateBitField = builder_.LoadFromAddressWithoutBarrier(VariableType::INT64(), bitAddr);
919     GateRef readBarrierStateMask = circuit_->GetConstantGateWithoutCache(
920         MachineType::I64, JSThread::READ_BARRIER_STATE_BITFIELD_MASK, GateType::NJSValue());
921     GateRef readBarrierStateBit = builder_.Int64And(gcStateBitField, readBarrierStateMask);
922     GateRef conditionValue = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
923     GateRef condition = builder_.Equal(readBarrierStateBit, conditionValue);
924     Label *currentLabel = env.GetCurrentLabel();
925     BRANCH_CIR_LIKELY(condition, &noBarrier, &callRuntime);
926     {
927         GateRef ifBranch = currentLabel->GetControl();
928         PrepareToScheduleNewGate(ifBranch, currentBBGates);
929         PrepareToScheduleNewGate(condition, currentBBGates);
930         PrepareToScheduleNewGate(conditionValue, currentBBGates);
931         PrepareToScheduleNewGate(readBarrierStateBit, currentBBGates);
932         PrepareToScheduleNewGate(readBarrierStateMask, currentBBGates);
933         PrepareToScheduleNewGate(gcStateBitField, currentBBGates);
934         PrepareToScheduleNewGate(bitAddr, currentBBGates);
935         PrepareToScheduleNewGate(bitOffset, currentBBGates);
936         PrepareToScheduleNewGate(hole, currentBBGates);
937     }
938     builder_.Bind(&noBarrier);
939     {
940         GateRef ifTrue = builder_.GetState();
941         GateRef loadWithoutBarrier = builder_.LoadFromAddressWithoutBarrier(type, addr, acc_.GetMemoryAttribute(gate));
942         result = loadWithoutBarrier;
943         builder_.Jump(&exit);
944         {
945             GateRef ordinaryBlock = noBarrier.GetControl();
946             PrepareToScheduleNewGate(ordinaryBlock, successBBGates);
947             PrepareToScheduleNewGate(loadWithoutBarrier, successBBGates);
948             PrepareToScheduleNewGate(ifTrue, successBBGates);
949         }
950     }
951     builder_.Bind(&callRuntime);
952     {
953         GateRef ifFalse = builder_.GetState();
954         int index = CommonStubCSigns::GetValueWithBarrier;
955         const CallSignature *cs = CommonStubCSigns::Get(index);
956         ASSERT(cs->IsCommonStub());
957         GateRef target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, index, GateType::NJSValue());
958         GateRef reservedFrameArgs = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
959         GateRef reservedPc = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
960         GateRef loadBarrier = builder_.Call(cs, glue, target, builder_.GetDepend(),
961                                             { glue, addr, reservedFrameArgs, reservedPc },
962                                             Circuit::NullGate(), "load barrier");
963         result = loadBarrier;
964         builder_.Jump(&exit);
965         {
966             GateRef ordinaryBlock = callRuntime.GetControl();
967             PrepareToScheduleNewGate(ordinaryBlock, failBBGates);
968             PrepareToScheduleNewGate(loadBarrier, failBBGates);
969             PrepareToScheduleNewGate(reservedPc, failBBGates);
970             PrepareToScheduleNewGate(reservedFrameArgs, failBBGates);
971             PrepareToScheduleNewGate(target, failBBGates);
972             PrepareToScheduleNewGate(ifFalse, failBBGates);
973         }
974     }
975     builder_.Bind(&exit);
976     {
977         GateRef merge = builder_.GetState();
978         GateRef phi = *result;
979         PrepareToScheduleNewGate(merge, endBBGates);
980         PrepareToScheduleNewGate(phi, endBBGates);
981     }
982     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
983 }
984 
LoweringLoadNoBarrierAndPrepareScheduleGate(GateRef gate,std::vector<GateRef> & currentBBGates)985 void PostSchedule::LoweringLoadNoBarrierAndPrepareScheduleGate(GateRef gate, std::vector<GateRef> &currentBBGates)
986 {
987     Environment env(gate, circuit_, &builder_);
988 
989     GateRef addr = acc_.GetValueIn(gate, 1);
990     VariableType type = VariableType(acc_.GetMachineType(gate), acc_.GetGateType(gate));
991     GateRef loadWithoutBarrier = builder_.LoadFromAddressWithoutBarrier(type, addr, acc_.GetMemoryAttribute(gate));
992     {
993         PrepareToScheduleNewGate(loadWithoutBarrier, currentBBGates);
994     }
995     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), loadWithoutBarrier);
996 }
997 
LoweringLoadHClassAndPrepareScheduleGate(GateRef gate,std::vector<GateRef> & currentBBGates)998 void PostSchedule::LoweringLoadHClassAndPrepareScheduleGate(GateRef gate, std::vector<GateRef> &currentBBGates)
999 {
1000     Environment env(gate, circuit_, &builder_);
1001 
1002     GateRef addr = acc_.GetValueIn(gate, 1);
1003     VariableType type = VariableType(acc_.GetMachineType(gate), acc_.GetGateType(gate));
1004     GateRef loadWithoutBarrier = builder_.LoadFromAddressWithoutBarrier(type, addr, acc_.GetMemoryAttribute(gate));
1005     GateRef valueWithTag = builder_.ChangeTaggedPointerToInt64(loadWithoutBarrier);
1006     GateRef mask = circuit_->GetConstantGateWithoutCache(
1007         MachineType::I64, TaggedObject::GC_STATE_MASK, GateType::NJSValue());
1008     GateRef value = builder_.Int64And(valueWithTag, mask);
1009     GateRef hclass = builder_.Int64ToTaggedPtr(value);
1010     {
1011         PrepareToScheduleNewGate(hclass, currentBBGates);
1012         PrepareToScheduleNewGate(value, currentBBGates);
1013         PrepareToScheduleNewGate(mask, currentBBGates);
1014         PrepareToScheduleNewGate(valueWithTag, currentBBGates);
1015         PrepareToScheduleNewGate(loadWithoutBarrier, currentBBGates);
1016     }
1017     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), hclass);
1018 }
1019 
PrintGraph(const char * title,ControlFlowGraph & cfg)1020 void PostSchedule::PrintGraph(const char* title, ControlFlowGraph &cfg)
1021 {
1022     LOG_COMPILER(INFO) << "======================== " << title << " ========================";
1023     for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) {
1024         LOG_COMPILER(INFO) << "B" << bbIdx << ":";
1025         const std::vector<GateRef>& bb = cfg.at(bbIdx);
1026         for (size_t instIdx = 0; instIdx < bb.size(); instIdx++) {
1027             GateRef gate = bb[instIdx];
1028             acc_.Print(gate);
1029         }
1030         LOG_COMPILER(INFO) << "";
1031     }
1032 }
1033 }  // namespace panda::ecmascript::kungfu
1034