Title: [97512] trunk/Source/_javascript_Core
Revision
97512
Author
[email protected]
Date
2011-10-14 15:01:10 -0700 (Fri, 14 Oct 2011)

Log Message

Reflective Arguments retrieval should be hardened for the
possibility of inlining
https://bugs.webkit.org/show_bug.cgi?id=70068

Reviewed by Oliver Hunt.
        
CodeBlock can now track, as part of its RareData, the virtual inline
stack at callsites. CallFrame walking can now rematerialize "inline"
CallFrames by combining the meta-data in CodeBlock with the information
already in the JS stack. Arguments can now safely retrieve the
arguments from inline CallFrames.
        
The DFG already had the notion of a "CodeOrigin" in preparation for
inlining. This notion will now be saved into the CodeBlock, if the DFG
had done inlining. So, CodeOrigin has been moved to bytecode/ and has
been changed to behave more like a struct since that is how it's
meant to be used.

* GNUmakefile.list.am:
* _javascript_Core.vcproj/_javascript_Core/_javascript_Core.vcproj:
* _javascript_Core.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.h:
(JSC::CodeBlock::inlineCallFrames):
(JSC::CodeBlock::codeOrigins):
(JSC::CodeBlock::hasCodeOrigins):
(JSC::CodeBlock::codeOriginForReturn):
* bytecode/CodeOrigin.h: Added.
(JSC::CodeOrigin::CodeOrigin):
(JSC::CodeOrigin::isSet):
(JSC::getCallReturnOffsetForCodeOrigin):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
* dfg/DFGNode.h:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* interpreter/CallFrame.cpp:
(JSC::CallFrame::isInlineCallFrame):
(JSC::CallFrame::trueCallerFrame):
* interpreter/CallFrame.h:
(JSC::ExecState::inlineCallFrame):
(JSC::ExecState::setInlineCallFrame):
(JSC::ExecState::isInlineCallFrame):
(JSC::ExecState::trueCallerFrame):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::findFunctionCallFrame):
* interpreter/Register.h:
(JSC::Register::operator=):
(JSC::Register::inlineCallFrame):
* runtime/Arguments.h:
(JSC::Arguments::getArgumentsData):
(JSC::Arguments::finishCreationButDontCopyRegisters):
(JSC::Arguments::finishCreation):
(JSC::Arguments::finishCreationAndCopyRegisters):
* runtime/Executable.h:
(JSC::FunctionExecutable::parameterCount):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (97511 => 97512)


--- trunk/Source/_javascript_Core/ChangeLog	2011-10-14 22:00:38 UTC (rev 97511)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-10-14 22:01:10 UTC (rev 97512)
@@ -1,3 +1,65 @@
+2011-10-13  Filip Pizlo  <[email protected]>
+
+        Reflective Arguments retrieval should be hardened for the
+        possibility of inlining
+        https://bugs.webkit.org/show_bug.cgi?id=70068
+
+        Reviewed by Oliver Hunt.
+        
+        CodeBlock can now track, as part of its RareData, the virtual inline
+        stack at callsites. CallFrame walking can now rematerialize "inline"
+        CallFrames by combining the meta-data in CodeBlock with the information
+        already in the JS stack. Arguments can now safely retrieve the
+        arguments from inline CallFrames.
+        
+        The DFG already had the notion of a "CodeOrigin" in preparation for
+        inlining. This notion will now be saved into the CodeBlock, if the DFG
+        had done inlining. So, CodeOrigin has been moved to bytecode/ and has
+        been changed to behave more like a struct since that is how it's
+        meant to be used.
+
+        * GNUmakefile.list.am:
+        * _javascript_Core.vcproj/_javascript_Core/_javascript_Core.vcproj:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::inlineCallFrames):
+        (JSC::CodeBlock::codeOrigins):
+        (JSC::CodeBlock::hasCodeOrigins):
+        (JSC::CodeBlock::codeOriginForReturn):
+        * bytecode/CodeOrigin.h: Added.
+        (JSC::CodeOrigin::CodeOrigin):
+        (JSC::CodeOrigin::isSet):
+        (JSC::getCallReturnOffsetForCodeOrigin):
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::link):
+        * dfg/DFGNode.h:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * interpreter/CallFrame.cpp:
+        (JSC::CallFrame::isInlineCallFrame):
+        (JSC::CallFrame::trueCallerFrame):
+        * interpreter/CallFrame.h:
+        (JSC::ExecState::inlineCallFrame):
+        (JSC::ExecState::setInlineCallFrame):
+        (JSC::ExecState::isInlineCallFrame):
+        (JSC::ExecState::trueCallerFrame):
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::findFunctionCallFrame):
+        * interpreter/Register.h:
+        (JSC::Register::operator=):
+        (JSC::Register::inlineCallFrame):
+        * runtime/Arguments.h:
+        (JSC::Arguments::getArgumentsData):
+        (JSC::Arguments::finishCreationButDontCopyRegisters):
+        (JSC::Arguments::finishCreation):
+        (JSC::Arguments::finishCreationAndCopyRegisters):
+        * runtime/Executable.h:
+        (JSC::FunctionExecutable::parameterCount):
+
 2011-10-14  Mark Hahnenberg  <[email protected]>
 
         Rename virtual deleteProperty to deletePropertyVirtual

