Title: [258874] trunk
Revision
258874
Author
[email protected]
Date
2020-03-23 14:09:21 -0700 (Mon, 23 Mar 2020)

Log Message

[JSC] DFG OSR exit cannot find StructureStubInfo for put_by_val if CodeBlock is once converved from Baseline to LLInt
https://bugs.webkit.org/show_bug.cgi?id=209327
<rdar://problem/60631061>

Reviewed by Saam Barati.

JSTests:

* stress/osr-exit-attempts-to-find-stubinfo-which-is-cleared-by-previous-baseline-to-llint-conversion.js: Added.
(setter):
(foo):

Source/_javascript_Core:

DFG compiles op_put_by_val as PutById and inlines SetterCall only when DFG found StructureStubInfo for this op_put_by_val.
However, it is still possible that DFG OSR exit cannot find StructureStubInfo for SetterCall generated by op_put_by_val.
Let's consider the following scenario.

    1. Baseline CodeBlock (A) is compiled.
    2. (A) gets DFG (B).
    3. Since (A) collects enough information for put_by_val, (B) can get StructureStubInfo from (A) and compile it as inlined Setter call.
    4. (A)'s JITData is destroyed since it is not executed. Then, (A) becomes LLInt.
    5. The CodeBlock inlining (A) gets OSR exit. So (A) is executed and (A) eventually gets Baseline CodeBlock again.
    6. (B) gets OSR exit. (B) attempts to search for StructureStubInfo in (A) for PutById (originally, put_by_val). But it does not exist since (A)'s JITData is cleared once.

We should just link to doneTarget of ByValInfo when the SetterCall is generated by `op_put_by_val`. ByValInfo and its doneTarget always exists per op_put_by_val.

* bytecode/ByValInfo.h:
(JSC::ByValInfo::ByValInfo):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::findByValInfo):
* bytecode/CodeBlock.h:
* dfg/DFGOSRExitCompilerCommon.cpp:
(JSC::DFG::callerReturnPC):
* jit/JITOpcodes.cpp:
(JSC::JIT::privateCompileHasIndexedProperty):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::privateCompileHasIndexedProperty):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::privateCompilePutByVal):
(JSC::JIT::privateCompilePutByValWithCachedId):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (258873 => 258874)


--- trunk/JSTests/ChangeLog	2020-03-23 21:00:01 UTC (rev 258873)
+++ trunk/JSTests/ChangeLog	2020-03-23 21:09:21 UTC (rev 258874)
@@ -1,3 +1,15 @@
+2020-03-23  Yusuke Suzuki  <[email protected]>
+
+        [JSC] DFG OSR exit cannot find StructureStubInfo for put_by_val if CodeBlock is once converved from Baseline to LLInt
+        https://bugs.webkit.org/show_bug.cgi?id=209327
+        <rdar://problem/60631061>
+
+        Reviewed by Saam Barati.
+
+        * stress/osr-exit-attempts-to-find-stubinfo-which-is-cleared-by-previous-baseline-to-llint-conversion.js: Added.
+        (setter):
+        (foo):
+
 2020-03-23  Ross Kirsling  <[email protected]>
 
         Catch parameters must not be lexically redeclared

Added: trunk/JSTests/stress/osr-exit-attempts-to-find-stubinfo-which-is-cleared-by-previous-baseline-to-llint-conversion.js (0 => 258874)


--- trunk/JSTests/stress/osr-exit-attempts-to-find-stubinfo-which-is-cleared-by-previous-baseline-to-llint-conversion.js	                        (rev 0)
+++ trunk/JSTests/stress/osr-exit-attempts-to-find-stubinfo-which-is-cleared-by-previous-baseline-to-llint-conversion.js	2020-03-23 21:09:21 UTC (rev 258874)
@@ -0,0 +1,18 @@
+//@ runDefault("--slowPathAllocsBetweenGCs=50", "--jitPolicyScale=0", "--watchdog=100", "--watchdog-exception-ok")
+let o = {};
+let eff = 'f';
+
+function setter(s) {
+  +s;
+  [arguments];
+}
+
+Object.defineProperty(o, eff, { set: setter });
+
+function foo() {
+  o[eff] = null;
+}
+
+for (let i = 0; i < 100000000; i++) {
+  foo();
+}

