Title: [139136] trunk
Revision
139136
Author
[email protected]
Date
2013-01-08 17:11:32 -0800 (Tue, 08 Jan 2013)

Log Message

DFG shouldn't treat the 'this' argument as being captured if a code block uses arguments
https://bugs.webkit.org/show_bug.cgi?id=106398
<rdar://problem/12439776>

Source/_javascript_Core: 

Reviewed by Mark Hahnenberg.
        
This is a possible optimization for inlined calls, and fixes crashes for inlined constructors, in the case
that the inlined code used arguments. The problem was that assuming that 'this' was captured implies the
assumption that it was initialized by the caller, which is wrong for constructors and this.
        
Also added a pretty essential DFG IR validation rule: we shouldn't have any live locals at the top of the
root block. This helps to catch this bug: our assumption that 'this' was captured in an inlined constructor
that used arguments led to liveness for the temporary that would have held 'this' in the caller being
propagated all the way up to the entrypoint of the function.

* bytecode/CodeBlock.h:
(JSC::CodeBlock::isCaptured):
* dfg/DFGValidate.cpp:
(JSC::DFG::Validate::validate):
(JSC::DFG::Validate::reportValidationContext):
(Validate):
(JSC::DFG::Validate::dumpGraphIfAppropriate):

LayoutTests: 

Reviewed by Mark Hahnenberg.

* fast/js/dfg-inline-constructor-that-uses-arguments-expected.txt: Added.
* fast/js/dfg-inline-constructor-that-uses-arguments.html: Added.
* fast/js/jsc-test-list:
* fast/js/script-tests/dfg-inline-constructor-that-uses-arguments.js: Added.
(Foo):
(bar):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (139135 => 139136)


--- trunk/LayoutTests/ChangeLog	2013-01-09 00:59:43 UTC (rev 139135)
+++ trunk/LayoutTests/ChangeLog	2013-01-09 01:11:32 UTC (rev 139136)
@@ -1,3 +1,18 @@
+2013-01-08  Filip Pizlo  <[email protected]>
+
+        DFG shouldn't treat the 'this' argument as being captured if a code block uses arguments
+        https://bugs.webkit.org/show_bug.cgi?id=106398
+        <rdar://problem/12439776>
+
+        Reviewed by Mark Hahnenberg.
+
+        * fast/js/dfg-inline-constructor-that-uses-arguments-expected.txt: Added.
+        * fast/js/dfg-inline-constructor-that-uses-arguments.html: Added.
+        * fast/js/jsc-test-list:
+        * fast/js/script-tests/dfg-inline-constructor-that-uses-arguments.js: Added.
+        (Foo):
+        (bar):
+
 2013-01-08  Viatcheslav Ostapenko  <[email protected]>
 
         [EFL][WK2] WebGL test cases are sometimes crashing

Added: trunk/LayoutTests/fast/js/dfg-inline-constructor-that-uses-arguments-expected.txt (0 => 139136)


--- trunk/LayoutTests/fast/js/dfg-inline-constructor-that-uses-arguments-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-inline-constructor-that-uses-arguments-expected.txt	2013-01-09 01:11:32 UTC (rev 139136)
@@ -0,0 +1,209 @@
+Tests that we can inline a constructor that uses arguments without failing DFG validation.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS bar().x is 42
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/js/dfg-inline-constructor-that-uses-arguments.html (0 => 139136)


