Title: [261824] trunk
Revision
261824
Author
keith_mil...@apple.com
Date
2020-05-18 11:56:41 -0700 (Mon, 18 May 2020)

Log Message

OSR loop entry to iterator_next generic needs to CheckNotEmpty on m_next
https://bugs.webkit.org/show_bug.cgi?id=212001

Reviewed by Saam Barati.

JSTests:

* stress/for-of-osr-loop-enter-active-next-differs-from-seen-modes.js: Added.
(foo):

Source/_javascript_Core:

If we happen to OSR enter into iterator_next during a for-of loop
that has only profiled a generic iterator but is actually running
a fast iterator we will incorrectly perform the Call node This
could happen if we loop_hint OSR enter the first time have seen a
fast iterator. If this happens right now, we generate the following
code:

D@113:<!2:loc15>    GetLocal(Check:Untyped:D@198, JS|MustGen|UseAsOther, Function|Empty, loc13(W~/FlushedJSValue), machine:loc10, R:Stack(loc13),Stack(loc5), bc#46, ExitValid)  predicting Function|Empty
  0x4913f1806151: mov -0x58(%rbp), %rsi
D@114:<!0:->    FilterCallLinkStatus(Check:Untyped:D@113, MustGen, (Function: Object: 0x1053f47e0 with butterfly 0x0 (Structure 0x1053f9260:[0x6dad, Function, {}, NonArray, Proto:0x1050fc248]), StructureID: 28077; Executable: next#Ddkruz:[0x1053c0480->0x1053e4a80, BaselineFunctionCall, 54 (StrictMode)]), R:Stack(loc5), W:SideState, bc#46, ExitValid)
D@115:<!6:loc15>    Call(Check:Untyped:D@113, Check:Untyped:D@110, JS|MustGen|VarArgs|UseAsOther, Final, R:World,Stack(loc5), W:Heap, ExitsForExceptions, ClobbersExit, bc#46, ExitValid)  predicting Final
  0x4913f1806155: mov $0x1, 0x10(%rsp)
  0x4913f180615d: mov %rax, 0x18(%rsp)
  0x4913f1806162: mov %rsi, 0x8(%rsp)
  0x4913f1806167: mov %rax, -0xa0(%rbp)
  0x4913f180616e: mov $0x0, 0x24(%rbp)
  0x4913f1806175: mov $0x0, %r11
  0x4913f180617f: cmp %r11, %rsi
  0x4913f1806182: jnz 0x4913f1806192
  0x4913f1806188: call 0x4913f180618d
  0x4913f180618d: jmp 0x4913f18061ae
  0x4913f1806192: mov %rsi, %rax
  0x4913f1806195: mov $0x1050cfcb0, %rdx
  0x4913f180619f: mov $0x1052fab68, %rcx
  0x4913f18061a9: call 0x4913f1801680
  0x4913f18061ae: lea -0xd0(%rbp), %rsp
D@116:<!0:->    MovHint(Check:Untyped:D@115, MustGen, tmp0, R:Stack(loc5), W:SideState, ClobbersExit, bc#46, ExitInvalid)
D@332:<!0:->    InvalidationPoint(MustGen, R:Stack(loc5), W:SideState, Exits, bc#46, exit: bc#46cp#1, ExitValid)
D@335:<!0:->    CheckStructure(Check:Cell:D@115, MustGen, [%B2:Object], R:Stack(loc5),JSCell_structureID, Exits, bc#46, exit: bc#46cp#1, ExitValid)
  0x4913f18061b5: test %rax, %r15
  0x4913f18061b8: jnz 0x4913f18068db
  0x4913f18061be: cmp $0xcaae, (%rax)
  0x4913f18061c4: jnz 0x4913f18068f1

Loc13 in this IR is the location of the next function. Since it's
nullptr, we will pass the initial fast-path value of 0 and make a
garbage call. This is because Call does not know how to handle
empty values. Subsequently, we will fail a structure check for the
Call's result and OSR exit to the getDone checkpoint. The fix for
this is to simply put a CheckNotEmpty at the top of the generic
case. 99.9% of the time this check will be eliminated so it
doesn't really cost anything.

* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (261823 => 261824)


--- trunk/JSTests/ChangeLog	2020-05-18 18:36:55 UTC (rev 261823)
+++ trunk/JSTests/ChangeLog	2020-05-18 18:56:41 UTC (rev 261824)
@@ -1,3 +1,13 @@
+2020-05-18  Keith Miller  <keith_mil...@apple.com>
+
+        OSR loop entry to iterator_next generic needs to CheckNotEmpty on m_next
+        https://bugs.webkit.org/show_bug.cgi?id=212001
+
+        Reviewed by Saam Barati.
+
+        * stress/for-of-osr-loop-enter-active-next-differs-from-seen-modes.js: Added.
+        (foo):
+
 2020-05-18  Paulo Matos  <pma...@igalia.com>
 
         Skip stress test array-buffer-view-watchpoint-can-be-fired-in-really-add-in-dfg.js on MIPS

Added: trunk/JSTests/stress/for-of-osr-loop-enter-active-next-differs-from-seen-modes.js (0 => 261824)


--- trunk/JSTests/stress/for-of-osr-loop-enter-active-next-differs-from-seen-modes.js	                        (rev 0)
+++ trunk/JSTests/stress/for-of-osr-loop-enter-active-next-differs-from-seen-modes.js	2020-05-18 18:56:41 UTC (rev 261824)
@@ -0,0 +1,7 @@
+//@ requireOptions("--jitPolicyScale=0", "--forceDebuggerBytecodeGeneration=1", "--useConcurrentJIT=0", "--minimumOptimizationDelay=6")
+function foo() {
+  Object.fromEntries(arguments);
+  Object.fromEntries([]);
+}
+
+new Promise(foo);

Modified: trunk/Source/_javascript_Core/ChangeLog (261823 => 261824)


--- trunk/Source/_javascript_Core/ChangeLog	2020-05-18 18:36:55 UTC (rev 261823)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-05-18 18:56:41 UTC (rev 261824)
@@ -1,3 +1,56 @@
+2020-05-18  Keith Miller  <keith_mil...@apple.com>
+
+        OSR loop entry to iterator_next generic needs to CheckNotEmpty on m_next
+        https://bugs.webkit.org/show_bug.cgi?id=212001
+
+        Reviewed by Saam Barati.
+
+        If we happen to OSR enter into iterator_next during a for-of loop
+        that has only profiled a generic iterator but is actually running
+        a fast iterator we will incorrectly perform the Call node This
+        could happen if we loop_hint OSR enter the first time have seen a
+        fast iterator. If this happens right now, we generate the following
+        code:
+
+        D@113:<!2:loc15>    GetLocal(Check:Untyped:D@198, JS|MustGen|UseAsOther, Function|Empty, loc13(W~/FlushedJSValue), machine:loc10, R:Stack(loc13),Stack(loc5), bc#46, ExitValid)  predicting Function|Empty
+          0x4913f1806151: mov -0x58(%rbp), %rsi
+        D@114:<!0:->    FilterCallLinkStatus(Check:Untyped:D@113, MustGen, (Function: Object: 0x1053f47e0 with butterfly 0x0 (Structure 0x1053f9260:[0x6dad, Function, {}, NonArray, Proto:0x1050fc248]), StructureID: 28077; Executable: next#Ddkruz:[0x1053c0480->0x1053e4a80, BaselineFunctionCall, 54 (StrictMode)]), R:Stack(loc5), W:SideState, bc#46, ExitValid)
+        D@115:<!6:loc15>    Call(Check:Untyped:D@113, Check:Untyped:D@110, JS|MustGen|VarArgs|UseAsOther, Final, R:World,Stack(loc5), W:Heap, ExitsForExceptions, ClobbersExit, bc#46, ExitValid)  predicting Final
+          0x4913f1806155: mov $0x1, 0x10(%rsp)
+          0x4913f180615d: mov %rax, 0x18(%rsp)
+          0x4913f1806162: mov %rsi, 0x8(%rsp)
+          0x4913f1806167: mov %rax, -0xa0(%rbp)
+          0x4913f180616e: mov $0x0, 0x24(%rbp)
+          0x4913f1806175: mov $0x0, %r11
+          0x4913f180617f: cmp %r11, %rsi
+          0x4913f1806182: jnz 0x4913f1806192
+          0x4913f1806188: call 0x4913f180618d
+          0x4913f180618d: jmp 0x4913f18061ae
+          0x4913f1806192: mov %rsi, %rax
+          0x4913f1806195: mov $0x1050cfcb0, %rdx
+          0x4913f180619f: mov $0x1052fab68, %rcx
+          0x4913f18061a9: call 0x4913f1801680
+          0x4913f18061ae: lea -0xd0(%rbp), %rsp
+        D@116:<!0:->    MovHint(Check:Untyped:D@115, MustGen, tmp0, R:Stack(loc5), W:SideState, ClobbersExit, bc#46, ExitInvalid)
+        D@332:<!0:->    InvalidationPoint(MustGen, R:Stack(loc5), W:SideState, Exits, bc#46, exit: bc#46cp#1, ExitValid)
+        D@335:<!0:->    CheckStructure(Check:Cell:D@115, MustGen, [%B2:Object], R:Stack(loc5),JSCell_structureID, Exits, bc#46, exit: bc#46cp#1, ExitValid)
+          0x4913f18061b5: test %rax, %r15
+          0x4913f18061b8: jnz 0x4913f18068db
+          0x4913f18061be: cmp $0xcaae, (%rax)
+          0x4913f18061c4: jnz 0x4913f18068f1
+
+        Loc13 in this IR is the location of the next function. Since it's
+        nullptr, we will pass the initial fast-path value of 0 and make a
+        garbage call. This is because Call does not know how to handle
+        empty values. Subsequently, we will fail a structure check for the
+        Call's result and OSR exit to the getDone checkpoint. The fix for
+        this is to simply put a CheckNotEmpty at the top of the generic
+        case. 99.9% of the time this check will be eliminated so it
+        doesn't really cost anything.
+
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+
 2020-05-17  Yusuke Suzuki  <ysuz...@apple.com>
 
         Unreviewed, link fix for our internal Debug build

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (261823 => 261824)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2020-05-18 18:36:55 UTC (rev 261823)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2020-05-18 18:56:41 UTC (rev 261824)
@@ -6997,6 +6997,11 @@
                 } else
                     ASSERT(!generatedCase);
 
+                // Our profiling could have been incorrect when we got here. For instance, if we LoopHint OSR enter the first time we would
+                // have seen a fast path, next will be the empty value. When that happens we need to make sure the empty value doesn't flow
+                // into the Call node since call can't handle empty values.
+                addToGraph(CheckNotEmpty, get(bytecode.m_next));
+
                 Terminality terminality = handleCall<OpIteratorNext>(currentInstruction, Call, CallMode::Regular, nextCheckpoint());
                 ASSERT_UNUSED(terminality, terminality == NonTerminal);
                 progressToNextCheckpoint();
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to