Modified: trunk/Source/_javascript_Core/ChangeLog (258873 => 258874)


--- trunk/Source/_javascript_Core/ChangeLog	2020-03-23 21:00:01 UTC (rev 258873)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-03-23 21:09:21 UTC (rev 258874)
@@ -1,3 +1,39 @@
+2020-03-23  Yusuke Suzuki  <[email protected]>
+
+        [JSC] DFG OSR exit cannot find StructureStubInfo for put_by_val if CodeBlock is once converved from Baseline to LLInt
+        https://bugs.webkit.org/show_bug.cgi?id=209327
+        <rdar://problem/60631061>
+
+        Reviewed by Saam Barati.
+
+        DFG compiles op_put_by_val as PutById and inlines SetterCall only when DFG found StructureStubInfo for this op_put_by_val.
+        However, it is still possible that DFG OSR exit cannot find StructureStubInfo for SetterCall generated by op_put_by_val.
+        Let's consider the following scenario.
+
+            1. Baseline CodeBlock (A) is compiled.
+            2. (A) gets DFG (B).
+            3. Since (A) collects enough information for put_by_val, (B) can get StructureStubInfo from (A) and compile it as inlined Setter call.
+            4. (A)'s JITData is destroyed since it is not executed. Then, (A) becomes LLInt.
+            5. The CodeBlock inlining (A) gets OSR exit. So (A) is executed and (A) eventually gets Baseline CodeBlock again.
+            6. (B) gets OSR exit. (B) attempts to search for StructureStubInfo in (A) for PutById (originally, put_by_val). But it does not exist since (A)'s JITData is cleared once.
+
+        We should just link to doneTarget of ByValInfo when the SetterCall is generated by `op_put_by_val`. ByValInfo and its doneTarget always exists per op_put_by_val.
+
+        * bytecode/ByValInfo.h:
+        (JSC::ByValInfo::ByValInfo):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::findByValInfo):
+        * bytecode/CodeBlock.h:
+        * dfg/DFGOSRExitCompilerCommon.cpp:
+        (JSC::DFG::callerReturnPC):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::privateCompileHasIndexedProperty):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::privateCompileHasIndexedProperty):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::privateCompilePutByVal):
+        (JSC::JIT::privateCompilePutByValWithCachedId):
+
 2020-03-23  Ross Kirsling  <[email protected]>
 
         Unreviewed, address Yusuke's feedback on r258801.

Modified: trunk/Source/_javascript_Core/bytecode/ByValInfo.h (258873 => 258874)


--- trunk/Source/_javascript_Core/bytecode/ByValInfo.h	2020-03-23 21:00:01 UTC (rev 258873)
+++ trunk/Source/_javascript_Core/bytecode/ByValInfo.h	2020-03-23 21:09:21 UTC (rev 258874)
@@ -227,11 +227,11 @@
 struct ByValInfo {
     ByValInfo() { }
 
-    ByValInfo(BytecodeIndex bytecodeIndex, CodeLocationJump<JSInternalPtrTag> notIndexJump, CodeLocationJump<JSInternalPtrTag> badTypeJump, CodeLocationLabel<ExceptionHandlerPtrTag> exceptionHandler, JITArrayMode arrayMode, ArrayProfile* arrayProfile, CodeLocationLabel<JSInternalPtrTag> badTypeDoneTarget, CodeLocationLabel<JSInternalPtrTag> badTypeNextHotPathTarget, CodeLocationLabel<JSInternalPtrTag> slowPathTarget)
+    ByValInfo(BytecodeIndex bytecodeIndex, CodeLocationJump<JSInternalPtrTag> notIndexJump, CodeLocationJump<JSInternalPtrTag> badTypeJump, CodeLocationLabel<ExceptionHandlerPtrTag> exceptionHandler, JITArrayMode arrayMode, ArrayProfile* arrayProfile, CodeLocationLabel<JSInternalPtrTag> doneTarget, CodeLocationLabel<JSInternalPtrTag> badTypeNextHotPathTarget, CodeLocationLabel<JSInternalPtrTag> slowPathTarget)
         : notIndexJump(notIndexJump)
         , badTypeJump(badTypeJump)
         , exceptionHandler(exceptionHandler)
-        , badTypeDoneTarget(badTypeDoneTarget)
+        , doneTarget(doneTarget)
         , badTypeNextHotPathTarget(badTypeNextHotPathTarget)
         , slowPathTarget(slowPathTarget)
         , arrayProfile(arrayProfile)
@@ -249,7 +249,7 @@
     CodeLocationJump<JSInternalPtrTag> notIndexJump;
     CodeLocationJump<JSInternalPtrTag> badTypeJump;
     CodeLocationLabel<ExceptionHandlerPtrTag> exceptionHandler;
-    CodeLocationLabel<JSInternalPtrTag> badTypeDoneTarget;
+    CodeLocationLabel<JSInternalPtrTag> doneTarget;
     CodeLocationLabel<JSInternalPtrTag> badTypeNextHotPathTarget;
     CodeLocationLabel<JSInternalPtrTag> slowPathTarget;
     ArrayProfile* arrayProfile;

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (258873 => 258874)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2020-03-23 21:00:01 UTC (rev 258873)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2020-03-23 21:09:21 UTC (rev 258874)
@@ -1557,6 +1557,18 @@
     return nullptr;
 }
 
