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