summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/interpreter/StackVisitor.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
commit32761a6cee1d0dee366b885b7b9c777e67885688 (patch)
treed6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/interpreter/StackVisitor.cpp
parenta4e969f4965059196ca948db781e52f7cfebf19e (diff)
downloadWebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/interpreter/StackVisitor.cpp')
-rw-r--r--Source/JavaScriptCore/interpreter/StackVisitor.cpp310
1 files changed, 172 insertions, 138 deletions
diff --git a/Source/JavaScriptCore/interpreter/StackVisitor.cpp b/Source/JavaScriptCore/interpreter/StackVisitor.cpp
index c0c03d280..d922e7f8f 100644
--- a/Source/JavaScriptCore/interpreter/StackVisitor.cpp
+++ b/Source/JavaScriptCore/interpreter/StackVisitor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 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
@@ -26,11 +26,11 @@
#include "config.h"
#include "StackVisitor.h"
-#include "ClonedArguments.h"
+#include "Arguments.h"
+#include "CallFrameInlines.h"
#include "Executable.h"
-#include "InlineCallFrame.h"
#include "Interpreter.h"
-#include "JSCInlines.h"
+#include "Operations.h"
#include <wtf/DataLog.h>
namespace JSC {
@@ -38,20 +38,7 @@ namespace JSC {
StackVisitor::StackVisitor(CallFrame* startFrame)
{
m_frame.m_index = 0;
- CallFrame* topFrame;
- if (startFrame) {
- m_frame.m_VMEntryFrame = startFrame->vm().topVMEntryFrame;
- topFrame = startFrame->vm().topCallFrame;
- } else {
- m_frame.m_VMEntryFrame = 0;
- topFrame = 0;
- }
- m_frame.m_callerIsVMEntryFrame = false;
- readFrame(topFrame);
-
- // Find the frame the caller wants to start unwinding from.
- while (m_frame.callFrame() && m_frame.callFrame() != startFrame)
- gotoNextFrame();
+ readFrame(startFrame);
}
void StackVisitor::gotoNextFrame()
@@ -59,33 +46,17 @@ void StackVisitor::gotoNextFrame()
#if ENABLE(DFG_JIT)
if (m_frame.isInlinedFrame()) {
InlineCallFrame* inlineCallFrame = m_frame.inlineCallFrame();
- CodeOrigin* callerCodeOrigin = inlineCallFrame->getCallerSkippingTailCalls();
- if (!callerCodeOrigin) {
- while (inlineCallFrame) {
- readInlinedFrame(m_frame.callFrame(), &inlineCallFrame->directCaller);
- inlineCallFrame = m_frame.inlineCallFrame();
- }
- m_frame.m_VMEntryFrame = m_frame.m_CallerVMEntryFrame;
- readFrame(m_frame.callerFrame());
- } else
- readInlinedFrame(m_frame.callFrame(), callerCodeOrigin);
- return;
- }
-#endif // ENABLE(DFG_JIT)
- m_frame.m_VMEntryFrame = m_frame.m_CallerVMEntryFrame;
- readFrame(m_frame.callerFrame());
-}
+ CodeOrigin* callerCodeOrigin = &inlineCallFrame->caller;
+ readInlinedFrame(m_frame.callFrame(), callerCodeOrigin);
-void StackVisitor::unwindToMachineCodeBlockFrame()
-{
-#if ENABLE(DFG_JIT)
- while (m_frame.isInlinedFrame())
- gotoNextFrame();
-#endif
+ } else
+#endif // ENABLE(DFG_JIT)
+ readFrame(m_frame.callerFrame());
}
void StackVisitor::readFrame(CallFrame* callFrame)
{
+ ASSERT(!callFrame->isVMEntrySentinel());
if (!callFrame) {
m_frame.setToEnd();
return;
@@ -110,7 +81,7 @@ void StackVisitor::readFrame(CallFrame* callFrame)
return;
}
- CallSiteIndex index = callFrame->callSiteIndex();
+ unsigned index = callFrame->locationAsCodeOriginIndex();
ASSERT(codeBlock->canGetCodeOrigin(index));
if (!codeBlock->canGetCodeOrigin(index)) {
// See assertion above. In release builds, we try to protect ourselves
@@ -133,14 +104,13 @@ void StackVisitor::readNonInlinedFrame(CallFrame* callFrame, CodeOrigin* codeOri
{
m_frame.m_callFrame = callFrame;
m_frame.m_argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
- m_frame.m_CallerVMEntryFrame = m_frame.m_VMEntryFrame;
- m_frame.m_callerFrame = callFrame->callerFrame(m_frame.m_CallerVMEntryFrame);
- m_frame.m_callerIsVMEntryFrame = m_frame.m_CallerVMEntryFrame != m_frame.m_VMEntryFrame;
+ m_frame.m_callerFrame = callFrame->callerFrameSkippingVMEntrySentinel();
m_frame.m_callee = callFrame->callee();
+ m_frame.m_scope = callFrame->scope();
m_frame.m_codeBlock = callFrame->codeBlock();
m_frame.m_bytecodeOffset = !m_frame.codeBlock() ? 0
: codeOrigin ? codeOrigin->bytecodeIndex
- : callFrame->bytecodeOffset();
+ : callFrame->locationAsBytecodeOffset();
#if ENABLE(DFG_JIT)
m_frame.m_inlineCallFrame = 0;
#endif
@@ -157,6 +127,7 @@ static int inlinedFrameOffset(CodeOrigin* codeOrigin)
void StackVisitor::readInlinedFrame(CallFrame* callFrame, CodeOrigin* codeOrigin)
{
ASSERT(codeOrigin);
+ ASSERT(!callFrame->isVMEntrySentinel());
int frameOffset = inlinedFrameOffset(codeOrigin);
bool isInlined = !!frameOffset;
@@ -165,15 +136,14 @@ void StackVisitor::readInlinedFrame(CallFrame* callFrame, CodeOrigin* codeOrigin
m_frame.m_callFrame = callFrame;
m_frame.m_inlineCallFrame = inlineCallFrame;
- if (inlineCallFrame->argumentCountRegister.isValid())
- m_frame.m_argumentCountIncludingThis = callFrame->r(inlineCallFrame->argumentCountRegister.offset()).unboxedInt32();
- else
- m_frame.m_argumentCountIncludingThis = inlineCallFrame->arguments.size();
- m_frame.m_codeBlock = inlineCallFrame->baselineCodeBlock.get();
+ m_frame.m_argumentCountIncludingThis = inlineCallFrame->arguments.size();
+ m_frame.m_codeBlock = inlineCallFrame->baselineCodeBlock();
m_frame.m_bytecodeOffset = codeOrigin->bytecodeIndex;
JSFunction* callee = inlineCallFrame->calleeForCallFrame(callFrame);
+ m_frame.m_scope = callee->scope();
m_frame.m_callee = callee;
+ ASSERT(m_frame.scope());
ASSERT(m_frame.callee());
// The callerFrame just needs to be non-null to indicate that we
@@ -196,8 +166,6 @@ StackVisitor::Frame::CodeType StackVisitor::Frame::codeType() const
switch (codeBlock()->codeType()) {
case EvalCode:
return CodeType::Eval;
- case ModuleCode:
- return CodeType::Module;
case FunctionCode:
return CodeType::Function;
case GlobalCode:
@@ -214,10 +182,7 @@ String StackVisitor::Frame::functionName()
switch (codeType()) {
case CodeType::Eval:
- traceLine = ASCIILiteral("eval code");
- break;
- case CodeType::Module:
- traceLine = ASCIILiteral("module code");
+ traceLine = "eval code";
break;
case CodeType::Native:
if (callee)
@@ -227,7 +192,7 @@ String StackVisitor::Frame::functionName()
traceLine = getCalculatedDisplayName(callFrame(), callee).impl();
break;
case CodeType::Global:
- traceLine = ASCIILiteral("global code");
+ traceLine = "global code";
break;
}
return traceLine.isNull() ? emptyString() : traceLine;
@@ -239,16 +204,15 @@ String StackVisitor::Frame::sourceURL()
switch (codeType()) {
case CodeType::Eval:
- case CodeType::Module:
case CodeType::Function:
case CodeType::Global: {
- String sourceURL = codeBlock()->ownerScriptExecutable()->sourceURL();
+ String sourceURL = codeBlock()->ownerExecutable()->sourceURL();
if (!sourceURL.isEmpty())
traceLine = sourceURL.impl();
break;
}
case CodeType::Native:
- traceLine = ASCIILiteral("[native code]");
+ traceLine = "[native code]";
break;
}
return traceLine.isNull() ? emptyString() : traceLine;
@@ -277,26 +241,48 @@ String StackVisitor::Frame::toString()
return traceBuild.toString().impl();
}
-ClonedArguments* StackVisitor::Frame::createArguments()
+Arguments* StackVisitor::Frame::createArguments()
{
ASSERT(m_callFrame);
CallFrame* physicalFrame = m_callFrame;
- ClonedArguments* arguments;
- ArgumentsMode mode;
- if (Options::useFunctionDotArguments())
- mode = ArgumentsMode::Cloned;
- else
- mode = ArgumentsMode::FakeValues;
+ VM& vm = physicalFrame->vm();
+ Arguments* arguments;
#if ENABLE(DFG_JIT)
if (isInlinedFrame()) {
ASSERT(m_inlineCallFrame);
- arguments = ClonedArguments::createWithInlineFrame(physicalFrame, physicalFrame, m_inlineCallFrame, mode);
+ arguments = Arguments::create(vm, physicalFrame, m_inlineCallFrame);
+ arguments->tearOff(physicalFrame, m_inlineCallFrame);
} else
#endif
- arguments = ClonedArguments::createWithMachineFrame(physicalFrame, physicalFrame, mode);
+ {
+ arguments = Arguments::create(vm, physicalFrame);
+ arguments->tearOff(physicalFrame);
+ }
return arguments;
}
+Arguments* StackVisitor::Frame::existingArguments()
+{
+ if (codeBlock()->codeType() != FunctionCode)
+ return 0;
+ if (!codeBlock()->usesArguments())
+ return 0;
+
+ VirtualRegister reg;
+
+#if ENABLE(DFG_JIT)
+ if (isInlinedFrame())
+ reg = inlineCallFrame()->argumentsRegister;
+ else
+#endif // ENABLE(DFG_JIT)
+ reg = codeBlock()->argumentsRegister();
+
+ JSValue result = callFrame()->r(unmodifiedArgumentsRegister(reg).offset()).jsValue();
+ if (!result)
+ return 0;
+ return jsCast<Arguments*>(result);
+}
+
void StackVisitor::Frame::computeLineAndColumn(unsigned& line, unsigned& column)
{
CodeBlock* codeBlock = this->codeBlock();
@@ -313,11 +299,8 @@ void StackVisitor::Frame::computeLineAndColumn(unsigned& line, unsigned& column)
unsigned divotColumn = 0;
retrieveExpressionInfo(divot, unusedStartOffset, unusedEndOffset, divotLine, divotColumn);
- line = divotLine + codeBlock->ownerScriptExecutable()->firstLine();
+ line = divotLine + codeBlock->ownerExecutable()->lineNo();
column = divotColumn + (divotLine ? 1 : codeBlock->firstLineColumnOffset());
-
- if (codeBlock->ownerScriptExecutable()->hasOverrideLineNumber())
- line = codeBlock->ownerScriptExecutable()->overrideLineNumber();
}
void StackVisitor::Frame::retrieveExpressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column)
@@ -335,106 +318,157 @@ void StackVisitor::Frame::setToEnd()
#endif
}
+#ifndef NDEBUG
+
+static const char* jitTypeName(JITCode::JITType jitType)
+{
+ switch (jitType) {
+ case JITCode::None: return "None";
+ case JITCode::HostCallThunk: return "HostCallThunk";
+ case JITCode::InterpreterThunk: return "InterpreterThunk";
+ case JITCode::BaselineJIT: return "BaselineJIT";
+ case JITCode::DFGJIT: return "DFGJIT";
+ case JITCode::FTLJIT: return "FTLJIT";
+ }
+ return "<unknown>";
+}
+
static void printIndents(int levels)
{
while (levels--)
dataLogFString(" ");
}
-template<typename... Types>
-void log(unsigned indent, const Types&... values)
+static void printif(int indentLevels, const char* format, ...)
{
- printIndents(indent);
- dataLog(values...);
-}
+ va_list argList;
+ va_start(argList, format);
-template<typename... Types>
-void logF(unsigned indent, const char* format, const Types&... values)
-{
- printIndents(indent);
+ if (indentLevels)
+ printIndents(indentLevels);
-#if COMPILER(GCC_OR_CLANG)
+#if COMPILER(CLANG) || (COMPILER(GCC) && GCC_VERSION_AT_LEAST(4, 6, 0))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#pragma GCC diagnostic ignored "-Wmissing-format-attribute"
#endif
- dataLogF(format, values...);
+ WTF::dataLogFV(format, argList);
-#if COMPILER(GCC_OR_CLANG)
+#if COMPILER(CLANG) || (COMPILER(GCC) && GCC_VERSION_AT_LEAST(4, 6, 0))
#pragma GCC diagnostic pop
#endif
+
+ va_end(argList);
}
-void StackVisitor::Frame::print(int indent)
+void StackVisitor::Frame::print(int indentLevel)
{
+ int i = indentLevel;
+
if (!this->callFrame()) {
- log(indent, "frame 0x0\n");
+ printif(i, "frame 0x0\n");
return;
}
CodeBlock* codeBlock = this->codeBlock();
- logF(indent, "frame %p {\n", this->callFrame());
+ printif(i, "frame %p {\n", this->callFrame());
- {
- indent++;
-
- CallFrame* callFrame = m_callFrame;
- CallFrame* callerFrame = this->callerFrame();
- void* returnPC = callFrame->hasReturnPC() ? callFrame->returnPC().value() : nullptr;
+ CallFrame* callFrame = m_callFrame;
+ CallFrame* callerFrame = this->callerFrame();
+ void* returnPC = callFrame->hasReturnPC() ? callFrame->returnPC().value() : nullptr;
- log(indent, "name: ", functionName(), "\n");
- log(indent, "sourceURL: ", sourceURL(), "\n");
+ printif(i, " name '%s'\n", functionName().utf8().data());
+ printif(i, " sourceURL '%s'\n", sourceURL().utf8().data());
+ printif(i, " isVMEntrySentinel %d\n", callerFrame->isVMEntrySentinel());
- bool isInlined = false;
#if ENABLE(DFG_JIT)
- isInlined = isInlinedFrame();
- log(indent, "isInlinedFrame: ", isInlinedFrame(), "\n");
- if (isInlinedFrame())
- logF(indent, "InlineCallFrame: %p\n", m_inlineCallFrame);
+ printif(i, " isInlinedFrame %d\n", isInlinedFrame());
+ if (isInlinedFrame())
+ printif(i, " InlineCallFrame %p\n", m_inlineCallFrame);
#endif
- logF(indent, "callee: %p\n", callee());
- logF(indent, "returnPC: %p\n", returnPC);
- logF(indent, "callerFrame: %p\n", callerFrame);
- unsigned locationRawBits = callFrame->callSiteAsRawBits();
- logF(indent, "rawLocationBits: %u 0x%x\n", locationRawBits, locationRawBits);
- logF(indent, "codeBlock: %p ", codeBlock);
- if (codeBlock)
- dataLog(*codeBlock);
- dataLog("\n");
- if (codeBlock && !isInlined) {
- indent++;
-
- if (callFrame->callSiteBitsAreBytecodeOffset()) {
- unsigned bytecodeOffset = callFrame->bytecodeOffset();
- log(indent, "bytecodeOffset: ", bytecodeOffset, " of ", codeBlock->instructions().size(), "\n");
+ printif(i, " callee %p\n", callee());
+ printif(i, " returnPC %p\n", returnPC);
+ printif(i, " callerFrame %p\n", callerFrame);
+ unsigned locationRawBits = callFrame->locationAsRawBits();
+ printif(i, " rawLocationBits %u 0x%x\n", locationRawBits, locationRawBits);
+ printif(i, " codeBlock %p\n", codeBlock);
+ if (codeBlock) {
+ JITCode::JITType jitType = codeBlock->jitType();
+ if (callFrame->hasLocationAsBytecodeOffset()) {
+ unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset();
+ printif(i, " bytecodeOffset %u %p / %zu\n", bytecodeOffset, reinterpret_cast<void*>(bytecodeOffset), codeBlock->instructions().size());
#if ENABLE(DFG_JIT)
- } else {
- log(indent, "hasCodeOrigins: ", codeBlock->hasCodeOrigins(), "\n");
- if (codeBlock->hasCodeOrigins()) {
- CallSiteIndex callSiteIndex = callFrame->callSiteIndex();
- log(indent, "callSiteIndex: ", callSiteIndex.bits(), " of ", codeBlock->codeOrigins().size(), "\n");
-
- JITCode::JITType jitType = codeBlock->jitType();
- if (jitType != JITCode::FTLJIT) {
- JITCode* jitCode = codeBlock->jitCode().get();
- logF(indent, "jitCode: %p start %p end %p\n", jitCode, jitCode->start(), jitCode->end());
- }
- }
+ } else {
+ unsigned codeOriginIndex = callFrame->locationAsCodeOriginIndex();
+ printif(i, " codeOriginIdex %u %p / %zu\n", codeOriginIndex, reinterpret_cast<void*>(codeOriginIndex), codeBlock->codeOrigins().size());
#endif
- }
- unsigned line = 0;
- unsigned column = 0;
- computeLineAndColumn(line, column);
- log(indent, "line: ", line, "\n");
- log(indent, "column: ", column, "\n");
-
- indent--;
}
- indent--;
+ unsigned line = 0;
+ unsigned column = 0;
+ computeLineAndColumn(line, column);
+ printif(i, " line %d\n", line);
+ printif(i, " column %d\n", column);
+ printif(i, " jitType %d <%s> isOptimizingJIT %d\n", jitType, jitTypeName(jitType), JITCode::isOptimizingJIT(jitType));
+#if ENABLE(DFG_JIT)
+ printif(i, " hasCodeOrigins %d\n", codeBlock->hasCodeOrigins());
+ if (codeBlock->hasCodeOrigins()) {
+ JITCode* jitCode = codeBlock->jitCode().get();
+ printif(i, " jitCode %p start %p end %p\n", jitCode, jitCode->start(), jitCode->end());
+ }
+#endif
}
- log(indent, "}\n");
+ printif(i, "}\n");
}
+#endif // NDEBUG
+
} // namespace JSC
+
+#ifndef NDEBUG
+using JSC::StackVisitor;
+
+// For debugging use
+JS_EXPORT_PRIVATE void debugPrintCallFrame(JSC::CallFrame*);
+JS_EXPORT_PRIVATE void debugPrintStack(JSC::CallFrame* topCallFrame);
+
+class DebugPrintFrameFunctor {
+public:
+ enum Action {
+ PrintOne,
+ PrintAll
+ };
+
+ DebugPrintFrameFunctor(Action action)
+ : m_action(action)
+ {
+ }
+
+ StackVisitor::Status operator()(StackVisitor& visitor)
+ {
+ visitor->print(2);
+ return m_action == PrintAll ? StackVisitor::Continue : StackVisitor::Done;
+ }
+
+private:
+ Action m_action;
+};
+
+void debugPrintCallFrame(JSC::CallFrame* callFrame)
+{
+ if (!callFrame)
+ return;
+ DebugPrintFrameFunctor functor(DebugPrintFrameFunctor::PrintOne);
+ callFrame->iterate(functor);
+}
+
+void debugPrintStack(JSC::CallFrame* topCallFrame)
+{
+ if (!topCallFrame)
+ return;
+ DebugPrintFrameFunctor functor(DebugPrintFrameFunctor::PrintAll);
+ topCallFrame->iterate(functor);
+}
+
+#endif // !NDEBUG