Baseline JIT's disassembly should be just as pretty as the DFG's
https://bugs.webkit.org/show_bug.cgi?id=102873

Reviewed by Sam Weinig.

Integrated the CodeBlock's bytecode dumper with the JIT's disassembler. Also fixed
some type goof-ups (instructions are not in a Vector<Instruction> so using a Vector
iterator makes no sense) and stream-lined some things (you don't actually need a
full-fledged ExecState* to dump bytecode).

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::printUnaryOp):
(JSC::CodeBlock::printBinaryOp):
(JSC::CodeBlock::printConditionalJump):
(JSC::CodeBlock::printGetByIdOp):
(JSC::CodeBlock::printCallOp):
(JSC::CodeBlock::printPutByIdOp):
(JSC::CodeBlock::dump):
(JSC):
(JSC::CodeBlock::CodeBlock):
* bytecode/CodeBlock.h:
(CodeBlock):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::dumpCallFrame):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
(JSC::JIT::privateCompile):
* jit/JIT.h:
(JIT):
* jit/JITDisassembler.cpp: Added.
(JSC):
(JSC::JITDisassembler::JITDisassembler):
(JSC::JITDisassembler::~JITDisassembler):
(JSC::JITDisassembler::dump):
(JSC::JITDisassembler::dumpForInstructions):
(JSC::JITDisassembler::dumpDisassembly):
* jit/JITDisassembler.h: Added.
(JSC):
(JITDisassembler):
(JSC::JITDisassembler::setStartOfCode):
(JSC::JITDisassembler::setForBytecodeMainPath):
(JSC::JITDisassembler::setForBytecodeSlowPath):
(JSC::JITDisassembler::setEndOfSlowPath):
(JSC::JITDisassembler::setEndOfCode):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@135457 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index 9ce6139..161996a 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -164,7 +164,7 @@
     return "";
 }
 
-void CodeBlock::printUnaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op)
+void CodeBlock::printUnaryOp(ExecState* exec, int location, const Instruction*& it, const char* op)
 {
     int r0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
@@ -173,7 +173,7 @@
     dumpBytecodeCommentAndNewLine(location);
 }
 
-void CodeBlock::printBinaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op)
+void CodeBlock::printBinaryOp(ExecState* exec, int location, const Instruction*& it, const char* op)
 {
     int r0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
@@ -182,7 +182,7 @@
     dumpBytecodeCommentAndNewLine(location);
 }
 
-void CodeBlock::printConditionalJump(ExecState* exec, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator& it, int location, const char* op)
+void CodeBlock::printConditionalJump(ExecState* exec, const Instruction*, const Instruction*& it, int location, const char* op)
 {
     int r0 = (++it)->u.operand;
     int offset = (++it)->u.operand;
@@ -190,7 +190,7 @@
     dumpBytecodeCommentAndNewLine(location);
 }
 
-void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it)
+void CodeBlock::printGetByIdOp(ExecState* exec, int location, const Instruction*& it)
 {
     const char* op;
     switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
@@ -396,7 +396,7 @@
 #endif
 }
 
-void CodeBlock::printCallOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op, CacheDumpMode cacheDumpMode)
+void CodeBlock::printCallOp(ExecState* exec, int location, const Instruction*& it, const char* op, CacheDumpMode cacheDumpMode)
 {
     int func = (++it)->u.operand;
     int argCount = (++it)->u.operand;
@@ -426,7 +426,7 @@
     it += 2;
 }
 
-void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op)
+void CodeBlock::printPutByIdOp(ExecState* exec, int location, const Instruction*& it, const char* op)
 {
     int r0 = (++it)->u.operand;
     int id0 = (++it)->u.operand;
@@ -480,8 +480,12 @@
     ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_call) || vPC[0].u.opcode == interpreter->getOpcode(op_call_eval) || vPC[0].u.opcode == interpreter->getOpcode(op_construct));
 }
 
-void CodeBlock::dump(ExecState* exec)
+void CodeBlock::dump()
 {
+    // We only use the ExecState* for things that don't actually lead to JS execution,
+    // like converting a JSString to a String. Hence the globalExec is appropriate.
+    ExecState* exec = m_globalObject->globalExec();
+    
     size_t instructionCount = 0;
 
     for (size_t i = 0; i < instructions().size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(instructions()[i].u.opcode)])
@@ -505,9 +509,9 @@
         dataLog("; activation in r%d", activationRegister());
     dataLog("\n\n");
 
-    Vector<Instruction>::const_iterator begin = instructions().begin();
-    Vector<Instruction>::const_iterator end = instructions().end();
-    for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)
+    const Instruction* begin = instructions().begin();
+    const Instruction* end = instructions().end();
+    for (const Instruction* it = begin; it != end; ++it)
         dump(exec, begin, it);
 
     if (!m_identifiers.isEmpty()) {
@@ -603,7 +607,7 @@
     dataLog("\n");
 }
 
-void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it)
+void CodeBlock::dump(ExecState* exec, const Instruction* begin, const Instruction*& it)
 {
     int location = it - begin;
     switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
@@ -1454,6 +1458,13 @@
     }
 }
 
+void CodeBlock::dump(unsigned bytecodeOffset)
+{
+    ExecState* exec = m_globalObject->globalExec();
+    const Instruction* it = instructions().begin() + bytecodeOffset;
+    dump(exec, instructions().begin(), it);
+}
+
 #if DUMP_CODE_BLOCK_STATISTICS
 static HashSet<CodeBlock*> liveCodeBlockSet;
 #endif
@@ -1881,7 +1892,7 @@
     m_instructions = WTF::RefCountedArray<Instruction>(instructions);
 
     if (BytecodeGenerator::dumpsGeneratedCode())
-        dump(m_globalObject->globalExec());
+        dump();
     m_globalData->finishedCompiling(this);
 }