Skip to content
Permalink
Browse files
DFGSpeculativeJIT should not &= exitOK with mayExit(node)
https://bugs.webkit.org/show_bug.cgi?id=191897
<rdar://problem/45871998>

Reviewed by Mark Lam.

JSTests:

* stress/exitok-is-not-the-same-as-mayExit.js: Added.
(bar):
(foo):

Source/JavaScriptCore:

exitOK is a statement about it being legal to exit. mayExit() is about being
conservative and returning false only if an OSR exit *could never* happen.
mayExit() tries to be as smart as possible to see if it can return false.
It can't return false if a runtime exit *could* happen. However, there is
code in the compiler where mayExit() returns false (because it uses data
generated from AI about type checks being proved), but the code we emit in the
compiler backend unconditionally generates an OSR exit, even if that exit may
never execute. For example, let's say we have this IR:

SomeNode(Boolean:@input)

And we always emit code like this as a way of emitting a boolean type check:

jump L1 if input == true
jump L1 if input == false
emit an OSR exit

In such a program, when we generate the above OSR exit, in a validationEnabled()
build, and if @input is proved to be a boolean, we'll end up crashing because we
have the bogus assertion saying !exitOK. This is one reason why things are cleaner
if we don't conflate mayExit() with exitOK.

* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileCurrentBlock):


Canonical link: https://commits.webkit.org/206607@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238437 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Saam Barati committed Nov 22, 2018
1 parent fb4d872 commit 58f56424c6fdfe3034a48d9c223c9b65d60b5851
Showing with 64 additions and 2 deletions.
  1. +12 −0 JSTests/ChangeLog
  2. +19 −0 JSTests/stress/exitok-is-not-the-same-as-mayExit.js
  3. +33 −0 Source/JavaScriptCore/ChangeLog
  4. +0 −2 Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -1,3 +1,15 @@
2018-11-21 Saam barati <sbarati@apple.com>

DFGSpeculativeJIT should not &= exitOK with mayExit(node)
https://bugs.webkit.org/show_bug.cgi?id=191897
<rdar://problem/45871998>

Reviewed by Mark Lam.

* stress/exitok-is-not-the-same-as-mayExit.js: Added.
(bar):
(foo):

2018-11-21 Saam barati <sbarati@apple.com>

Fix assertion in KnownCellUse inside SpeculativeJIT::speculate
@@ -0,0 +1,19 @@
//@ runDefault("--useAccessInlining=0")

function bar(ranges) {
for (const [z] of ranges) {
let ys = [];
for (y = 0; y <= 100000; y++) {
ys[y] = false;
}
}
}

function foo() {
let iterator = [][Symbol.iterator]();
iterator.x = 1;
}

bar([ [], [], [], [], [], [], [], [], [], [], [] ]);
foo();
bar([ [], [] ]);
@@ -1,3 +1,36 @@
2018-11-21 Saam barati <sbarati@apple.com>

DFGSpeculativeJIT should not &= exitOK with mayExit(node)
https://bugs.webkit.org/show_bug.cgi?id=191897
<rdar://problem/45871998>

Reviewed by Mark Lam.

exitOK is a statement about it being legal to exit. mayExit() is about being
conservative and returning false only if an OSR exit *could never* happen.
mayExit() tries to be as smart as possible to see if it can return false.
It can't return false if a runtime exit *could* happen. However, there is
code in the compiler where mayExit() returns false (because it uses data
generated from AI about type checks being proved), but the code we emit in the
compiler backend unconditionally generates an OSR exit, even if that exit may
never execute. For example, let's say we have this IR:

SomeNode(Boolean:@input)

And we always emit code like this as a way of emitting a boolean type check:

jump L1 if input == true
jump L1 if input == false
emit an OSR exit

In such a program, when we generate the above OSR exit, in a validationEnabled()
build, and if @input is proved to be a boolean, we'll end up crashing because we
have the bogus assertion saying !exitOK. This is one reason why things are cleaner
if we don't conflate mayExit() with exitOK.

* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileCurrentBlock):

2018-11-21 Saam barati <sbarati@apple.com>

Fix assertion in KnownCellUse inside SpeculativeJIT::speculate
@@ -1840,8 +1840,6 @@ void SpeculativeJIT::compileCurrentBlock()
m_interpreter.executeKnownEdgeTypes(m_currentNode);
m_jit.setForNode(m_currentNode);
m_origin = m_currentNode->origin;
if (validationEnabled())
m_origin.exitOK &= mayExit(m_jit.graph(), m_currentNode) == Exits;
m_lastGeneratedNode = m_currentNode->op();

ASSERT(m_currentNode->shouldGenerate());

0 comments on commit 58f5642

Please sign in to comment.