Modified: trunk/Source/_javascript_Core/GNUmakefile.list.am (97511 => 97512)


--- trunk/Source/_javascript_Core/GNUmakefile.list.am	2011-10-14 22:00:38 UTC (rev 97511)
+++ trunk/Source/_javascript_Core/GNUmakefile.list.am	2011-10-14 22:01:10 UTC (rev 97512)
@@ -83,6 +83,7 @@
 	Source/_javascript_Core/assembler/X86Assembler.h \
 	Source/_javascript_Core/bytecode/CodeBlock.cpp \
 	Source/_javascript_Core/bytecode/CodeBlock.h \
+	Source/_javascript_Core/bytecode/CodeOrigin.h \
 	Source/_javascript_Core/bytecode/EvalCodeCache.h \
 	Source/_javascript_Core/bytecode/Instruction.h \
 	Source/_javascript_Core/bytecode/JumpTable.cpp \

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.vcproj (97511 => 97512)


--- trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.vcproj	2011-10-14 22:00:38 UTC (rev 97511)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.vcproj	2011-10-14 22:01:10 UTC (rev 97512)
@@ -1446,6 +1446,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\bytecode\CodeOrigin.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\bytecode\EvalCodeCache.h"
 				>
 			</File>

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (97511 => 97512)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2011-10-14 22:00:38 UTC (rev 97511)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2011-10-14 22:01:10 UTC (rev 97512)
@@ -64,6 +64,7 @@
 		0F963B2D13F854020002D9B2 /* MetaAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B2A13F853BD0002D9B2 /* MetaAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F963B2F13FC66BB0002D9B2 /* MetaAllocatorHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B2E13FC66AE0002D9B2 /* MetaAllocatorHandle.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F963B3813FC6FE90002D9B2 /* ValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		0FBD7E691447999600481315 /* CodeOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBD7E671447998F00481315 /* CodeOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FC8150A14043BF500CFA603 /* WriteBarrierSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FC8150B14043C0E00CFA603 /* WriteBarrierSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */; };
 		0FC815151405119B00CFA603 /* VTableSpectrum.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC815141405118D00CFA603 /* VTableSpectrum.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -828,6 +829,7 @@
 		0F963B2B13F853C70002D9B2 /* MetaAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MetaAllocator.cpp; sourceTree = "<group>"; };
 		0F963B2E13FC66AE0002D9B2 /* MetaAllocatorHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MetaAllocatorHandle.h; sourceTree = "<group>"; };
 		0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueProfile.h; sourceTree = "<group>"; };
+		0FBD7E671447998F00481315 /* CodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeOrigin.h; sourceTree = "<group>"; };
 		0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WriteBarrierSupport.cpp; sourceTree = "<group>"; };
 		0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WriteBarrierSupport.h; sourceTree = "<group>"; };
 		0FC815121405118600CFA603 /* VTableSpectrum.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VTableSpectrum.cpp; sourceTree = "<group>"; };
@@ -2400,6 +2402,7 @@
 		969A078F0ED1D3AE00F1F681 /* bytecode */ = {
 			isa = PBXGroup;
 			children = (
+				0FBD7E671447998F00481315 /* CodeOrigin.h */,
 				0FD82E8E14207A5100179C94 /* ValueProfile.cpp */,
 				0FD82E84141F3FDA00179C94 /* PredictedType.cpp */,
 				0FD82E4F141DAEA100179C94 /* PredictedType.h */,
@@ -2896,6 +2899,7 @@
 				0F620176143FCD3B0068B77C /* DFGBasicBlock.h in Headers */,
 				0F620177143FCD3F0068B77C /* DFGAbstractValue.h in Headers */,
 				0F620178143FCD440068B77C /* DFGAbstractState.h in Headers */,
+				0FBD7E691447999600481315 /* CodeOrigin.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (97511 => 97512)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2011-10-14 22:00:38 UTC (rev 97511)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2011-10-14 22:01:10 UTC (rev 97512)
@@ -30,6 +30,7 @@
 #ifndef CodeBlock_h
 #define CodeBlock_h
 
+#include "CodeOrigin.h"
 #include "CompactJITCodeMap.h"
 #include "DFGOSREntry.h"
 #include "EvalCodeCache.h"
@@ -182,6 +183,8 @@
     // (given as an offset in bytes into the JIT code) back to
     // the bytecode index of the corresponding bytecode operation.
     // This is then used to look up the corresponding handler.
+    // FIXME: This should be made inlining aware! Currently it isn't
+    // because we never inline code that has exception handlers.
     struct CallReturnOffsetToBytecodeOffset {
         CallReturnOffsetToBytecodeOffset(unsigned callReturnOffset, unsigned bytecodeOffset)
             : callReturnOffset(callReturnOffset)
@@ -616,6 +619,32 @@
         }
 #endif
 
+#if ENABLE(DFG_JIT)
+        SegmentedVector<InlineCallFrame, 4>& inlineCallFrames()
+        {
+            createRareDataIfNecessary();
+            return m_rareData->m_inlineCallFrames;
+        }
+        
+        Vector<CodeOriginAtCallReturnOffset>& codeOrigins()
+        {
+            createRareDataIfNecessary();
+            return m_rareData->m_codeOrigins;
+        }
+        
+        // Having code origins implies that there has been some inlining.
+        bool hasCodeOrigins()
+        {
+            return m_rareData && !!m_rareData->m_codeOrigins.size();
+        }
+        
+        CodeOrigin codeOriginForReturn(ReturnAddressPtr returnAddress)
+        {
+            ASSERT(hasCodeOrigins());
+            return binarySearch<CodeOriginAtCallReturnOffset, unsigned, getCallReturnOffsetForCodeOrigin>(codeOrigins().begin(), codeOrigins().size(), getJITCode().offsetOf(returnAddress.value()))->codeOrigin;
+        }
+#endif
+
         // Constant Pool
 
         size_t numberOfIdentifiers() const { return m_identifiers.size(); }
@@ -999,6 +1028,10 @@
 #if ENABLE(JIT)
             Vector<CallReturnOffsetToBytecodeOffset> m_callReturnIndexVector;
 #endif
+#if ENABLE(DFG_JIT)
+            SegmentedVector<InlineCallFrame, 4> m_inlineCallFrames;
+            Vector<CodeOriginAtCallReturnOffset> m_codeOrigins;
+#endif
         };
 #if COMPILER(MSVC)
         friend void WTF::deleteOwnedPtr<RareData>(RareData*);
@@ -1104,6 +1137,22 @@
         ASSERT(index < FirstConstantRegisterIndex);
         return this[index];
     }
+
+#if ENABLE(DFG_JIT)
+    inline bool ExecState::isInlineCallFrame()
+    {
+        if (LIKELY(!codeBlock() || codeBlock()->getJITType() != JITCode::DFGJIT))
+            return false;
+        return isInlineCallFrameSlow();
+    }
+
+    inline ExecState* ExecState::trueCallerFrame()
+    {
+        if (LIKELY(!codeBlock() || codeBlock()->getJITType() != JITCode::DFGJIT))
+            return callerFrame()->removeHostCallFrameFlag();
+        return trueCallerFrameSlow();
+    }
+#endif
     
 } // namespace JSC
 

Added: trunk/Source/_javascript_Core/bytecode/CodeOrigin.h (0 => 97512)


--- trunk/Source/_javascript_Core/bytecode/CodeOrigin.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/bytecode/CodeOrigin.h	2011-10-14 22:01:10 UTC (rev 97512)
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef CodeOrigin_h
+#define CodeOrigin_h
+
+#include <wtf/StdLibExtras.h>
+
+namespace JSC {
+
+struct InlineCallFrame;
+class ExecutableBase;
+
+struct CodeOrigin {
+    uint32_t bytecodeIndex;
+    InlineCallFrame* inlineCallFrame;
+    
+    CodeOrigin()
+        : bytecodeIndex(std::numeric_limits<uint32_t>::max())
+        , inlineCallFrame(0)
+    {
+    }
+    
+    explicit CodeOrigin(uint32_t bytecodeIndex)
+        : bytecodeIndex(bytecodeIndex)
+        , inlineCallFrame(0)
+    {
+    }
+    
+    bool isSet() const { return bytecodeIndex != std::numeric_limits<uint32_t>::max(); }
+};
+
+struct InlineCallFrame {
+    ExecutableBase* executable;
+    unsigned stackOffset;
+    unsigned calleeVR;
+    CodeOrigin caller;
+    unsigned numArgumentsIncludingThis;
+};
+
+struct CodeOriginAtCallReturnOffset {
+    CodeOrigin codeOrigin;
+    unsigned callReturnOffset;
+};
+
+inline unsigned getCallReturnOffsetForCodeOrigin(CodeOriginAtCallReturnOffset* data)
+{
+    return data->callReturnOffset;
+}
+
+} // namespace JSC
+
+#endif // CodeOrigin_h
+

Modified: trunk/Source/_javascript_Core/dfg/DFGDriver.cpp (97511 => 97512)


--- trunk/Source/_javascript_Core/dfg/DFGDriver.cpp	2011-10-14 22:00:38 UTC (rev 97511)
+++ trunk/Source/_javascript_Core/dfg/DFGDriver.cpp	2011-10-14 22:01:10 UTC (rev 97512)
@@ -58,6 +58,7 @@
         
         dataFlowJIT.compile(jitCode);
     }
+    
     return true;
 }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp (97511 => 97512)


--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2011-10-14 22:00:38 UTC (rev 97511)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2011-10-14 22:01:10 UTC (rev 97512)
@@ -601,7 +601,7 @@
         for (unsigned i = 0; i < m_calls.size(); ++i) {
             if (m_calls[i].m_handlesExceptions) {
                 unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_calls[i].m_call);
-                unsigned exceptionInfo = m_calls[i].m_codeOrigin.bytecodeIndex();
+                unsigned exceptionInfo = m_calls[i].m_codeOrigin.bytecodeIndex;
                 m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(returnAddressOffset, exceptionInfo));
             }
         }

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (97511 => 97512)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2011-10-14 22:00:38 UTC (rev 97511)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2011-10-14 22:01:10 UTC (rev 97512)
@@ -66,6 +66,7 @@
 #define DFG_ENABLE_RESTRICTIONS 1
 
 #include "CodeBlock.h"
+#include "CodeOrigin.h"
 #include "DFGOperands.h"
 #include "DFGVariableAccessData.h"
 #include "JSValue.h"
@@ -86,33 +87,6 @@
     static NodeIndex defaultValue() { return NoNode; }
 };
 
-// Information used to map back from an exception to any handler/source information,
-// and to implement OSR.
-// (Presently implemented as a bytecode index).
-class CodeOrigin {
-public:
-    CodeOrigin()
-        : m_bytecodeIndex(std::numeric_limits<uint32_t>::max())
-    {
-    }
-    
-    explicit CodeOrigin(uint32_t bytecodeIndex)
-        : m_bytecodeIndex(bytecodeIndex)
-    {
-    }
-    
-    bool isSet() const { return m_bytecodeIndex != std::numeric_limits<uint32_t>::max(); }
-    
-    uint32_t bytecodeIndex() const
-    {
-        ASSERT(isSet());
-        return m_bytecodeIndex;
-    }
-    
-private:
-    uint32_t m_bytecodeIndex;
-};
-
 struct StructureTransitionData {
     Structure* previousStructure;
     Structure* newStructure;

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (97511 => 97512)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-10-14 22:00:38 UTC (rev 97511)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-10-14 22:01:10 UTC (rev 97512)
@@ -294,17 +294,17 @@
 
     for (; m_compileIndex < block.end; ++m_compileIndex) {
         Node& node = at(m_compileIndex);
-        m_bytecodeIndexForOSR = node.codeOrigin.bytecodeIndex();
+        m_bytecodeIndexForOSR = node.codeOrigin.bytecodeIndex;
         if (!node.shouldGenerate()) {
 #if DFG_ENABLE(DEBUG_VERBOSE)
-            fprintf(stderr, "SpeculativeJIT skipping Node @%d (bc#%u) at JIT offset 0x%x     ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex(), m_jit.debugOffset());
+            fprintf(stderr, "SpeculativeJIT skipping Node @%d (bc#%u) at JIT offset 0x%x     ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
 #endif
             if (node.op == SetLocal)
                 compileMovHint(node);
         } else {
             
 #if DFG_ENABLE(DEBUG_VERBOSE)
-            fprintf(stderr, "SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x   ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex(), m_jit.debugOffset());
+            fprintf(stderr, "SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x   ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
 #endif
 #if DFG_ENABLE(JIT_BREAK_ON_EVERY_NODE)
             m_jit.breakpoint();

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (97511 => 97512)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2011-10-14 22:00:38 UTC (rev 97511)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2011-10-14 22:01:10 UTC (rev 97512)
@@ -730,10 +730,10 @@
         // to the *next* instruction, since we've already "executed" the
         // SetLocal and whatever other DFG Nodes are associated with the same
         // bytecode index as the SetLocal.
-        ASSERT(m_bytecodeIndexForOSR == node.codeOrigin.bytecodeIndex());
+        ASSERT(m_bytecodeIndexForOSR == node.codeOrigin.bytecodeIndex);
         Node& nextNode = at(m_compileIndex + 1);
         
-        m_bytecodeIndexForOSR = nextNode.codeOrigin.bytecodeIndex();
+        m_bytecodeIndexForOSR = nextNode.codeOrigin.bytecodeIndex;
         
         PredictedType predictedType = node.variableAccessData()->prediction();
         if (isInt32Prediction(predictedType)) {

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (97511 => 97512)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2011-10-14 22:00:38 UTC (rev 97511)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2011-10-14 22:01:10 UTC (rev 97512)
@@ -846,7 +846,7 @@
         // to the *next* instruction, since we've already "executed" the
         // SetLocal and whatever other DFG Nodes are associated with the same
         // bytecode index as the SetLocal.
-        ASSERT(m_bytecodeIndexForOSR == node.codeOrigin.bytecodeIndex());
+        ASSERT(m_bytecodeIndexForOSR == node.codeOrigin.bytecodeIndex);
         Node& nextNode = at(m_compileIndex + 1);
         
         // Oddly, it's possible for the bytecode index for the next node to be
@@ -859,7 +859,7 @@
         // statement) would be dead anyway - so the fact that DFG would have
         // already made the assignment, and baked it into the register file during
         // OSR exit, would not be visible to the old JIT in any way.
-        m_bytecodeIndexForOSR = nextNode.codeOrigin.bytecodeIndex();
+        m_bytecodeIndexForOSR = nextNode.codeOrigin.bytecodeIndex;
         
         PredictedType predictedType = node.variableAccessData()->prediction();
         if (isInt32Prediction(predictedType)) {

Modified: trunk/Source/_javascript_Core/interpreter/CallFrame.cpp (97511 => 97512)


--- trunk/Source/_javascript_Core/interpreter/CallFrame.cpp	2011-10-14 22:00:38 UTC (rev 97511)
+++ trunk/Source/_javascript_Core/interpreter/CallFrame.cpp	2011-10-14 22:01:10 UTC (rev 97512)
@@ -50,4 +50,75 @@
 
 #endif
 
+#if ENABLE(DFG_JIT)
+bool CallFrame::isInlineCallFrameSlow()
+{
+    if (!callee())
+        return false;
+    JSCell* calleeAsFunctionCell = getJSFunction(callee());
+    if (!calleeAsFunctionCell)
+        return false;
+    JSFunction* calleeAsFunction = asFunction(calleeAsFunctionCell);
+    return calleeAsFunction->executable() != codeBlock()->ownerExecutable();
 }
+        
+CallFrame* CallFrame::trueCallerFrameSlow()
+{
+    // this -> The callee; this is either an inlined callee in which case it already has
+    //    a pointer to the true caller. Otherwise it contains current PC in the machine
+    //    caller.
+    //
+    // machineCaller -> The caller according to the machine, which may be zero or
+    //    more frames above the true caller due to inlining.
+    //
+    // trueCaller -> The real caller.
+    
+    // Am I an inline call frame? If so, we're done.
+    if (isInlineCallFrame())
+        return callerFrame();
+    
+    // I am a machine call frame, so the question is: is my caller a machine call frame
+    // that has inlines or a machine call frame that doesn't?
+    CallFrame* machineCaller = callerFrame()->removeHostCallFrameFlag();
+    if (!machineCaller)
+        return 0;
+    ASSERT(!machineCaller->isInlineCallFrame());
+    if (!machineCaller->codeBlock() || !machineCaller->codeBlock()->hasCodeOrigins())
+        return machineCaller; // No inlining, so machineCaller == trueCaller
+    
+    // Figure out where the caller frame would have gone relative to the machine
+    // caller, and rematerialize it. Do so for the entire inline stack.
+    
+    CodeOrigin codeOrigin = machineCaller->codeBlock()->codeOriginForReturn(returnPC());
+    
+    for (InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; inlineCallFrame;) {
+        InlineCallFrame* nextInlineCallFrame = inlineCallFrame = inlineCallFrame->caller.inlineCallFrame;
+        
+        CallFrame* inlinedCaller = machineCaller + inlineCallFrame->stackOffset;
+        
+        JSObject* callee = machineCaller->registers()[inlineCallFrame->calleeVR].function();
+        JSCell* calleeAsFunctionCell = getJSFunction(callee);
+        ASSERT(calleeAsFunctionCell);
+        JSFunction* calleeAsFunction = asFunction(calleeAsFunctionCell);
+        
+        // Fill in the inlinedCaller
+        inlinedCaller->setCodeBlock(machineCaller->codeBlock());
+        
+        inlinedCaller->setScopeChain(calleeAsFunction->scope());
+        if (nextInlineCallFrame)
+            inlinedCaller->setCallerFrame(machineCaller + nextInlineCallFrame->stackOffset);
+        else
+            inlinedCaller->setCallerFrame(machineCaller);
+        
+        inlinedCaller->setInlineCallFrame(inlineCallFrame);
+        inlinedCaller->setArgumentCountIncludingThis(inlineCallFrame->numArgumentsIncludingThis);
+        inlinedCaller->setCallee(callee);
+        
+        inlineCallFrame = nextInlineCallFrame;
+    }
+    
+    return machineCaller + codeOrigin.inlineCallFrame->stackOffset;
+}
+#endif
+
+}

Modified: trunk/Source/_javascript_Core/interpreter/CallFrame.h (97511 => 97512)


--- trunk/Source/_javascript_Core/interpreter/CallFrame.h	2011-10-14 22:00:38 UTC (rev 97511)
+++ trunk/Source/_javascript_Core/interpreter/CallFrame.h	2011-10-14 22:01:10 UTC (rev 97512)
@@ -104,6 +104,9 @@
 #if ENABLE(JIT)
         ReturnAddressPtr returnPC() const { return ReturnAddressPtr(this[RegisterFile::ReturnPC].vPC()); }
 #endif
+#if ENABLE(DFG_JIT)
+        InlineCallFrame* inlineCallFrame() const { return this[RegisterFile::ReturnPC].inlineCallFrame(); }
+#endif
 #if ENABLE(INTERPRETER)
         Instruction* returnVPC() const { return this[RegisterFile::ReturnPC].vPC(); }
 #endif
@@ -153,12 +156,30 @@
         void setCallee(JSObject* callee) { static_cast<Register*>(this)[RegisterFile::Callee] = Register::withCallee(callee); }
         void setCodeBlock(CodeBlock* codeBlock) { static_cast<Register*>(this)[RegisterFile::CodeBlock] = codeBlock; }
         void setReturnPC(void* value) { static_cast<Register*>(this)[RegisterFile::ReturnPC] = (Instruction*)value; }
+        
+#if ENABLE(DFG_JIT)
+        bool isInlineCallFrame();
+        
+        void setInlineCallFrame(InlineCallFrame* inlineCallFrame) { static_cast<Register*>(this)[RegisterFile::ReturnPC] = inlineCallFrame; }
+        
+        // Call this to get the semantically correct JS CallFrame*. This resolves issues
+        // surrounding inlining and the HostCallFrameFlag stuff.
+        CallFrame* trueCallerFrame();
+#else
+        bool isInlineCallFrame() { return false; }
+        
+        CallFrame* trueCallerFrame() { return callerFrame()->removeHostCallFrameFlag(); }
+#endif
 
     private:
         static const intptr_t HostCallFrameFlag = 1;
 #ifndef NDEBUG
         RegisterFile* registerFile();
 #endif
+#if ENABLE(DFG_JIT)
+        bool isInlineCallFrameSlow();
+        CallFrame* trueCallerFrameSlow();
+#endif
         ExecState();
         ~ExecState();
     };

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (97511 => 97512)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2011-10-14 22:00:38 UTC (rev 97511)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2011-10-14 22:01:10 UTC (rev 97512)
@@ -5190,7 +5190,7 @@
 
 CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, JSFunction* function)
 {
-    for (CallFrame* candidate = callFrame; candidate; candidate = candidate->callerFrame()->removeHostCallFrameFlag()) {
+    for (CallFrame* candidate = callFrame; candidate; candidate = candidate->trueCallerFrame()) {
         if (candidate->callee() == function)
             return candidate;
     }

Modified: trunk/Source/_javascript_Core/interpreter/Register.h (97511 => 97512)


--- trunk/Source/_javascript_Core/interpreter/Register.h	2011-10-14 22:00:38 UTC (rev 97511)
+++ trunk/Source/_javascript_Core/interpreter/Register.h	2011-10-14 22:01:10 UTC (rev 97512)
@@ -42,6 +42,7 @@
     class JSPropertyNameIterator;
     class ScopeChainNode;
 
+    struct InlineCallFrame;
     struct Instruction;
 
     typedef ExecState CallFrame;
@@ -60,6 +61,7 @@
         Register& operator=(CodeBlock*);
         Register& operator=(ScopeChainNode*);
         Register& operator=(Instruction*);
+        Register& operator=(InlineCallFrame*);
 
         int32_t i() const;
         JSActivation* activation() const;
@@ -69,6 +71,7 @@
         JSPropertyNameIterator* propertyNameIterator() const;
         ScopeChainNode* scopeChain() const;
         Instruction* vPC() const;
+        InlineCallFrame* inlineCallFrame() const;
 
         static Register withInt(int32_t i)
         {
@@ -84,6 +87,7 @@
             CallFrame* callFrame;
             CodeBlock* codeBlock;
             Instruction* vPC;
+            InlineCallFrame* inlineCallFrame;
         } u;
     };
 
@@ -135,6 +139,12 @@
         return *this;
     }
 
+    ALWAYS_INLINE Register& Register::operator=(InlineCallFrame* inlineCallFrame)
+    {
+        u.inlineCallFrame = inlineCallFrame;
+        return *this;
+    }
+
     ALWAYS_INLINE int32_t Register::i() const
     {
         return jsValue().asInt32();
@@ -155,6 +165,11 @@
         return u.vPC;
     }
 
+    ALWAYS_INLINE InlineCallFrame* Register::inlineCallFrame() const
+    {
+        return u.inlineCallFrame;
+    }
+
 } // namespace JSC
 
 namespace WTF {

Modified: trunk/Source/_javascript_Core/runtime/Arguments.h (97511 => 97512)


--- trunk/Source/_javascript_Core/runtime/Arguments.h	2011-10-14 22:00:38 UTC (rev 97511)
+++ trunk/Source/_javascript_Core/runtime/Arguments.h	2011-10-14 22:01:10 UTC (rev 97512)
@@ -24,6 +24,7 @@
 #ifndef Arguments_h
 #define Arguments_h
 
+#include "CodeOrigin.h"
 #include "JSActivation.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
@@ -54,6 +55,7 @@
         bool overrodeCallee : 1;
         bool overrodeCaller : 1;
         bool isStrictMode : 1;
+        bool isInlineFrame : 1; // If true, all arguments are in the extraArguments buffer.
     };
 
 
@@ -169,6 +171,9 @@
 
         int numParameters = function->jsExecutable()->parameterCount();
         argc = callFrame->argumentCountIncludingThis();
+        
+        if (callFrame->isInlineCallFrame())
+            ASSERT(argc == numParameters);
 
         if (argc <= numParameters)
             argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters;
@@ -205,6 +210,7 @@
         d->numParameters = callee->jsExecutable()->parameterCount();
         d->firstParameterIndex = firstParameterIndex;
         d->numArguments = numArguments;
+        d->isInlineFrame = false;
 
         d->registers = reinterpret_cast<WriteBarrier<Unknown>*>(callFrame->registers());
 
@@ -232,6 +238,7 @@
 
     inline void Arguments::finishCreation(CallFrame* callFrame)
     {
+        ASSERT(!callFrame->isInlineCallFrame());
         finishCreationButDontCopyRegisters(callFrame);
         if (d->isStrictMode)
             copyRegisters(callFrame->globalData());
@@ -239,12 +246,59 @@
 
     inline void Arguments::finishCreationAndCopyRegisters(CallFrame* callFrame)
     {
-        finishCreationButDontCopyRegisters(callFrame);
-        copyRegisters(callFrame->globalData());
+        Base::finishCreation(callFrame->globalData());
+        ASSERT(inherits(&s_info));
+        
+        JSFunction* callee;
+
+        ptrdiff_t firstParameterIndex;
+        Register* argv;
+        int numArguments;
+        getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments);
+        
+        d->numParameters = callee->jsExecutable()->parameterCount();
+        d->firstParameterIndex = firstParameterIndex;
+        d->numArguments = numArguments;
+        
+        if (d->numParameters) {
+            int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize;
+            size_t registerArraySize = d->numParameters;
+            
+            OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[registerArraySize]);
+            for (size_t i = 0; i < registerArraySize; ++i)
+                registerArray[i].set(callFrame->globalData(), this, callFrame->registers()[i - registerOffset].jsValue());
+            d->registers = registerArray.get() + d->numParameters + RegisterFile::CallFrameHeaderSize;
+            d->registerArray = registerArray.release();
+        }
+        
+        WriteBarrier<Unknown>* extraArguments;
+        if (callFrame->isInlineCallFrame())
+            ASSERT(d->numArguments == d->numParameters);
+        if (d->numArguments <= d->numParameters)
+            extraArguments = 0;
+        else {
+            unsigned numExtraArguments = d->numArguments - d->numParameters;
+            if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(WriteBarrier<Unknown>))
+                extraArguments = new WriteBarrier<Unknown>[numExtraArguments];
+            else
+                extraArguments = d->extraArgumentsFixedBuffer;
+            for (unsigned i = 0; i < numExtraArguments; ++i)
+                extraArguments[i].set(callFrame->globalData(), this, argv[d->numParameters + i].jsValue());
+        }
+        
+        d->extraArguments = extraArguments;
+
+        d->callee.set(callFrame->globalData(), this, callee);
+        d->overrodeLength = false;
+        d->overrodeCallee = false;
+        d->overrodeCaller = false;
+        d->isInlineFrame = callFrame->isInlineCallFrame();
+        d->isStrictMode = callFrame->codeBlock()->isStrictMode();
     }
 
     inline void Arguments::finishCreation(CallFrame* callFrame, NoParametersType)
     {
+        ASSERT(!callFrame->isInlineCallFrame());
         Base::finishCreation(callFrame->globalData());
         ASSERT(inherits(&s_info));
         ASSERT(!asFunction(callFrame->callee())->jsExecutable()->parameterCount());
@@ -253,6 +307,7 @@
 
         d->numParameters = 0;
         d->numArguments = numArguments;
+        d->isInlineFrame = false;
 
         WriteBarrier<Unknown>* extraArguments;
         if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))

Modified: trunk/Source/_javascript_Core/runtime/Executable.h (97511 => 97512)


--- trunk/Source/_javascript_Core/runtime/Executable.h	2011-10-14 22:00:38 UTC (rev 97511)
+++ trunk/Source/_javascript_Core/runtime/Executable.h	2011-10-14 22:01:10 UTC (rev 97512)
@@ -573,7 +573,7 @@
 
         const Identifier& name() { return m_name; }
         JSString* nameValue() const { return m_nameValue.get(); }
-        size_t parameterCount() const { return m_parameters->size(); }
+        size_t parameterCount() const { return m_parameters->size(); } // Including 'this'!
         unsigned capturedVariableCount() const { return m_numCapturedVariables; }
         UString paramString() const;
         SharedSymbolTable* symbolTable() const { return m_symbolTable; }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to