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> ¤tBBGates,
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> ¤tBBGates,
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> ¤tBBGates,
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> ¤tBBGates,
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> ¤tBBGates)
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> ¤tBBGates)
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> ¤tBBGates)
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> ¤tBBGates,
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> ¤tBBGates,
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> ¤tBBGates)
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> ¤tBBGates)
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