Title: [91883] trunk/Source/_javascript_Core
Revision
91883
Author
[email protected]
Date
2011-07-27 16:48:56 -0700 (Wed, 27 Jul 2011)

Log Message

https://bugs.webkit.org/show_bug.cgi?id=65294
DFG JIT - may speculate based on wrong arguments.

Reviewed by Oliver Hunt

In the case of a DFG compiled function calling to and compiling a second function that
also compiles through the DFG JIT (i.e. compilation triggered with DFGOperations.cpp),
we call compileFor passing the caller functions exec state, rather than the callee's.
This may lead to mis-optimization, since the DFG compiler will example the exec state's
arguments on the assumption that these will be passed to the callee - it is wanting the
callee exec state, not the caller's exec state.

Fixing this for all cases of compilation is tricksy, due to the way the numeric sort
function is compiled, & the structure of the calls in the Interpreter::execute methods.
Only fix for compilation from the JIT, in other calls don't speculate based on arguments
for now.

* dfg/DFGOperations.cpp:
* runtime/Executable.cpp:
(JSC::tryDFGCompile):
(JSC::tryDFGCompileFunction):
(JSC::FunctionExecutable::compileForCallInternal):
* runtime/Executable.h:
(JSC::FunctionExecutable::compileForCall):
(JSC::FunctionExecutable::compileFor):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (91882 => 91883)


--- trunk/Source/_javascript_Core/ChangeLog	2011-07-27 23:40:36 UTC (rev 91882)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-07-27 23:48:56 UTC (rev 91883)
@@ -1,3 +1,31 @@
+2011-07-27  Gavin Barraclough  <[email protected]>
+
+        https://bugs.webkit.org/show_bug.cgi?id=65294
+        DFG JIT - may speculate based on wrong arguments.
+
+        Reviewed by Oliver Hunt
+
+        In the case of a DFG compiled function calling to and compiling a second function that
+        also compiles through the DFG JIT (i.e. compilation triggered with DFGOperations.cpp),
+        we call compileFor passing the caller functions exec state, rather than the callee's.
+        This may lead to mis-optimization, since the DFG compiler will example the exec state's
+        arguments on the assumption that these will be passed to the callee - it is wanting the
+        callee exec state, not the caller's exec state.
+
+        Fixing this for all cases of compilation is tricksy, due to the way the numeric sort
+        function is compiled, & the structure of the calls in the Interpreter::execute methods.
+        Only fix for compilation from the JIT, in other calls don't speculate based on arguments
+        for now.
+
+        * dfg/DFGOperations.cpp:
+        * runtime/Executable.cpp:
+        (JSC::tryDFGCompile):
+        (JSC::tryDFGCompileFunction):
+        (JSC::FunctionExecutable::compileForCallInternal):
+        * runtime/Executable.h:
+        (JSC::FunctionExecutable::compileForCall):
+        (JSC::FunctionExecutable::compileFor):
+
 2011-07-27  Oliver Hunt  <[email protected]>
 
         Handle callback oriented JSONP

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (91882 => 91883)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2011-07-27 23:40:36 UTC (rev 91882)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2011-07-27 23:48:56 UTC (rev 91883)
@@ -529,8 +529,9 @@
     if (executable->isHostFunction())
         codePtr = executable->generatedJITCodeFor(kind).addressForCall();
     else {
+        execCallee->setScopeChain(callee->scope());
         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
-        JSObject* error = functionExecutable->compileFor(exec, callee->scope(), kind);
+        JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind);
         if (error) {
             globalData->exception = createStackOverflowError(exec);
             return 0;
@@ -540,7 +541,6 @@
             codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
         else
             codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
-        execCallee->setScopeChain(callee->scope());
     }
     CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(returnAddress);
     if (!callLinkInfo.seenOnce())
@@ -574,16 +574,16 @@
         return handleHostCall(execCallee, calleeAsValue, kind);
     
     JSFunction* function = asFunction(calleeAsFunctionCell);
+    execCallee->setScopeChain(function->scopeUnchecked());
     ExecutableBase* executable = function->executable();
     if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
-        JSObject* error = functionExecutable->compileFor(exec, function->scope(), kind);
+        JSObject* error = functionExecutable->compileFor(execCallee, function->scope(), kind);
         if (error) {
             exec->globalData().exception = error;
             return 0;
         }
     }
-    execCallee->setScopeChain(function->scopeUnchecked());
     return executable->generatedJITCodeWithArityCheckFor(kind).executableAddress();
 }
 

Modified: trunk/Source/_javascript_Core/runtime/Executable.cpp (91882 => 91883)


--- trunk/Source/_javascript_Core/runtime/Executable.cpp	2011-07-27 23:40:36 UTC (rev 91882)
+++ trunk/Source/_javascript_Core/runtime/Executable.cpp	2011-07-27 23:48:56 UTC (rev 91883)
@@ -57,14 +57,12 @@
     if (!parse(dfg, globalData, codeBlock))
         return false;
 
