Log Message
dumpCallFrame is broken in ToT https://bugs.webkit.org/show_bug.cgi?id=91444
Reviewed by Gavin Barraclough.
Various changes have been made to the SF calling convention, but
dumpCallFrame has not been updated to reflect these changes.
That resulted in both bogus information, as well as numerous
assertions of sadness.
This patch makes dumpCallFrame actually work again and adds the
wonderful feature of telling you the name of the variable that a
register reflects, or what value it contains.
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::nameForRegister):
A really innefficient mechanism for finding the name of a local register.
This should only ever be used by debug code so this should be okay.
* bytecode/CodeBlock.h:
(CodeBlock):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::generate):
Debug builds no longer throw away a functions symbol table, this allows
us to actually perform a register# to name mapping
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
We weren't propogating the bytecode offset here leading to assertions
in debug builds when dumping bytecode of DFG compiled code.
* interpreter/Interpreter.cpp:
(JSC):
(JSC::Interpreter::dumpRegisters):
Rework to actually be correct.
(JSC::getCallerInfo):
Return the byteocde offset as well now, given we have to determine it
anyway.
(JSC::Interpreter::getStackTrace):
(JSC::Interpreter::retrieveCallerFromVMCode):
* interpreter/Interpreter.h:
(Interpreter):
* jsc.cpp:
(GlobalObject::finishCreation):
(functionDumpCallFrame):
Give debug builds of JSC a method for calling dumpCallFrame so we can
inspect a callframe without requiring us to break in a debugger.
Modified Paths
- trunk/Source/_javascript_Core/ChangeLog
- trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def
- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp
- trunk/Source/_javascript_Core/bytecode/CodeBlock.h
- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp
- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp
- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp
- trunk/Source/_javascript_Core/interpreter/Interpreter.h
- trunk/Source/_javascript_Core/jsc.cpp
Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (122789 => 122790)
--- trunk/Source/_javascript_Core/ChangeLog 2012-07-17 00:57:54 UTC (rev 122789)
+++ trunk/Source/_javascript_Core/ChangeLog 2012-07-17 01:14:18 UTC (rev 122790)
@@ -1,3 +1,50 @@
+2012-07-16 Oliver Hunt <[email protected]>
+
+ dumpCallFrame is broken in ToT
+ https://bugs.webkit.org/show_bug.cgi?id=91444
+
+ Reviewed by Gavin Barraclough.
+
+ Various changes have been made to the SF calling convention, but
+ dumpCallFrame has not been updated to reflect these changes.
+ That resulted in both bogus information, as well as numerous
+ assertions of sadness.
+
+ This patch makes dumpCallFrame actually work again and adds the
+ wonderful feature of telling you the name of the variable that a
+ register reflects, or what value it contains.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::nameForRegister):
+ A really innefficient mechanism for finding the name of a local register.
+ This should only ever be used by debug code so this should be okay.
+ * bytecode/CodeBlock.h:
+ (CodeBlock):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::generate):
+ Debug builds no longer throw away a functions symbol table, this allows
+ us to actually perform a register# to name mapping
+ * dfg/DFGJITCompiler.cpp:
+ (JSC::DFG::JITCompiler::link):
+ We weren't propogating the bytecode offset here leading to assertions
+ in debug builds when dumping bytecode of DFG compiled code.
+ * interpreter/Interpreter.cpp:
+ (JSC):
+ (JSC::Interpreter::dumpRegisters):
+ Rework to actually be correct.
+ (JSC::getCallerInfo):
+ Return the byteocde offset as well now, given we have to determine it
+ anyway.
+ (JSC::Interpreter::getStackTrace):
+ (JSC::Interpreter::retrieveCallerFromVMCode):
+ * interpreter/Interpreter.h:
+ (Interpreter):
+ * jsc.cpp:
+ (GlobalObject::finishCreation):
+ (functionDumpCallFrame):
+ Give debug builds of JSC a method for calling dumpCallFrame so we can
+ inspect a callframe without requiring us to break in a debugger.
+
2012-07-16 Filip Pizlo <[email protected]>
Unreviewed, adding forgotten files.
Modified: trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def (122789 => 122790)
--- trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def 2012-07-17 00:57:54 UTC (rev 122789)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def 2012-07-17 01:14:18 UTC (rev 122790)
@@ -163,6 +163,7 @@
?displayName@JSFunction@JSC@@QAE?BVUString@2@PAVExecState@2@@Z
?dtoa@WTF@@YAXQADNAA_NAAHAAI@Z
?dumpAllOptions@Options@JSC@@SAXPAU_iobuf@@@Z
+ ?dumpCallFrame@Interpreter@JSC@@QAEXPAVExecState@2@@Z
?dumpSampleData@JSGlobalData@JSC@@QAEXPAVExecState@2@@Z
?empty@StringImpl@WTF@@SAPAV12@XZ
?enumerable@PropertyDescriptor@JSC@@QBE_NXZ
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (122789 => 122790)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2012-07-17 00:57:54 UTC (rev 122789)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2012-07-17 01:14:18 UTC (rev 122790)
@@ -2942,4 +2942,29 @@
return false;
}
+UString CodeBlock::nameForRegister(int registerNumber)
+{
+ SymbolTable::iterator end = m_symbolTable->end();
+ for (SymbolTable::iterator ptr = m_symbolTable->begin(); ptr != end; ++ptr) {
+ if (ptr->second.getIndex() == registerNumber)
+ return UString(ptr->first);
+ }
+ if (needsActivation() && registerNumber == activationRegister())
+ return "activation";
+ if (registerNumber == thisRegister())
+ return "this";
+ if (usesArguments()) {
+ if (registerNumber == argumentsRegister())
+ return "arguments";
+ if (unmodifiedArgumentsRegister(argumentsRegister()) == registerNumber)
+ return "real arguments";
+ }
+ if (registerNumber < 0) {
+ int argumentPosition = -registerNumber;
+ argumentPosition -= RegisterFile::CallFrameHeaderSize + 1;
+ return String::format("arguments[%3d]", argumentPosition - 1).impl();
+ }
+ return "";
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (122789 => 122790)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2012-07-17 00:57:54 UTC (rev 122789)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2012-07-17 01:14:18 UTC (rev 122790)
@@ -578,7 +578,9 @@
void createActivation(CallFrame*);
void clearEvalCache();
-
+
+ UString nameForRegister(int registerNumber);
+
void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
{
m_propertyAccessInstructions.append(propertyAccessInstruction);
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (122789 => 122790)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2012-07-17 00:57:54 UTC (rev 122789)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2012-07-17 01:14:18 UTC (rev 122790)
@@ -193,8 +193,10 @@
if (s_dumpsGeneratedCode)
m_codeBlock->dump(m_scopeChain->globalObject->globalExec());
+#ifdef NDEBUG
if ((m_codeType == FunctionCode && !m_codeBlock->needsFullScopeChain() && !m_codeBlock->usesArguments()) || m_codeType == EvalCode)
symbolTable().clear();
+#endif
m_codeBlock->shrinkToFit(CodeBlock::EarlyShrink);
Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp (122789 => 122790)
--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp 2012-07-17 00:57:54 UTC (rev 122789)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp 2012-07-17 01:14:18 UTC (rev 122790)
@@ -188,6 +188,7 @@
CallLinkInfo& info = m_codeBlock->callLinkInfo(i);
info.callType = m_jsCalls[i].m_callType;
info.isDFG = true;
+ info.bytecodeIndex = m_jsCalls[i].m_codeOrigin.bytecodeIndex;
linkBuffer.link(m_jsCalls[i].m_slowCall, FunctionPtr((m_globalData->getCTIStub(info.callType == CallLinkInfo::Construct ? linkConstructThunkGenerator : linkCallThunkGenerator)).code().executableAddress()));
info.callReturnLocation = linkBuffer.locationOfNearCall(m_jsCalls[i].m_slowCall);
info.hotPathBegin = linkBuffer.locationOf(m_jsCalls[i].m_targetToCheck);
Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (122789 => 122790)
--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp 2012-07-17 00:57:54 UTC (rev 122789)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp 2012-07-17 01:14:18 UTC (rev 122790)
@@ -77,6 +77,8 @@
namespace JSC {
+static CallFrame* getCallerInfo(JSGlobalData*, CallFrame*, int& lineNumber, unsigned& bytecodeOffset);
+
// Returns the depth of the scope chain within a given call frame.
static int depth(CodeBlock* codeBlock, ScopeChainNode* sc)
{
@@ -624,34 +626,42 @@
CodeBlock* codeBlock = callFrame->codeBlock();
const Register* it;
const Register* end;
- JSValue v;
- it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->numParameters();
- v = (*it).jsValue();
+ it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - callFrame->argumentCountIncludingThis();
+ end = callFrame->registers() - RegisterFile::CallFrameHeaderSize;
+ while (it < end) {
+ JSValue v = it->jsValue();
+ int registerNumber = it - callFrame->registers();
+ UString name = codeBlock->nameForRegister(registerNumber);
#if USE(JSVALUE32_64)
- dataLog("[this] | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v)); ++it;
+ dataLog("[r% 3d %14s] | %10p | %-16s 0x%llx \n", registerNumber, name.ascii().data(), it, v.description(), JSValue::encode(v));
#else
- dataLog("[this] | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v)); ++it;
+ dataLog("[r% 3d %14s] | %10p | %-16s %p \n", registerNumber, name.ascii().data(), it, v.description(), JSValue::encode(v));
#endif
- end = it + max(codeBlock->numParameters() - 1, 0); // - 1 to skip "this"
- if (it != end) {
- do {
- v = (*it).jsValue();
-#if USE(JSVALUE32_64)
- dataLog("[param] | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v));
-#else
- dataLog("[param] | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v));
-#endif
- ++it;
- } while (it != end);
+ it++;
}
+
dataLog("-----------------------------------------------------------------------------\n");
- dataLog("[CodeBlock] | %10p | %p \n", it, (*it).codeBlock()); ++it;
- dataLog("[ScopeChain] | %10p | %p \n", it, (*it).scopeChain()); ++it;
- dataLog("[CallerRegisters] | %10p | %d \n", it, (*it).i()); ++it;
- dataLog("[ReturnPC] | %10p | %p \n", it, (*it).vPC()); ++it;
- dataLog("[ArgumentCount] | %10p | %d \n", it, (*it).i()); ++it;
- dataLog("[Callee] | %10p | %p \n", it, (*it).function()); ++it;
+ dataLog("[ArgumentCount] | %10p | %ld \n", it, callFrame->argumentCount());
+ ++it;
+ dataLog("[CallerFrame] | %10p | %p \n", it, callFrame->callerFrame());
+ ++it;
+ dataLog("[Callee] | %10p | %p \n", it, callFrame->callee());
+ ++it;
+ dataLog("[ScopeChain] | %10p | %p \n", it, callFrame->scopeChain());
+ ++it;
+#if ENABLE(JIT)
+ AbstractPC pc = callFrame->abstractReturnPC(callFrame->globalData());
+ if (pc.hasJITReturnAddress())
+ dataLog("[ReturnJITPC] | %10p | %p \n", it, pc.jitReturnAddress().value());
+#endif
+ unsigned bytecodeOffset = 0;
+ int line = 0;
+ getCallerInfo(&callFrame->globalData(), callFrame, line, bytecodeOffset);
+ dataLog("[ReturnVPC] | %10p | %d (line %d)\n", it, bytecodeOffset, line);
+ ++it;
+ dataLog("[CodeBlock] | %10p | %p \n", it, callFrame->codeBlock());
+ ++it;
dataLog("-----------------------------------------------------------------------------\n");
int registerCount = 0;
@@ -659,11 +669,13 @@
end = it + codeBlock->m_numVars;
if (it != end) {
do {
- v = (*it).jsValue();
+ JSValue v = it->jsValue();
+ int registerNumber = it - callFrame->registers();
+ UString name = codeBlock->nameForRegister(registerNumber);
#if USE(JSVALUE32_64)
- dataLog("[r%2d] | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
+ dataLog("[r% 3d %14s] | %10p | %-16s 0x%llx \n", registerNumber, name.ascii().data(), it, v.description(), JSValue::encode(v));
#else
- dataLog("[r%2d] | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
+ dataLog("[r% 3d %14s] | %10p | %-16s %p \n", registerNumber, name.ascii().data(), it, v.description(), JSValue::encode(v));
#endif
++it;
++registerCount;
@@ -674,11 +686,11 @@
end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numVars;
if (it != end) {
do {
- v = (*it).jsValue();
+ JSValue v = (*it).jsValue();
#if USE(JSVALUE32_64)
- dataLog("[r%2d] | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
+ dataLog("[r% 3d] | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v));
#else
- dataLog("[r%2d] | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
+ dataLog("[r% 3d] | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v));
#endif
++it;
++registerCount;
@@ -838,10 +850,10 @@
#endif
}
-static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, int& lineNumber)
+static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, int& lineNumber, unsigned& bytecodeOffset)
{
UNUSED_PARAM(globalData);
- unsigned bytecodeOffset = 0;
+ bytecodeOffset = 0;
lineNumber = -1;
ASSERT(!callFrame->hasHostCallFrameFlag());
CallFrame* callerFrame = callFrame->codeBlock() ? callFrame->trueCallerFrame() : callFrame->callerFrame()->removeHostCallFrameFlag();
@@ -973,7 +985,8 @@
StackFrame s = { Strong<JSObject>(*globalData, callFrame->callee()), StackFrameNativeCode, Strong<ExecutableBase>(), -1, UString()};
results.append(s);
}
- callFrame = getCallerInfo(globalData, callFrame, line);
+ unsigned unusedBytecodeOffset = 0;
+ callFrame = getCallerInfo(globalData, callFrame, line, unusedBytecodeOffset);
}
}
@@ -5330,7 +5343,8 @@
return jsNull();
int lineNumber;
- CallFrame* callerFrame = getCallerInfo(&callFrame->globalData(), functionCallFrame, lineNumber);
+ unsigned bytecodeOffset;
+ CallFrame* callerFrame = getCallerInfo(&callFrame->globalData(), functionCallFrame, lineNumber, bytecodeOffset);
if (!callerFrame)
return jsNull();
JSValue caller = callerFrame->callee();
@@ -5340,7 +5354,7 @@
// Skip over function bindings.
ASSERT(caller.isObject());
while (asObject(caller)->inherits(&JSBoundFunction::s_info)) {
- callerFrame = getCallerInfo(&callFrame->globalData(), callerFrame, lineNumber);
+ callerFrame = getCallerInfo(&callFrame->globalData(), callerFrame, lineNumber, bytecodeOffset);
if (!callerFrame)
return jsNull();
caller = callerFrame->callee();
Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.h (122789 => 122790)
--- trunk/Source/_javascript_Core/interpreter/Interpreter.h 2012-07-17 00:57:54 UTC (rev 122789)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.h 2012-07-17 01:14:18 UTC (rev 122790)
@@ -248,6 +248,11 @@
void dumpSampleData(ExecState* exec);
void startSampling();
void stopSampling();
+
+#ifndef NDEBUG
+ JS_EXPORT_PRIVATE void dumpCallFrame(CallFrame*);
+#endif
+
private:
enum ExecutionFlag { Normal, InitializeAndReturn };
@@ -279,7 +284,6 @@
JSValue privateExecute(ExecutionFlag, RegisterFile*, CallFrame*);
- void dumpCallFrame(CallFrame*);
void dumpRegisters(CallFrame*);
bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); }
Modified: trunk/Source/_javascript_Core/jsc.cpp (122789 => 122790)
--- trunk/Source/_javascript_Core/jsc.cpp 2012-07-17 00:57:54 UTC (rev 122789)
+++ trunk/Source/_javascript_Core/jsc.cpp 2012-07-17 01:14:18 UTC (rev 122790)
@@ -88,6 +88,7 @@
static EncodedJSValue JSC_HOST_CALL functionGC(ExecState*);
#ifndef NDEBUG
static EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*);
#endif
static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
@@ -194,6 +195,7 @@
addFunction(globalData, "quit", functionQuit, 0);
addFunction(globalData, "gc", functionGC, 0);
#ifndef NDEBUG
+ addFunction(globalData, "dumpCallFrame", functionDumpCallFrame, 0);
addFunction(globalData, "releaseExecutableMemory", functionReleaseExecutableMemory, 0);
#endif
addFunction(globalData, "version", functionVersion, 1);
@@ -281,6 +283,15 @@
return JSValue::encode(jsUndefined());
}
+#ifndef NDEBUG
+EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec)
+{
+ if (!exec->callerFrame()->hasHostCallFrameFlag())
+ exec->globalData().interpreter->dumpCallFrame(exec->callerFrame());
+ return JSValue::encode(jsUndefined());
+}
+#endif
+
EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
{
fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->value(exec).utf8().data());
_______________________________________________ webkit-changes mailing list [email protected] http://lists.webkit.org/mailman/listinfo/webkit-changes
