|
Lines 221-226
public:
Source/JavaScriptCore/dfg/DFGPutStackSinkingPhase.cpp_sec1
|
| 221 |
continue; |
221 |
continue; |
| 222 |
} |
222 |
} |
| 223 |
|
223 |
|
|
|
224 |
if (node->op() == GetStack) { |
| 225 |
// A GetStack doesn't affect anything, since we know which local we are reading |
| 226 |
// from. |
| 227 |
continue; |
| 228 |
} |
| 229 |
|
| 224 |
auto escapeHandler = [&] (VirtualRegister operand) { |
230 |
auto escapeHandler = [&] (VirtualRegister operand) { |
| 225 |
if (operand.isHeader()) |
231 |
if (operand.isHeader()) |
| 226 |
return; |
232 |
return; |
|
Lines 390-395
public:
Source/JavaScriptCore/dfg/DFGPutStackSinkingPhase.cpp_sec2
|
| 390 |
deferred.operand(node->unlinkedLocal()) = ConflictingFlush; |
396 |
deferred.operand(node->unlinkedLocal()) = ConflictingFlush; |
| 391 |
break; |
397 |
break; |
| 392 |
} |
398 |
} |
|
|
399 |
|
| 400 |
case GetStack: { |
| 401 |
StackAccessData* data = node->stackAccessData(); |
| 402 |
FlushFormat format = deferred.operand(data->local); |
| 403 |
if (!isConcrete(format)) { |
| 404 |
// This means there is no deferral. No deferral means that the most |
| 405 |
// authoritative value for this stack slot is what is stored in the stack. So, |
| 406 |
// keep the GetStack. |
| 407 |
mapping.operand(data->local) = node; |
| 408 |
break; |
| 409 |
} |
| 410 |
|
| 411 |
// We have a concrete deferral, which means a PutStack that hasn't executed yet. It |
| 412 |
// would have stored a value with a certain format. That format must match our |
| 413 |
// format. But more importantly, we can simply use the value that the PutStack would |
| 414 |
// have stored and get rid of the GetStack. |
| 415 |
DFG_ASSERT(m_graph, node, format == data->format); |
| 416 |
|
| 417 |
Node* incoming = mapping.operand(data->local); |
| 418 |
node->child1() = incoming->defaultEdge(); |
| 419 |
node->convertToIdentity(); |
| 420 |
break; |
| 421 |
} |
| 393 |
|
422 |
|
| 394 |
default: { |
423 |
default: { |
| 395 |
auto escapeHandler = [&] (VirtualRegister operand) { |
424 |
auto escapeHandler = [&] (VirtualRegister operand) { |
|
Lines 418-433
public:
Source/JavaScriptCore/dfg/DFGPutStackSinkingPhase.cpp_sec3
|
| 418 |
preciseLocalClobberize( |
447 |
preciseLocalClobberize( |
| 419 |
m_graph, node, escapeHandler, escapeHandler, |
448 |
m_graph, node, escapeHandler, escapeHandler, |
| 420 |
[&] (VirtualRegister, Node*) { }); |
449 |
[&] (VirtualRegister, Node*) { }); |
| 421 |
|
|
|
| 422 |
// If we're a GetStack, then we also create a mapping. |
| 423 |
// FIXME: We should be able to just eliminate such GetLocals, when we know |
| 424 |
// what their incoming value will be. |
| 425 |
// https://bugs.webkit.org/show_bug.cgi?id=141624 |
| 426 |
if (node->op() == GetStack) { |
| 427 |
StackAccessData* data = node->stackAccessData(); |
| 428 |
VirtualRegister operand = data->local; |
| 429 |
mapping.operand(operand) = node; |
| 430 |
} |
| 431 |
break; |
450 |
break; |
| 432 |
} } |
451 |
} } |
| 433 |
} |
452 |
} |
|
Lines 444-477
public:
Source/JavaScriptCore/dfg/DFGPutStackSinkingPhase.cpp_sec4
|
| 444 |
FlushFormat format = deferredAtHead[successorBlock].operand(operand); |
463 |
FlushFormat format = deferredAtHead[successorBlock].operand(operand); |
| 445 |
DFG_ASSERT(m_graph, nullptr, isConcrete(format)); |
464 |
DFG_ASSERT(m_graph, nullptr, isConcrete(format)); |
| 446 |
UseKind useKind = useKindFor(format); |
465 |
UseKind useKind = useKindFor(format); |
| 447 |
Node* incoming = mapping.operand(operand); |
466 |
|
| 448 |
if (!incoming) { |
467 |
// We need to get a value for the stack slot. This phase doesn't really have a |
| 449 |
// This can totally happen, see tests/stress/put-local-conservative.js. |
468 |
// good way of determining if a stack location got clobbered. It just knows if |
| 450 |
// This arises because deferral and liveness are both conservative. |
469 |
// there is a deferral. The lack of a deferral might mean that a PutStack or |
| 451 |
// Conservative liveness means that a load from a *different* closure |
470 |
// GetStack had never happened, or it might mean that the value was read, or |
| 452 |
// variable may lead us to believe that our local is live. Conservative |
471 |
// that it was written. It's OK for us to make some bad decisions here, since |
| 453 |
// deferral may lead us to believe that the local doesn't have a top deferral |
472 |
// GCSE will clean it up anyway. |
| 454 |
// because someone has done something that would have forced it to be |
473 |
Node* incoming; |
| 455 |
// materialized. The basic pattern is: |
474 |
if (isConcrete(deferred.operand(operand))) { |
| 456 |
// |
475 |
incoming = mapping.operand(operand); |
| 457 |
// GetClosureVar(loc42) // loc42's deferral is now bottom |
476 |
DFG_ASSERT(m_graph, phiNode, incoming); |
| 458 |
// if (predicate1) |
477 |
} else { |
| 459 |
// PutClosureVar(loc42) // prevent GCSE of our GetClosureVar's |
478 |
// Issue a GetStack to get the value. This might introduce some redundancy |
| 460 |
// if (predicate2) |
479 |
// into the code, but if it's bad enough, GCSE will clean it up. |
| 461 |
// PutStack(loc42) // we now have a concrete deferral |
480 |
incoming = insertionSet.insertNode( |
| 462 |
// // we still have the concrete deferral because we merged with bottom |
481 |
upsilonInsertionPoint, SpecNone, GetStack, upsilonOrigin, |
| 463 |
// GetClosureVar(loc42) // force materialization |
482 |
OpInfo(m_graph.m_stackAccessData.add(operand, format))); |
| 464 |
// |
483 |
incoming->setResult(resultFor(format)); |
| 465 |
// We will have a Phi with no incoming value form the basic block that |
|
|
| 466 |
// bypassed the PutStack. |
| 467 |
|
| 468 |
// Note: we sort of could have used the equivalent of LLVM's undef here. The |
| 469 |
// point is that it's OK to just leave random bits in the local if we're |
| 470 |
// coming down this path. But, we don't have a way of saying that in our IR |
| 471 |
// right now and anyway it probably doesn't matter that much. |
| 472 |
|
| 473 |
incoming = insertionSet.insertBottomConstantForUse( |
| 474 |
upsilonInsertionPoint, upsilonOrigin, useKind).node(); |
| 475 |
} |
484 |
} |
| 476 |
|
485 |
|
| 477 |
insertionSet.insertNode( |
486 |
insertionSet.insertNode( |