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 23namespace panda::ecmascript::kungfu { 24void 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 41void 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 76bool 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 107void 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 114void 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 123void 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 130void 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 142void PostSchedule::PrepareToScheduleNewGate(GateRef gate, std::vector<GateRef> &gates) 143{ 144 gates.emplace_back(gate); 145} 146 147void 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 192void 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 324void 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 369bool 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 402MemoryAttribute::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 411int 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 442void 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 460MemoryAttribute::ShareFlag PostSchedule::GetShareKind(panda::ecmascript::kungfu::GateRef gate) 461{ 462 MemoryAttribute mAttr = acc_.GetMemoryAttribute(gate); 463 return mAttr.GetShare(); 464} 465 466void 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 501void 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 584void 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