+ByValInfo* CodeBlock::findByValInfo(CodeOrigin codeOrigin)
+{
+    ConcurrentJSLocker locker(m_lock);
+    if (auto* jitData = m_jitData.get()) {
+        for (ByValInfo* byValInfo : jitData->m_byValInfos) {
+            if (byValInfo->bytecodeIndex == codeOrigin.bytecodeIndex())
+                return byValInfo;
+        }
+    }
+    return nullptr;
+}
+
 ByValInfo* CodeBlock::addByValInfo()
 {
     ConcurrentJSLocker locker(m_lock);

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (258873 => 258874)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2020-03-23 21:00:01 UTC (rev 258873)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2020-03-23 21:09:21 UTC (rev 258874)
@@ -312,9 +312,10 @@
 
     StructureStubInfo* addStubInfo(AccessType);
 
-    // O(n) operation. Use getStubInfoMap() unless you really only intend to get one
-    // stub info.
+    // O(n) operation. Use getICStatusMap() unless you really only intend to get one stub info.
     StructureStubInfo* findStubInfo(CodeOrigin);
+    // O(n) operation. Use getICStatusMap() unless you really only intend to get one by-val-info.
+    ByValInfo* findByValInfo(CodeOrigin);
 
     ByValInfo* addByValInfo();
 

Modified: trunk/Source/_javascript_Core/dfg/DFGOSRExitCompilerCommon.cpp (258873 => 258874)


--- trunk/Source/_javascript_Core/dfg/DFGOSRExitCompilerCommon.cpp	2020-03-23 21:00:01 UTC (rev 258873)
+++ trunk/Source/_javascript_Core/dfg/DFGOSRExitCompilerCommon.cpp	2020-03-23 21:09:21 UTC (rev 258874)
@@ -154,8 +154,8 @@
 
     MacroAssemblerCodePtr<JSEntryPtrTag> jumpTarget;
 
+    const Instruction& callInstruction = *baselineCodeBlockForCaller->instructions().at(callBytecodeIndex).ptr();
     if (callerIsLLInt) {
-        const Instruction& callInstruction = *baselineCodeBlockForCaller->instructions().at(callBytecodeIndex).ptr();
 #define LLINT_RETURN_LOCATION(name) (callInstruction.isWide16() ? LLInt::getWide16CodePtr<JSEntryPtrTag>(name##_return_location) : (callInstruction.isWide32() ? LLInt::getWide32CodePtr<JSEntryPtrTag>(name##_return_location) : LLInt::getCodePtr<JSEntryPtrTag>(name##_return_location)))
 
         switch (trueCallerCallKind) {
@@ -213,10 +213,23 @@
 
         case InlineCallFrame::GetterCall:
         case InlineCallFrame::SetterCall: {
-            StructureStubInfo* stubInfo =
-                baselineCodeBlockForCaller->findStubInfo(CodeOrigin(callBytecodeIndex));
+            if (callInstruction.opcodeID() == op_put_by_val) {
+                // We compile op_put_by_val as PutById and inlines SetterCall only when we found StructureStubInfo for this op_put_by_val.
+                // But still it is possible that we cannot find StructureStubInfo here. Let's consider the following scenario.
+                // 1. Baseline CodeBlock (A) is compiled.
+                // 2. (A) gets DFG (B).
+                // 3. Since (A) collects enough information for put_by_val, (B) can get StructureStubInfo from (A) and copmile it as inlined Setter call.
+                // 4. (A)'s JITData is destroyed since it is not executed. Then, (A) becomes LLInt.
+                // 5. The CodeBlock inlining (A) gets OSR exit. So (A) is executed and (A) eventually gets Baseline CodeBlock again.
+                // 6. (B) gets OSR exit. (B) attempts to search for StructureStubInfo in (A) for PutById (originally, put_by_val). But it does not exist since (A)'s JITData is cleared once.
+                ByValInfo* byValInfo = baselineCodeBlockForCaller->findByValInfo(CodeOrigin(callBytecodeIndex));
+                RELEASE_ASSERT(byValInfo);
+                jumpTarget = byValInfo->doneTarget.retagged<JSEntryPtrTag>();
+                break;
+            }
+
+            StructureStubInfo* stubInfo = baselineCodeBlockForCaller->findStubInfo(CodeOrigin(callBytecodeIndex));
             RELEASE_ASSERT(stubInfo);
-
             jumpTarget = stubInfo->doneLocation.retagged<JSEntryPtrTag>();
             break;
         }

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (258873 => 258874)


--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2020-03-23 21:00:01 UTC (rev 258873)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2020-03-23 21:09:21 UTC (rev 258874)
@@ -1285,7 +1285,7 @@
     patchBuffer.link(badType, byValInfo->slowPathTarget);
     patchBuffer.link(slowCases, byValInfo->slowPathTarget);
 
-    patchBuffer.link(done, byValInfo->badTypeDoneTarget);
+    patchBuffer.link(done, byValInfo->doneTarget);
 
     byValInfo->stubRoutine = FINALIZE_CODE_FOR_STUB(
         m_codeBlock, patchBuffer, JITStubRoutinePtrTag,

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (258873 => 258874)


--- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2020-03-23 21:00:01 UTC (rev 258873)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2020-03-23 21:09:21 UTC (rev 258874)
@@ -1158,7 +1158,7 @@
     patchBuffer.link(badType, byValInfo->slowPathTarget);
     patchBuffer.link(slowCases, byValInfo->slowPathTarget);
 
-    patchBuffer.link(done, byValInfo->badTypeDoneTarget);
+    patchBuffer.link(done, byValInfo->doneTarget);
 
     byValInfo->stubRoutine = FINALIZE_CODE_FOR_STUB(
         m_codeBlock, patchBuffer, JITStubRoutinePtrTag,

Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp (258873 => 258874)


--- trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2020-03-23 21:00:01 UTC (rev 258873)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2020-03-23 21:09:21 UTC (rev 258874)
@@ -1337,7 +1337,7 @@
     LinkBuffer patchBuffer(*this, m_codeBlock);
     patchBuffer.link(badType, byValInfo->slowPathTarget);
     patchBuffer.link(slowCases, byValInfo->slowPathTarget);
-    patchBuffer.link(done, byValInfo->badTypeDoneTarget);
+    patchBuffer.link(done, byValInfo->doneTarget);
     if (needsLinkForWriteBarrier) {
         ASSERT(removeCodePtrTag(m_calls.last().callee.executableAddress()) == removeCodePtrTag(operationWriteBarrierSlowPath));
         patchBuffer.link(m_calls.last().from, m_calls.last().callee);
@@ -1377,7 +1377,7 @@
     ConcurrentJSLocker locker(m_codeBlock->m_lock);
     LinkBuffer patchBuffer(*this, m_codeBlock);
     patchBuffer.link(slowCases, byValInfo->slowPathTarget);
-    patchBuffer.link(doneCases, byValInfo->badTypeDoneTarget);
+    patchBuffer.link(doneCases, byValInfo->doneTarget);
     if (!m_exceptionChecks.empty())
         patchBuffer.link(m_exceptionChecks, byValInfo->exceptionHandler);
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to