-    dfg.predictArgumentTypes(exec);
-
     DFG::JITCompiler dataFlowJIT(globalData, dfg, codeBlock);
     dataFlowJIT.compile(jitCode);
     return true;
 }
 
-static bool tryDFGCompileFunction(ExecState* exec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
+static bool tryDFGCompileFunction(ExecState* exec, ExecState* calleeArgsExec, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
 {
 #if ENABLE(DFG_JIT_RESTRICTIONS)
     // FIXME: No flow control yet supported, don't bother scanning the bytecode if there are any jump targets.
@@ -77,7 +75,8 @@
     if (!parse(dfg, globalData, codeBlock))
         return false;
 
-    dfg.predictArgumentTypes(exec);
+    if (calleeArgsExec)
+        dfg.predictArgumentTypes(calleeArgsExec);
 
     DFG::JITCompiler dataFlowJIT(globalData, dfg, codeBlock);
     dataFlowJIT.compileFunction(jitCode, jitCodeWithArityCheck);
@@ -85,7 +84,7 @@
 }
 #else
 static bool tryDFGCompile(ExecState*, CodeBlock*, JITCode&) { return false; }
-static bool tryDFGCompileFunction(ExecState*, CodeBlock*, JITCode&, MacroAssemblerCodePtr&) { return false; }
+static bool tryDFGCompileFunction(ExecState*, ExecState*, CodeBlock*, JITCode&, MacroAssemblerCodePtr&) { return false; }
 #endif
 
 class ExecutableFinalizer : public WeakHandleOwner {
@@ -317,7 +316,7 @@
         m_programCodeBlock->visitAggregate(visitor);
 }
 
-JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
+JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode, ExecState* calleeArgsExec)
 {
     JSObject* exception = 0;
     JSGlobalData* globalData = scopeChainNode->globalData;
@@ -351,7 +350,7 @@
 
 #if ENABLE(JIT)
     if (exec->globalData().canUseJIT()) {
-        bool dfgCompiled = tryDFGCompileFunction(exec, m_codeBlockForCall.get(), m_jitCodeForCall, m_jitCodeForCallWithArityCheck);
+        bool dfgCompiled = tryDFGCompileFunction(exec, calleeArgsExec, m_codeBlockForCall.get(), m_jitCodeForCall, m_jitCodeForCallWithArityCheck);
         if (!dfgCompiled)
             m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_codeBlockForCall.get(), &m_jitCodeForCallWithArityCheck);
 

Modified: trunk/Source/_javascript_Core/runtime/Executable.h (91882 => 91883)


--- trunk/Source/_javascript_Core/runtime/Executable.h	2011-07-27 23:40:36 UTC (rev 91882)
+++ trunk/Source/_javascript_Core/runtime/Executable.h	2011-07-27 23:48:56 UTC (rev 91883)
@@ -405,12 +405,12 @@
             return *m_codeBlockForConstruct;
         }
 
-        JSObject* compileForCall(ExecState* exec, ScopeChainNode* scopeChainNode)
+        JSObject* compileForCall(ExecState* exec, ScopeChainNode* scopeChainNode, ExecState* calleeArgsExec = 0)
         {
             ASSERT(exec->globalData().dynamicGlobalObject);
             JSObject* error = 0;
             if (!m_codeBlockForCall)
-                error = compileForCallInternal(exec, scopeChainNode);
+                error = compileForCallInternal(exec, scopeChainNode, calleeArgsExec);
             ASSERT(!error == !!m_codeBlockForCall);
             return error;
         }
@@ -449,8 +449,14 @@
         
         JSObject* compileFor(ExecState* exec, ScopeChainNode* scopeChainNode, CodeSpecializationKind kind)
         {
+            // compileFor should only be called with a callframe set up to call this function,
+            // since we will make speculative optimizations based on the arguments.
+            ASSERT(exec->callee());
+            ASSERT(exec->callee()->inherits(&JSFunction::s_info));
+            ASSERT(asFunction(exec->callee())->jsExecutable() == this);
+
             if (kind == CodeForCall)
-                return compileForCall(exec, scopeChainNode);
+                return compileForCall(exec, scopeChainNode, exec);
             ASSERT(kind == CodeForConstruct);
             return compileForConstruct(exec, scopeChainNode);
         }
@@ -491,7 +497,7 @@
         FunctionExecutable(JSGlobalData&, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool, int firstLine, int lastLine);
         FunctionExecutable(ExecState*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool, int firstLine, int lastLine);
 
-        JSObject* compileForCallInternal(ExecState*, ScopeChainNode*);
+        JSObject* compileForCallInternal(ExecState*, ScopeChainNode*, ExecState* calleeArgsExec);
         JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*);
         
         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to