--- trunk/LayoutTests/fast/js/dfg-inline-constructor-that-uses-arguments.html	                        (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-inline-constructor-that-uses-arguments.html	2013-01-09 01:11:32 UTC (rev 139136)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Modified: trunk/LayoutTests/fast/js/jsc-test-list (139135 => 139136)


--- trunk/LayoutTests/fast/js/jsc-test-list	2013-01-09 00:59:43 UTC (rev 139135)
+++ trunk/LayoutTests/fast/js/jsc-test-list	2013-01-09 01:11:32 UTC (rev 139136)
@@ -131,6 +131,7 @@
 fast/js/dfg-inline-arguments-use-from-getter
 fast/js/dfg-inline-arguments-use-from-uninlined-code
 fast/js/dfg-inline-constant
+fast/js/dfg-inline-constructor-that-uses-arguments
 fast/js/dfg-inline-early-return
 fast/js/dfg-inline-function-dot-caller
 fast/js/dfg-inline-many-blocks

Added: trunk/LayoutTests/fast/js/script-tests/dfg-inline-constructor-that-uses-arguments.js (0 => 139136)


--- trunk/LayoutTests/fast/js/script-tests/dfg-inline-constructor-that-uses-arguments.js	                        (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/dfg-inline-constructor-that-uses-arguments.js	2013-01-09 01:11:32 UTC (rev 139136)
@@ -0,0 +1,14 @@
+description(
+"Tests that we can inline a constructor that uses arguments without failing DFG validation."
+);
+
+function Foo() {
+    this.x = arguments[0];
+}
+
+function bar() {
+    return new Foo(42);
+}
+
+for (var i = 0; i < 200; ++i)
+    shouldBe("bar().x", "42");

Modified: trunk/Source/_javascript_Core/ChangeLog (139135 => 139136)


--- trunk/Source/_javascript_Core/ChangeLog	2013-01-09 00:59:43 UTC (rev 139135)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-01-09 01:11:32 UTC (rev 139136)
@@ -1,5 +1,30 @@
 2013-01-08  Filip Pizlo  <[email protected]>
 
+        DFG shouldn't treat the 'this' argument as being captured if a code block uses arguments
+        https://bugs.webkit.org/show_bug.cgi?id=106398
+        <rdar://problem/12439776>
+
+        Reviewed by Mark Hahnenberg.
+        
+        This is a possible optimization for inlined calls, and fixes crashes for inlined constructors, in the case
+        that the inlined code used arguments. The problem was that assuming that 'this' was captured implies the
+        assumption that it was initialized by the caller, which is wrong for constructors and this.
+        
+        Also added a pretty essential DFG IR validation rule: we shouldn't have any live locals at the top of the
+        root block. This helps to catch this bug: our assumption that 'this' was captured in an inlined constructor
+        that used arguments led to liveness for the temporary that would have held 'this' in the caller being
+        propagated all the way up to the entrypoint of the function.
+
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::isCaptured):
+        * dfg/DFGValidate.cpp:
+        (JSC::DFG::Validate::validate):
+        (JSC::DFG::Validate::reportValidationContext):
+        (Validate):
+        (JSC::DFG::Validate::dumpGraphIfAppropriate):
+
+2013-01-08  Filip Pizlo  <[email protected]>
+
         REGRESSION (r138921): Crash in JSC::Arguments::create
         https://bugs.webkit.org/show_bug.cgi?id=106329
         <rdar://problem/12974196>

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (139135 => 139136)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2013-01-09 00:59:43 UTC (rev 139135)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2013-01-09 01:11:32 UTC (rev 139136)
@@ -594,12 +594,12 @@
         
         bool isCaptured(int operand, InlineCallFrame* inlineCallFrame = 0) const
         {
-            if (inlineCallFrame && !operandIsArgument(operand))
+            if (operandIsArgument(operand))
+                return operandToArgument(operand) && usesArguments();
+
+            if (inlineCallFrame)
                 return inlineCallFrame->capturedVars.get(operand);
 
-            if (operandIsArgument(operand))
-                return usesArguments();
-
             // The activation object isn't in the captured region, but it's "captured"
             // in the sense that stores to its location can be observed indirectly.
             if (needsActivation() && operand == activationRegister())

Modified: trunk/Source/_javascript_Core/dfg/DFGValidate.cpp (139135 => 139136)


--- trunk/Source/_javascript_Core/dfg/DFGValidate.cpp	2013-01-09 00:59:43 UTC (rev 139135)
+++ trunk/Source/_javascript_Core/dfg/DFGValidate.cpp	2013-01-09 01:11:32 UTC (rev 139136)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,6 +28,7 @@
 
 #if ENABLE(DFG_JIT)
 
+#include "CodeBlockWithJITType.h"
 #include <wtf/Assertions.h>
 #include <wtf/BitVector.h>
 
@@ -76,6 +77,11 @@
         // NB. This code is not written for performance, since it is not intended to run
         // in release builds.
         
+        // Validate that all local variables at the head of the root block are dead.
+        BasicBlock* root = m_graph.m_blocks[0].get();
+        for (unsigned i = 0; i < root->variablesAtHead.numberOfLocals(); ++i)
+            V_EQUAL((static_cast<VirtualRegister>(i), 0), NoNode, root->variablesAtHead.local(i));
+        
         // Validate ref counts and uses.
         Vector<unsigned> myRefCounts;
         myRefCounts.fill(0, m_graph.size());
@@ -304,6 +310,11 @@
         dataLogF("@%u -> %s@%u", nodeIndex, useKindToString(edge.useKind()), edge.index());
     }
     
+    void reportValidationContext(VirtualRegister local, BlockIndex blockIndex)
+    {
+        dataLogF("r%d in Block #%u", local, blockIndex);
+    }
+    
     void reportValidationContext(
         VirtualRegister local, BlockIndex sourceBlockIndex, BlockTag, BlockIndex destinationBlockIndex)
     {
@@ -343,7 +354,7 @@
     {
         if (m_graphDumpMode == DontDumpGraph)
             return;
-        dataLogF("Graph at time of failure:\n");
+        dataLog("Graph of ", CodeBlockWithJITType(m_graph.m_codeBlock, JITCode::DFGJIT), " at time of failure:\n");
         m_graph.dump();
     }
 };
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to