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; }