diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-22 09:09:45 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-22 09:10:13 +0100 |
commit | 470286ecfe79d59df14944e5b5d34630fc739391 (patch) | |
tree | 43983212872e06cebefd2ae474418fa2908ca54c /Source/JavaScriptCore/bytecode/CodeBlock.cpp | |
parent | 23037105e948c2065da5a937d3a2396b0ff45c1e (diff) | |
download | qtwebkit-470286ecfe79d59df14944e5b5d34630fc739391.tar.gz |
Imported WebKit commit e89504fa9195b2063b2530961d4b73dd08de3242 (http://svn.webkit.org/repository/webkit/trunk@135485)
Change-Id: I03774e5ac79721c13ffa30d152537a74d0b12e66
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'Source/JavaScriptCore/bytecode/CodeBlock.cpp')
-rw-r--r-- | Source/JavaScriptCore/bytecode/CodeBlock.cpp | 569 |
1 files changed, 356 insertions, 213 deletions
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp index 5686d5d2c..206d281a2 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp @@ -32,6 +32,7 @@ #include "BytecodeGenerator.h" #include "DFGCapabilities.h" +#include "DFGCommon.h" #include "DFGNode.h" #include "DFGRepatch.h" #include "Debugger.h" @@ -44,7 +45,7 @@ #include "JSValue.h" #include "LowLevelInterpreter.h" #include "RepatchBuffer.h" -#include "SlotVisitorInlineMethods.h" +#include "SlotVisitorInlines.h" #include <stdio.h> #include <wtf/StringExtras.h> #include <wtf/UnusedParam.h> @@ -98,11 +99,11 @@ void CodeBlock::dumpBytecodeCommentAndNewLine(int location) #if ENABLE(BYTECODE_COMMENTS) const char* comment = commentForBytecodeOffset(location); if (comment) - dataLog("\t\t ; %s", comment); + dataLogF("\t\t ; %s", comment); #else UNUSED_PARAM(location); #endif - dataLog("\n"); + dataLogF("\n"); } CString CodeBlock::registerName(ExecState* exec, int r) const @@ -163,33 +164,33 @@ NEVER_INLINE static const char* debugHookName(int debugHookID) 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; - dataLog("[%4d] %s\t\t %s, %s", location, op, registerName(exec, r0).data(), registerName(exec, r1).data()); + dataLogF("[%4d] %s\t\t %s, %s", location, op, registerName(exec, r0).data(), registerName(exec, r1).data()); 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; int r2 = (++it)->u.operand; - dataLog("[%4d] %s\t\t %s, %s, %s", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dataLogF("[%4d] %s\t\t %s, %s, %s", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); 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; - dataLog("[%4d] %s\t\t %s, %d(->%d)", location, op, registerName(exec, r0).data(), offset, location + offset); + dataLogF("[%4d] %s\t\t %s, %d(->%d)", location, op, registerName(exec, r0).data(), offset, location + offset); 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)) { @@ -242,7 +243,7 @@ void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int id0 = (++it)->u.operand; - dataLog("[%4d] %s\t %s, %s, %s", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); + dataLogF("[%4d] %s\t %s, %s, %s", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); it += 5; } @@ -252,18 +253,18 @@ static void dumpStructure(const char* name, ExecState* exec, Structure* structur if (!structure) return; - dataLog("%s = %p", name, structure); + dataLogF("%s = %p", name, structure); PropertyOffset offset = structure->get(exec->globalData(), ident); if (offset != invalidOffset) - dataLog(" (offset = %d)", offset); + dataLogF(" (offset = %d)", offset); } #endif #if ENABLE(JIT) // unused when not ENABLE(JIT), leading to silly warnings static void dumpChain(ExecState* exec, StructureChain* chain, Identifier& ident) { - dataLog("chain = %p: [", chain); + dataLogF("chain = %p: [", chain); bool first = true; for (WriteBarrier<Structure>* currentStructure = chain->head(); *currentStructure; @@ -271,10 +272,10 @@ static void dumpChain(ExecState* exec, StructureChain* chain, Identifier& ident) if (first) first = false; else - dataLog(", "); + dataLogF(", "); dumpStructure("struct", exec, currentStructure->get(), ident); } - dataLog("]"); + dataLogF("]"); } #endif @@ -288,21 +289,21 @@ void CodeBlock::printGetByIdCacheStatus(ExecState* exec, int location) #if ENABLE(LLINT) if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_get_array_length) - dataLog(" llint(array_length)"); + dataLogF(" llint(array_length)"); else { Structure* structure = instruction[4].u.structure.get(); - dataLog(" llint("); + dataLogF(" llint("); dumpStructure("struct", exec, structure, ident); - dataLog(")"); + dataLogF(")"); } #endif #if ENABLE(JIT) if (numberOfStructureStubInfos()) { - dataLog(" jit("); + dataLogF(" jit("); StructureStubInfo& stubInfo = getStubInfo(location); if (!stubInfo.seen) - dataLog("not seen"); + dataLogF("not seen"); else { Structure* baseStructure = 0; Structure* prototypeStructure = 0; @@ -312,40 +313,40 @@ void CodeBlock::printGetByIdCacheStatus(ExecState* exec, int location) switch (stubInfo.accessType) { case access_get_by_id_self: - dataLog("self"); + dataLogF("self"); baseStructure = stubInfo.u.getByIdSelf.baseObjectStructure.get(); break; case access_get_by_id_proto: - dataLog("proto"); + dataLogF("proto"); baseStructure = stubInfo.u.getByIdProto.baseObjectStructure.get(); prototypeStructure = stubInfo.u.getByIdProto.prototypeStructure.get(); break; case access_get_by_id_chain: - dataLog("chain"); + dataLogF("chain"); baseStructure = stubInfo.u.getByIdChain.baseObjectStructure.get(); chain = stubInfo.u.getByIdChain.chain.get(); break; case access_get_by_id_self_list: - dataLog("self_list"); + dataLogF("self_list"); structureList = stubInfo.u.getByIdSelfList.structureList; listSize = stubInfo.u.getByIdSelfList.listSize; break; case access_get_by_id_proto_list: - dataLog("proto_list"); + dataLogF("proto_list"); structureList = stubInfo.u.getByIdProtoList.structureList; listSize = stubInfo.u.getByIdProtoList.listSize; break; case access_unset: - dataLog("unset"); + dataLogF("unset"); break; case access_get_by_id_generic: - dataLog("generic"); + dataLogF("generic"); break; case access_get_array_length: - dataLog("array_length"); + dataLogF("array_length"); break; case access_get_string_length: - dataLog("string_length"); + dataLogF("string_length"); break; default: ASSERT_NOT_REACHED(); @@ -353,71 +354,71 @@ void CodeBlock::printGetByIdCacheStatus(ExecState* exec, int location) } if (baseStructure) { - dataLog(", "); + dataLogF(", "); dumpStructure("struct", exec, baseStructure, ident); } if (prototypeStructure) { - dataLog(", "); + dataLogF(", "); dumpStructure("prototypeStruct", exec, baseStructure, ident); } if (chain) { - dataLog(", "); + dataLogF(", "); dumpChain(exec, chain, ident); } if (structureList) { - dataLog(", list = %p: [", structureList); + dataLogF(", list = %p: [", structureList); for (int i = 0; i < listSize; ++i) { if (i) - dataLog(", "); - dataLog("("); + dataLogF(", "); + dataLogF("("); dumpStructure("base", exec, structureList->list[i].base.get(), ident); if (structureList->list[i].isChain) { if (structureList->list[i].u.chain.get()) { - dataLog(", "); + dataLogF(", "); dumpChain(exec, structureList->list[i].u.chain.get(), ident); } } else { if (structureList->list[i].u.proto.get()) { - dataLog(", "); + dataLogF(", "); dumpStructure("proto", exec, structureList->list[i].u.proto.get(), ident); } } - dataLog(")"); + dataLogF(")"); } - dataLog("]"); + dataLogF("]"); } } - dataLog(")"); + dataLogF(")"); } #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; int registerOffset = (++it)->u.operand; - dataLog("[%4d] %s\t %s, %d, %d", location, op, registerName(exec, func).data(), argCount, registerOffset); + dataLogF("[%4d] %s\t %s, %d, %d", location, op, registerName(exec, func).data(), argCount, registerOffset); if (cacheDumpMode == DumpCaches) { #if ENABLE(LLINT) LLIntCallLinkInfo* callLinkInfo = it[1].u.callLinkInfo; if (callLinkInfo->lastSeenCallee) { - dataLog(" llint(%p, exec %p)", + dataLogF(" llint(%p, exec %p)", callLinkInfo->lastSeenCallee.get(), callLinkInfo->lastSeenCallee->executable()); } else - dataLog(" llint(not set)"); + dataLogF(" llint(not set)"); #endif #if ENABLE(JIT) if (numberOfCallLinkInfos()) { JSFunction* target = getCallLinkInfo(location).lastSeenCallee.get(); if (target) - dataLog(" jit(%p, exec %p)", target, target->executable()); + dataLogF(" jit(%p, exec %p)", target, target->executable()); else - dataLog(" jit(not set)"); + dataLogF(" jit(not set)"); } #endif } @@ -425,12 +426,12 @@ void CodeBlock::printCallOp(ExecState* exec, int location, Vector<Instruction>:: 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; int r1 = (++it)->u.operand; - dataLog("[%4d] %s\t %s, %s, %s", location, op, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); + dataLogF("[%4d] %s\t %s, %s, %s", location, op, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); dumpBytecodeCommentAndNewLine(location); it += 5; } @@ -438,7 +439,7 @@ void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) { unsigned instructionOffset = vPC - instructions().begin(); - dataLog(" [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).utf8().data()); + dataLogF(" [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).utf8().data()); } void CodeBlock::printStructures(const Instruction* vPC) @@ -455,15 +456,15 @@ void CodeBlock::printStructures(const Instruction* vPC) return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) { - dataLog(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).utf8().data(), pointerToSourceString(vPC[5].u.structure).utf8().data()); + dataLogF(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).utf8().data(), pointerToSourceString(vPC[5].u.structure).utf8().data()); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) { - dataLog(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(vPC[4].u.structure).utf8().data(), pointerToSourceString(vPC[5].u.structure).utf8().data(), pointerToSourceString(vPC[6].u.structureChain).utf8().data()); + dataLogF(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(vPC[4].u.structure).utf8().data(), pointerToSourceString(vPC[5].u.structure).utf8().data(), pointerToSourceString(vPC[6].u.structureChain).utf8().data()); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) { - dataLog(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).utf8().data(), pointerToSourceString(vPC[5].u.structureChain).utf8().data()); + dataLogF(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).utf8().data(), pointerToSourceString(vPC[5].u.structureChain).utf8().data()); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id)) { @@ -479,99 +480,103 @@ void CodeBlock::printStructures(const Instruction* vPC) 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)]) ++instructionCount; - dataLog( + dataLogF( "%lu m_instructions; %lu bytes at %p (%s); %d parameter(s); %d callee register(s); %d variable(s)", static_cast<unsigned long>(instructions().size()), static_cast<unsigned long>(instructions().size() * sizeof(Instruction)), this, codeTypeToString(codeType()), m_numParameters, m_numCalleeRegisters, m_numVars); if (symbolTable()->captureCount()) - dataLog("; %d captured var(s)", symbolTable()->captureCount()); + dataLogF("; %d captured var(s)", symbolTable()->captureCount()); if (usesArguments()) { - dataLog( + dataLogF( "; uses arguments, in r%d, r%d", argumentsRegister(), unmodifiedArgumentsRegister(argumentsRegister())); } if (needsFullScopeChain() && codeType() == FunctionCode) - dataLog("; activation in r%d", activationRegister()); - dataLog("\n\n"); + dataLogF("; activation in r%d", activationRegister()); + dataLogF("\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()) { - dataLog("\nIdentifiers:\n"); + dataLogF("\nIdentifiers:\n"); size_t i = 0; do { - dataLog(" id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].string().utf8().data()); + dataLogF(" id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].string().utf8().data()); ++i; } while (i != m_identifiers.size()); } if (!m_constantRegisters.isEmpty()) { - dataLog("\nConstants:\n"); + dataLogF("\nConstants:\n"); size_t i = 0; do { - dataLog(" k%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, m_constantRegisters[i].get()).utf8().data()); + dataLogF(" k%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, m_constantRegisters[i].get()).utf8().data()); ++i; } while (i < m_constantRegisters.size()); } if (size_t count = m_unlinkedCode->numberOfRegExps()) { - dataLog("\nm_regexps:\n"); + dataLogF("\nm_regexps:\n"); size_t i = 0; do { - dataLog(" re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_unlinkedCode->regexp(i)).utf8().data()); + dataLogF(" re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_unlinkedCode->regexp(i)).utf8().data()); ++i; } while (i < count); } #if ENABLE(JIT) if (!m_structureStubInfos.isEmpty()) - dataLog("\nStructures:\n"); + dataLogF("\nStructures:\n"); #endif if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) { - dataLog("\nException Handlers:\n"); + dataLogF("\nException Handlers:\n"); unsigned i = 0; do { - dataLog("\t %d: { start: [%4d] end: [%4d] target: [%4d] }\n", i + 1, m_rareData->m_exceptionHandlers[i].start, m_rareData->m_exceptionHandlers[i].end, m_rareData->m_exceptionHandlers[i].target); + dataLogF("\t %d: { start: [%4d] end: [%4d] target: [%4d] }\n", i + 1, m_rareData->m_exceptionHandlers[i].start, m_rareData->m_exceptionHandlers[i].end, m_rareData->m_exceptionHandlers[i].target); ++i; } while (i < m_rareData->m_exceptionHandlers.size()); } if (m_rareData && !m_rareData->m_immediateSwitchJumpTables.isEmpty()) { - dataLog("Immediate Switch Jump Tables:\n"); + dataLogF("Immediate Switch Jump Tables:\n"); unsigned i = 0; do { - dataLog(" %1d = {\n", i); + dataLogF(" %1d = {\n", i); int entry = 0; Vector<int32_t>::const_iterator end = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.end(); for (Vector<int32_t>::const_iterator iter = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) { if (!*iter) continue; - dataLog("\t\t%4d => %04d\n", entry + m_rareData->m_immediateSwitchJumpTables[i].min, *iter); + dataLogF("\t\t%4d => %04d\n", entry + m_rareData->m_immediateSwitchJumpTables[i].min, *iter); } - dataLog(" }\n"); + dataLogF(" }\n"); ++i; } while (i < m_rareData->m_immediateSwitchJumpTables.size()); } if (m_rareData && !m_rareData->m_characterSwitchJumpTables.isEmpty()) { - dataLog("\nCharacter Switch Jump Tables:\n"); + dataLogF("\nCharacter Switch Jump Tables:\n"); unsigned i = 0; do { - dataLog(" %1d = {\n", i); + dataLogF(" %1d = {\n", i); int entry = 0; Vector<int32_t>::const_iterator end = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.end(); for (Vector<int32_t>::const_iterator iter = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) { @@ -579,72 +584,79 @@ void CodeBlock::dump(ExecState* exec) continue; ASSERT(!((i + m_rareData->m_characterSwitchJumpTables[i].min) & ~0xFFFF)); UChar ch = static_cast<UChar>(entry + m_rareData->m_characterSwitchJumpTables[i].min); - dataLog("\t\t\"%s\" => %04d\n", String(&ch, 1).utf8().data(), *iter); + dataLogF("\t\t\"%s\" => %04d\n", String(&ch, 1).utf8().data(), *iter); } - dataLog(" }\n"); + dataLogF(" }\n"); ++i; } while (i < m_rareData->m_characterSwitchJumpTables.size()); } if (m_rareData && !m_rareData->m_stringSwitchJumpTables.isEmpty()) { - dataLog("\nString Switch Jump Tables:\n"); + dataLogF("\nString Switch Jump Tables:\n"); unsigned i = 0; do { - dataLog(" %1d = {\n", i); + dataLogF(" %1d = {\n", i); StringJumpTable::StringOffsetTable::const_iterator end = m_rareData->m_stringSwitchJumpTables[i].offsetTable.end(); for (StringJumpTable::StringOffsetTable::const_iterator iter = m_rareData->m_stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter) - dataLog("\t\t\"%s\" => %04d\n", String(iter->key).utf8().data(), iter->value.branchOffset); - dataLog(" }\n"); + dataLogF("\t\t\"%s\" => %04d\n", String(iter->key).utf8().data(), iter->value.branchOffset); + dataLogF(" }\n"); ++i; } while (i < m_rareData->m_stringSwitchJumpTables.size()); } - dataLog("\n"); + dataLogF("\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)) { case op_enter: { - dataLog("[%4d] enter", location); + dataLogF("[%4d] enter", location); dumpBytecodeCommentAndNewLine(location); break; } case op_create_activation: { int r0 = (++it)->u.operand; - dataLog("[%4d] create_activation %s", location, registerName(exec, r0).data()); + dataLogF("[%4d] create_activation %s", location, registerName(exec, r0).data()); dumpBytecodeCommentAndNewLine(location); break; } case op_create_arguments: { int r0 = (++it)->u.operand; - dataLog("[%4d] create_arguments\t %s", location, registerName(exec, r0).data()); + dataLogF("[%4d] create_arguments\t %s", location, registerName(exec, r0).data()); dumpBytecodeCommentAndNewLine(location); break; } case op_init_lazy_reg: { int r0 = (++it)->u.operand; - dataLog("[%4d] init_lazy_reg\t %s", location, registerName(exec, r0).data()); + dataLogF("[%4d] init_lazy_reg\t %s", location, registerName(exec, r0).data()); dumpBytecodeCommentAndNewLine(location); break; } + case op_get_callee: { + int r0 = (++it)->u.operand; + dataLogF("[%4d] op_get_callee %s\n", location, registerName(exec, r0).data()); + ++it; + break; + } case op_create_this: { int r0 = (++it)->u.operand; - dataLog("[%4d] create_this %s", location, registerName(exec, r0).data()); + int r1 = (++it)->u.operand; + dataLogF("[%4d] create_this %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); dumpBytecodeCommentAndNewLine(location); break; } case op_convert_this: { int r0 = (++it)->u.operand; - dataLog("[%4d] convert_this\t %s", location, registerName(exec, r0).data()); + dataLogF("[%4d] convert_this\t %s", location, registerName(exec, r0).data()); dumpBytecodeCommentAndNewLine(location); ++it; // Skip value profile. break; } case op_new_object: { int r0 = (++it)->u.operand; - dataLog("[%4d] new_object\t %s", location, registerName(exec, r0).data()); + dataLogF("[%4d] new_object\t %s", location, registerName(exec, r0).data()); dumpBytecodeCommentAndNewLine(location); break; } @@ -652,40 +664,43 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int dst = (++it)->u.operand; int argv = (++it)->u.operand; int argc = (++it)->u.operand; - dataLog("[%4d] new_array\t %s, %s, %d", location, registerName(exec, dst).data(), registerName(exec, argv).data(), argc); + dataLogF("[%4d] new_array\t %s, %s, %d", location, registerName(exec, dst).data(), registerName(exec, argv).data(), argc); dumpBytecodeCommentAndNewLine(location); + ++it; // Skip array allocation profile. break; } case op_new_array_with_size: { int dst = (++it)->u.operand; int length = (++it)->u.operand; - dataLog("[%4d] new_array_with_size\t %s, %s", location, registerName(exec, dst).data(), registerName(exec, length).data()); + dataLogF("[%4d] new_array_with_size\t %s, %s", location, registerName(exec, dst).data(), registerName(exec, length).data()); dumpBytecodeCommentAndNewLine(location); + ++it; // Skip array allocation profile. break; } case op_new_array_buffer: { int dst = (++it)->u.operand; int argv = (++it)->u.operand; int argc = (++it)->u.operand; - dataLog("[%4d] new_array_buffer\t %s, %d, %d", location, registerName(exec, dst).data(), argv, argc); + dataLogF("[%4d] new_array_buffer\t %s, %d, %d", location, registerName(exec, dst).data(), argv, argc); dumpBytecodeCommentAndNewLine(location); + ++it; // Skip array allocation profile. break; } case op_new_regexp: { int r0 = (++it)->u.operand; int re0 = (++it)->u.operand; - dataLog("[%4d] new_regexp\t %s, ", location, registerName(exec, r0).data()); + dataLogF("[%4d] new_regexp\t %s, ", location, registerName(exec, r0).data()); if (r0 >=0 && r0 < (int)m_unlinkedCode->numberOfRegExps()) - dataLog("%s", regexpName(re0, regexp(re0)).data()); + dataLogF("%s", regexpName(re0, regexp(re0)).data()); else - dataLog("bad_regexp(%d)", re0); + dataLogF("bad_regexp(%d)", re0); dumpBytecodeCommentAndNewLine(location); break; } case op_mov: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - dataLog("[%4d] mov\t\t %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); + dataLogF("[%4d] mov\t\t %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); dumpBytecodeCommentAndNewLine(location); break; } @@ -735,13 +750,13 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& } case op_pre_inc: { int r0 = (++it)->u.operand; - dataLog("[%4d] pre_inc\t\t %s", location, registerName(exec, r0).data()); + dataLogF("[%4d] pre_inc\t\t %s", location, registerName(exec, r0).data()); dumpBytecodeCommentAndNewLine(location); break; } case op_pre_dec: { int r0 = (++it)->u.operand; - dataLog("[%4d] pre_dec\t\t %s", location, registerName(exec, r0).data()); + dataLogF("[%4d] pre_dec\t\t %s", location, registerName(exec, r0).data()); dumpBytecodeCommentAndNewLine(location); break; } @@ -817,7 +832,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] check_has_instance\t\t %s, %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), offset, location + offset); + dataLogF("[%4d] check_has_instance\t\t %s, %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), offset, location + offset); dumpBytecodeCommentAndNewLine(location); break; } @@ -825,7 +840,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - dataLog("[%4d] instanceof\t\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dataLogF("[%4d] instanceof\t\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); dumpBytecodeCommentAndNewLine(location); break; } @@ -867,7 +882,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int id0 = (++it)->u.operand; int value = (++it)->u.operand; int resolveInfo = (++it)->u.operand; - dataLog("[%4d] put_to_base\t %s, %s, %s, %d", location, registerName(exec, base).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, value).data(), resolveInfo); + dataLogF("[%4d] put_to_base\t %s, %s, %s, %d", location, registerName(exec, base).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, value).data(), resolveInfo); dumpBytecodeCommentAndNewLine(location); break; } @@ -880,13 +895,13 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; int resolveInfo = (++it)->u.operand; - dataLog("[%4d] resolve\t\t %s, %s, %d", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo); + dataLogF("[%4d] resolve\t\t %s, %s, %d", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo); dumpBytecodeCommentAndNewLine(location); it++; break; } case op_init_global_const_nop: { - dataLog("[%4d] init_global_const_nop\t", location); + dataLogF("[%4d] init_global_const_nop\t", location); dumpBytecodeCommentAndNewLine(location); it++; it++; @@ -897,7 +912,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& case op_init_global_const: { WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer; int r0 = (++it)->u.operand; - dataLog("[%4d] init_global_const\t g%d(%p), %s", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data()); + dataLogF("[%4d] init_global_const\t g%d(%p), %s", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data()); dumpBytecodeCommentAndNewLine(location); it++; it++; @@ -906,7 +921,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& case op_init_global_const_check: { WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer; int r0 = (++it)->u.operand; - dataLog("[%4d] init_global_const_check\t g%d(%p), %s", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data()); + dataLogF("[%4d] init_global_const_check\t g%d(%p), %s", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data()); dumpBytecodeCommentAndNewLine(location); it++; it++; @@ -922,7 +937,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int isStrict = (++it)->u.operand; int resolveInfo = (++it)->u.operand; int putToBaseInfo = (++it)->u.operand; - dataLog("[%4d] resolve_base%s\t %s, %s, %d, %d", location, isStrict ? "_strict" : "", registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo, putToBaseInfo); + dataLogF("[%4d] resolve_base%s\t %s, %s, %d, %d", location, isStrict ? "_strict" : "", registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo, putToBaseInfo); dumpBytecodeCommentAndNewLine(location); it++; break; @@ -930,7 +945,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& case op_ensure_property_exists: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; - dataLog("[%4d] ensure_property_exists\t %s, %s", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); + dataLogF("[%4d] ensure_property_exists\t %s, %s", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); dumpBytecodeCommentAndNewLine(location); break; } @@ -940,7 +955,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int id0 = (++it)->u.operand; int resolveInfo = (++it)->u.operand; int putToBaseInfo = (++it)->u.operand; - dataLog("[%4d] resolve_with_base %s, %s, %s, %d, %d", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo, putToBaseInfo); + dataLogF("[%4d] resolve_with_base %s, %s, %s, %d, %d", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo, putToBaseInfo); dumpBytecodeCommentAndNewLine(location); it++; break; @@ -950,7 +965,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r1 = (++it)->u.operand; int id0 = (++it)->u.operand; int resolveInfo = (++it)->u.operand; - dataLog("[%4d] resolve_with_this %s, %s, %s, %d", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo); + dataLogF("[%4d] resolve_with_this %s, %s, %s, %d", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo); dumpBytecodeCommentAndNewLine(location); it++; break; @@ -1020,7 +1035,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int id0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - dataLog("[%4d] put_getter_setter\t %s, %s, %s, %s", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dataLogF("[%4d] put_getter_setter\t %s, %s, %s, %s", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); dumpBytecodeCommentAndNewLine(location); break; } @@ -1028,7 +1043,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int id0 = (++it)->u.operand; - dataLog("[%4d] del_by_id\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); + dataLogF("[%4d] del_by_id\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); dumpBytecodeCommentAndNewLine(location); break; } @@ -1036,7 +1051,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - dataLog("[%4d] get_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dataLogF("[%4d] get_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); dumpBytecodeCommentAndNewLine(location); it++; it++; @@ -1046,7 +1061,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - dataLog("[%4d] get_argument_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dataLogF("[%4d] get_argument_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); dumpBytecodeCommentAndNewLine(location); ++it; ++it; @@ -1059,7 +1074,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r3 = (++it)->u.operand; int r4 = (++it)->u.operand; int r5 = (++it)->u.operand; - dataLog("[%4d] get_by_pname\t %s, %s, %s, %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), registerName(exec, r4).data(), registerName(exec, r5).data()); + dataLogF("[%4d] get_by_pname\t %s, %s, %s, %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), registerName(exec, r4).data(), registerName(exec, r5).data()); dumpBytecodeCommentAndNewLine(location); break; } @@ -1067,7 +1082,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - dataLog("[%4d] put_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dataLogF("[%4d] put_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); dumpBytecodeCommentAndNewLine(location); ++it; break; @@ -1076,7 +1091,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - dataLog("[%4d] del_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dataLogF("[%4d] del_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); dumpBytecodeCommentAndNewLine(location); break; } @@ -1084,19 +1099,19 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; unsigned n0 = (++it)->u.operand; int r1 = (++it)->u.operand; - dataLog("[%4d] put_by_index\t %s, %u, %s", location, registerName(exec, r0).data(), n0, registerName(exec, r1).data()); + dataLogF("[%4d] put_by_index\t %s, %u, %s", location, registerName(exec, r0).data(), n0, registerName(exec, r1).data()); dumpBytecodeCommentAndNewLine(location); break; } case op_jmp: { int offset = (++it)->u.operand; - dataLog("[%4d] jmp\t\t %d(->%d)", location, offset, location + offset); + dataLogF("[%4d] jmp\t\t %d(->%d)", location, offset, location + offset); dumpBytecodeCommentAndNewLine(location); break; } case op_loop: { int offset = (++it)->u.operand; - dataLog("[%4d] loop\t\t %d(->%d)", location, offset, location + offset); + dataLogF("[%4d] loop\t\t %d(->%d)", location, offset, location + offset); dumpBytecodeCommentAndNewLine(location); break; } @@ -1128,7 +1143,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; Special::Pointer pointer = (++it)->u.specialPointer; int offset = (++it)->u.operand; - dataLog("[%4d] jneq_ptr\t\t %s, %d (%p), %d(->%d)", location, registerName(exec, r0).data(), pointer, m_globalObject->actualPointerFor(pointer), offset, location + offset); + dataLogF("[%4d] jneq_ptr\t\t %s, %d (%p), %d(->%d)", location, registerName(exec, r0).data(), pointer, m_globalObject->actualPointerFor(pointer), offset, location + offset); dumpBytecodeCommentAndNewLine(location); break; } @@ -1136,7 +1151,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jless\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLogF("[%4d] jless\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); dumpBytecodeCommentAndNewLine(location); break; } @@ -1144,7 +1159,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jlesseq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLogF("[%4d] jlesseq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); dumpBytecodeCommentAndNewLine(location); break; } @@ -1152,7 +1167,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jgreater\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLogF("[%4d] jgreater\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); dumpBytecodeCommentAndNewLine(location); break; } @@ -1160,7 +1175,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jgreatereq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLogF("[%4d] jgreatereq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); dumpBytecodeCommentAndNewLine(location); break; } @@ -1168,7 +1183,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jnless\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLogF("[%4d] jnless\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); dumpBytecodeCommentAndNewLine(location); break; } @@ -1176,7 +1191,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jnlesseq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLogF("[%4d] jnlesseq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); dumpBytecodeCommentAndNewLine(location); break; } @@ -1184,7 +1199,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jngreater\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLogF("[%4d] jngreater\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); dumpBytecodeCommentAndNewLine(location); break; } @@ -1192,7 +1207,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jngreatereq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLogF("[%4d] jngreatereq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); dumpBytecodeCommentAndNewLine(location); break; } @@ -1200,7 +1215,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] loop_if_less\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLogF("[%4d] loop_if_less\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); dumpBytecodeCommentAndNewLine(location); break; } @@ -1208,7 +1223,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLogF("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); dumpBytecodeCommentAndNewLine(location); break; } @@ -1216,7 +1231,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] loop_if_greater\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLogF("[%4d] loop_if_greater\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); dumpBytecodeCommentAndNewLine(location); break; } @@ -1224,12 +1239,12 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] loop_if_greatereq\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLogF("[%4d] loop_if_greatereq\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); dumpBytecodeCommentAndNewLine(location); break; } case op_loop_hint: { - dataLog("[%4d] loop_hint", location); + dataLogF("[%4d] loop_hint", location); dumpBytecodeCommentAndNewLine(location); break; } @@ -1237,7 +1252,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int tableIndex = (++it)->u.operand; int defaultTarget = (++it)->u.operand; int scrutineeRegister = (++it)->u.operand; - dataLog("[%4d] switch_imm\t %d, %d(->%d), %s", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); + dataLogF("[%4d] switch_imm\t %d, %d(->%d), %s", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); dumpBytecodeCommentAndNewLine(location); break; } @@ -1245,7 +1260,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int tableIndex = (++it)->u.operand; int defaultTarget = (++it)->u.operand; int scrutineeRegister = (++it)->u.operand; - dataLog("[%4d] switch_char\t %d, %d(->%d), %s", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); + dataLogF("[%4d] switch_char\t %d, %d(->%d), %s", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); dumpBytecodeCommentAndNewLine(location); break; } @@ -1253,7 +1268,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int tableIndex = (++it)->u.operand; int defaultTarget = (++it)->u.operand; int scrutineeRegister = (++it)->u.operand; - dataLog("[%4d] switch_string\t %d, %d(->%d), %s", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); + dataLogF("[%4d] switch_string\t %d, %d(->%d), %s", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); dumpBytecodeCommentAndNewLine(location); break; } @@ -1261,14 +1276,14 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int f0 = (++it)->u.operand; int shouldCheck = (++it)->u.operand; - dataLog("[%4d] new_func\t\t %s, f%d, %s", location, registerName(exec, r0).data(), f0, shouldCheck ? "<Checked>" : "<Unchecked>"); + dataLogF("[%4d] new_func\t\t %s, f%d, %s", location, registerName(exec, r0).data(), f0, shouldCheck ? "<Checked>" : "<Unchecked>"); dumpBytecodeCommentAndNewLine(location); break; } case op_new_func_exp: { int r0 = (++it)->u.operand; int f0 = (++it)->u.operand; - dataLog("[%4d] new_func_exp\t %s, f%d", location, registerName(exec, r0).data(), f0); + dataLogF("[%4d] new_func_exp\t %s, f%d", location, registerName(exec, r0).data(), f0); dumpBytecodeCommentAndNewLine(location); break; } @@ -1285,32 +1300,32 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int thisValue = (++it)->u.operand; int arguments = (++it)->u.operand; int firstFreeRegister = (++it)->u.operand; - dataLog("[%4d] call_varargs\t %s, %s, %s, %d", location, registerName(exec, callee).data(), registerName(exec, thisValue).data(), registerName(exec, arguments).data(), firstFreeRegister); + dataLogF("[%4d] call_varargs\t %s, %s, %s, %d", location, registerName(exec, callee).data(), registerName(exec, thisValue).data(), registerName(exec, arguments).data(), firstFreeRegister); dumpBytecodeCommentAndNewLine(location); break; } case op_tear_off_activation: { int r0 = (++it)->u.operand; - dataLog("[%4d] tear_off_activation\t %s", location, registerName(exec, r0).data()); + dataLogF("[%4d] tear_off_activation\t %s", location, registerName(exec, r0).data()); dumpBytecodeCommentAndNewLine(location); break; } case op_tear_off_arguments: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - dataLog("[%4d] tear_off_arguments %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); + dataLogF("[%4d] tear_off_arguments %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); dumpBytecodeCommentAndNewLine(location); break; } case op_ret: { int r0 = (++it)->u.operand; - dataLog("[%4d] ret\t\t %s", location, registerName(exec, r0).data()); + dataLogF("[%4d] ret\t\t %s", location, registerName(exec, r0).data()); dumpBytecodeCommentAndNewLine(location); break; } case op_call_put_result: { int r0 = (++it)->u.operand; - dataLog("[%4d] call_put_result\t\t %s", location, registerName(exec, r0).data()); + dataLogF("[%4d] call_put_result\t\t %s", location, registerName(exec, r0).data()); dumpBytecodeCommentAndNewLine(location); it++; break; @@ -1318,7 +1333,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& case op_ret_object_or_this: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - dataLog("[%4d] constructor_ret\t\t %s %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); + dataLogF("[%4d] constructor_ret\t\t %s %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); dumpBytecodeCommentAndNewLine(location); break; } @@ -1330,14 +1345,14 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int count = (++it)->u.operand; - dataLog("[%4d] strcat\t\t %s, %s, %d", location, registerName(exec, r0).data(), registerName(exec, r1).data(), count); + dataLogF("[%4d] strcat\t\t %s, %s, %d", location, registerName(exec, r0).data(), registerName(exec, r1).data(), count); dumpBytecodeCommentAndNewLine(location); break; } case op_to_primitive: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - dataLog("[%4d] to_primitive\t %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); + dataLogF("[%4d] to_primitive\t %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); dumpBytecodeCommentAndNewLine(location); break; } @@ -1347,7 +1362,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r2 = it[3].u.operand; int r3 = it[4].u.operand; int offset = it[5].u.operand; - dataLog("[%4d] get_pnames\t %s, %s, %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), offset, location + offset); + dataLogF("[%4d] get_pnames\t %s, %s, %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), offset, location + offset); dumpBytecodeCommentAndNewLine(location); it += OPCODE_LENGTH(op_get_pnames) - 1; break; @@ -1359,19 +1374,19 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int size = it[4].u.operand; int iter = it[5].u.operand; int offset = it[6].u.operand; - dataLog("[%4d] next_pname\t %s, %s, %s, %s, %s, %d(->%d)", location, registerName(exec, dest).data(), registerName(exec, base).data(), registerName(exec, i).data(), registerName(exec, size).data(), registerName(exec, iter).data(), offset, location + offset); + dataLogF("[%4d] next_pname\t %s, %s, %s, %s, %s, %d(->%d)", location, registerName(exec, dest).data(), registerName(exec, base).data(), registerName(exec, i).data(), registerName(exec, size).data(), registerName(exec, iter).data(), offset, location + offset); dumpBytecodeCommentAndNewLine(location); it += OPCODE_LENGTH(op_next_pname) - 1; break; } case op_push_with_scope: { int r0 = (++it)->u.operand; - dataLog("[%4d] push_with_scope\t %s", location, registerName(exec, r0).data()); + dataLogF("[%4d] push_with_scope\t %s", location, registerName(exec, r0).data()); dumpBytecodeCommentAndNewLine(location); break; } case op_pop_scope: { - dataLog("[%4d] pop_scope", location); + dataLogF("[%4d] pop_scope", location); dumpBytecodeCommentAndNewLine(location); break; } @@ -1379,33 +1394,33 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int id0 = (++it)->u.operand; int r1 = (++it)->u.operand; unsigned attributes = (++it)->u.operand; - dataLog("[%4d] push_name_scope \t%s, %s, %u", location, idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data(), attributes); + dataLogF("[%4d] push_name_scope \t%s, %s, %u", location, idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data(), attributes); dumpBytecodeCommentAndNewLine(location); break; } case op_jmp_scopes: { int scopeDelta = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jmp_scopes\t^%d, %d(->%d)", location, scopeDelta, offset, location + offset); + dataLogF("[%4d] jmp_scopes\t^%d, %d(->%d)", location, scopeDelta, offset, location + offset); dumpBytecodeCommentAndNewLine(location); break; } case op_catch: { int r0 = (++it)->u.operand; - dataLog("[%4d] catch\t\t %s", location, registerName(exec, r0).data()); + dataLogF("[%4d] catch\t\t %s", location, registerName(exec, r0).data()); dumpBytecodeCommentAndNewLine(location); break; } case op_throw: { int r0 = (++it)->u.operand; - dataLog("[%4d] throw\t\t %s", location, registerName(exec, r0).data()); + dataLogF("[%4d] throw\t\t %s", location, registerName(exec, r0).data()); dumpBytecodeCommentAndNewLine(location); break; } case op_throw_static_error: { int k0 = (++it)->u.operand; int k1 = (++it)->u.operand; - dataLog("[%4d] throw_static_error\t %s, %s", location, constantName(exec, k0, getConstant(k0)).data(), k1 ? "true" : "false"); + dataLogF("[%4d] throw_static_error\t %s, %s", location, constantName(exec, k0, getConstant(k0)).data(), k1 ? "true" : "false"); dumpBytecodeCommentAndNewLine(location); break; } @@ -1414,25 +1429,25 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int firstLine = (++it)->u.operand; int lastLine = (++it)->u.operand; int column = (++it)->u.operand; - dataLog("[%4d] debug\t\t %s, %d, %d, %d", location, debugHookName(debugHookID), firstLine, lastLine, column); + dataLogF("[%4d] debug\t\t %s, %d, %d, %d", location, debugHookName(debugHookID), firstLine, lastLine, column); dumpBytecodeCommentAndNewLine(location); break; } case op_profile_will_call: { int function = (++it)->u.operand; - dataLog("[%4d] profile_will_call %s", location, registerName(exec, function).data()); + dataLogF("[%4d] profile_will_call %s", location, registerName(exec, function).data()); dumpBytecodeCommentAndNewLine(location); break; } case op_profile_did_call: { int function = (++it)->u.operand; - dataLog("[%4d] profile_did_call\t %s", location, registerName(exec, function).data()); + dataLogF("[%4d] profile_did_call\t %s", location, registerName(exec, function).data()); dumpBytecodeCommentAndNewLine(location); break; } case op_end: { int r0 = (++it)->u.operand; - dataLog("[%4d] end\t\t %s", location, registerName(exec, r0).data()); + dataLogF("[%4d] end\t\t %s", location, registerName(exec, r0).data()); dumpBytecodeCommentAndNewLine(location); break; } @@ -1443,6 +1458,13 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& } } +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 @@ -1541,29 +1563,29 @@ void CodeBlock::dumpStatistics() totalSize += symbolTableTotalSize; totalSize += (liveCodeBlockSet.size() * sizeof(CodeBlock)); - dataLog("Number of live CodeBlocks: %d\n", liveCodeBlockSet.size()); - dataLog("Size of a single CodeBlock [sizeof(CodeBlock)]: %zu\n", sizeof(CodeBlock)); - dataLog("Size of all CodeBlocks: %zu\n", totalSize); - dataLog("Average size of a CodeBlock: %zu\n", totalSize / liveCodeBlockSet.size()); + dataLogF("Number of live CodeBlocks: %d\n", liveCodeBlockSet.size()); + dataLogF("Size of a single CodeBlock [sizeof(CodeBlock)]: %zu\n", sizeof(CodeBlock)); + dataLogF("Size of all CodeBlocks: %zu\n", totalSize); + dataLogF("Average size of a CodeBlock: %zu\n", totalSize / liveCodeBlockSet.size()); - dataLog("Number of FunctionCode CodeBlocks: %zu (%.3f%%)\n", isFunctionCode, static_cast<double>(isFunctionCode) * 100.0 / liveCodeBlockSet.size()); - dataLog("Number of GlobalCode CodeBlocks: %zu (%.3f%%)\n", isGlobalCode, static_cast<double>(isGlobalCode) * 100.0 / liveCodeBlockSet.size()); - dataLog("Number of EvalCode CodeBlocks: %zu (%.3f%%)\n", isEvalCode, static_cast<double>(isEvalCode) * 100.0 / liveCodeBlockSet.size()); + dataLogF("Number of FunctionCode CodeBlocks: %zu (%.3f%%)\n", isFunctionCode, static_cast<double>(isFunctionCode) * 100.0 / liveCodeBlockSet.size()); + dataLogF("Number of GlobalCode CodeBlocks: %zu (%.3f%%)\n", isGlobalCode, static_cast<double>(isGlobalCode) * 100.0 / liveCodeBlockSet.size()); + dataLogF("Number of EvalCode CodeBlocks: %zu (%.3f%%)\n", isEvalCode, static_cast<double>(isEvalCode) * 100.0 / liveCodeBlockSet.size()); - dataLog("Number of CodeBlocks with rare data: %zu (%.3f%%)\n", hasRareData, static_cast<double>(hasRareData) * 100.0 / liveCodeBlockSet.size()); + dataLogF("Number of CodeBlocks with rare data: %zu (%.3f%%)\n", hasRareData, static_cast<double>(hasRareData) * 100.0 / liveCodeBlockSet.size()); - #define PRINT_STATS(name) dataLog("Number of CodeBlocks with " #name ": %zu\n", name##IsNotEmpty); dataLog("Size of all " #name ": %zu\n", name##TotalSize); + #define PRINT_STATS(name) dataLogF("Number of CodeBlocks with " #name ": %zu\n", name##IsNotEmpty); dataLogF("Size of all " #name ": %zu\n", name##TotalSize); FOR_EACH_MEMBER_VECTOR(PRINT_STATS) FOR_EACH_MEMBER_VECTOR_RARE_DATA(PRINT_STATS) #undef PRINT_STATS - dataLog("Number of CodeBlocks with evalCodeCache: %zu\n", evalCodeCacheIsNotEmpty); - dataLog("Number of CodeBlocks with symbolTable: %zu\n", symbolTableIsNotEmpty); + dataLogF("Number of CodeBlocks with evalCodeCache: %zu\n", evalCodeCacheIsNotEmpty); + dataLogF("Number of CodeBlocks with symbolTable: %zu\n", symbolTableIsNotEmpty); - dataLog("Size of all symbolTables: %zu\n", symbolTableTotalSize); + dataLogF("Size of all symbolTables: %zu\n", symbolTableTotalSize); #else - dataLog("Dumping CodeBlock statistics is not enabled.\n"); + dataLogF("Dumping CodeBlock statistics is not enabled.\n"); #endif } @@ -1746,6 +1768,8 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin #if ENABLE(DFG_JIT) if (size_t size = unlinkedCodeBlock->numberOfArrayProfiles()) m_arrayProfiles.grow(size); + if (size_t size = unlinkedCodeBlock->numberOfArrayAllocationProfiles()) + m_arrayAllocationProfiles.grow(size); if (size_t size = unlinkedCodeBlock->numberOfValueProfiles()) m_valueProfiles.grow(size); #endif @@ -1786,7 +1810,8 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin case op_resolve_with_base: case op_resolve_with_this: case op_get_by_id: - case op_call_put_result: { + case op_call_put_result: + case op_get_callee: { ValueProfile* profile = &m_valueProfiles[pc[i + opLength - 1].u.operand]; ASSERT(profile->m_bytecodeOffset == -1); profile->m_bytecodeOffset = i; @@ -1800,22 +1825,32 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin break; } + case op_new_array: + case op_new_array_buffer: + case op_new_array_with_size: { + int arrayAllocationProfileIndex = pc[i + opLength - 1].u.operand; + instructions[i + opLength - 1] = &m_arrayAllocationProfiles[arrayAllocationProfileIndex]; + break; + } +#endif + case op_call: case op_call_eval: { +#if ENABLE(DFG_JIT) int arrayProfileIndex = pc[i + opLength - 1].u.operand; m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i); instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex]; - // fallthrough -#if !ENABLE(LLINT) - break; -#endif - } #endif #if ENABLE(LLINT) - case op_construct: instructions[i + 4] = &m_llintCallLinkInfos[pc[i + 4].u.operand]; +#endif break; + } + case op_construct: +#if ENABLE(LLINT) + instructions[i + 4] = &m_llintCallLinkInfos[pc[i + 4].u.operand]; #endif + break; case op_get_by_id_out_of_line: case op_get_by_id_self: case op_get_by_id_proto: @@ -1857,7 +1892,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin m_instructions = WTF::RefCountedArray<Instruction>(instructions); if (BytecodeGenerator::dumpsGeneratedCode()) - dump(m_globalObject->globalExec()); + dump(); m_globalData->finishedCompiling(this); } @@ -2118,7 +2153,7 @@ void CodeBlock::finalizeUnconditionally() if (!curInstruction[4].u.structure || Heap::isMarked(curInstruction[4].u.structure.get())) break; if (verboseUnlinking) - dataLog("Clearing LLInt property access with structure %p.\n", curInstruction[4].u.structure.get()); + dataLogF("Clearing LLInt property access with structure %p.\n", curInstruction[4].u.structure.get()); curInstruction[4].u.structure.clear(); curInstruction[5].u.operand = 0; break; @@ -2131,7 +2166,7 @@ void CodeBlock::finalizeUnconditionally() && Heap::isMarked(curInstruction[7].u.structureChain.get())) break; if (verboseUnlinking) { - dataLog("Clearing LLInt put transition with structures %p -> %p, chain %p.\n", + dataLogF("Clearing LLInt put transition with structures %p -> %p, chain %p.\n", curInstruction[4].u.structure.get(), curInstruction[6].u.structure.get(), curInstruction[7].u.structureChain.get()); @@ -2151,7 +2186,7 @@ void CodeBlock::finalizeUnconditionally() for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) { if (m_llintCallLinkInfos[i].isLinked() && !Heap::isMarked(m_llintCallLinkInfos[i].callee.get())) { if (verboseUnlinking) - dataLog("Clearing LLInt call from %p.\n", this); + dataLogF("Clearing LLInt call from %p.\n", this); m_llintCallLinkInfos[i].unlink(); } if (!!m_llintCallLinkInfos[i].lastSeenCallee && !Heap::isMarked(m_llintCallLinkInfos[i].lastSeenCallee.get())) @@ -2164,12 +2199,33 @@ void CodeBlock::finalizeUnconditionally() // Check if we're not live. If we are, then jettison. if (!(shouldImmediatelyAssumeLivenessDuringScan() || m_dfgData->livenessHasBeenProved)) { if (verboseUnlinking) - dataLog("Code block %p has dead weak references, jettisoning during GC.\n", this); + dataLogF("Code block %p (executable %p) has dead weak references, jettisoning during GC.\n", this, ownerExecutable()); // Make sure that the baseline JIT knows that it should re-warm-up before // optimizing. alternative()->optimizeAfterWarmUp(); + if (DFG::shouldShowDisassembly()) { + dataLogF("DFG CodeBlock %p will be jettisoned because of the following dead references:\n", this); + for (unsigned i = 0; i < m_dfgData->transitions.size(); ++i) { + WeakReferenceTransition& transition = m_dfgData->transitions[i]; + JSCell* origin = transition.m_codeOrigin.get(); + JSCell* from = transition.m_from.get(); + JSCell* to = transition.m_to.get(); + if ((!origin || Heap::isMarked(origin)) && Heap::isMarked(from)) + continue; + dataLogF(" Transition under %s, ", JSValue(origin).description()); + dataLogF("%s -> ", JSValue(from).description()); + dataLogF("%s.\n", JSValue(to).description()); + } + for (unsigned i = 0; i < m_dfgData->weakReferences.size(); ++i) { + JSCell* weak = m_dfgData->weakReferences[i].get(); + if (Heap::isMarked(weak)) + continue; + dataLogF(" Weak reference %s.\n", JSValue(weak).description()); + } + } + jettison(); return; } @@ -2178,7 +2234,7 @@ void CodeBlock::finalizeUnconditionally() for (size_t size = m_putToBaseOperations.size(), i = 0; i < size; ++i) { if (m_putToBaseOperations[i].m_structure && !Heap::isMarked(m_putToBaseOperations[i].m_structure.get())) { if (verboseUnlinking) - dataLog("Clearing putToBase info in %p.\n", this); + dataLogF("Clearing putToBase info in %p.\n", this); m_putToBaseOperations[i].m_structure.clear(); } } @@ -2192,7 +2248,7 @@ void CodeBlock::finalizeUnconditionally() m_resolveOperations[i].last().m_structure.clear(); if (m_resolveOperations[i].last().m_structure && !Heap::isMarked(m_resolveOperations[i].last().m_structure.get())) { if (verboseUnlinking) - dataLog("Clearing resolve info in %p.\n", this); + dataLogF("Clearing resolve info in %p.\n", this); m_resolveOperations[i].last().m_structure.clear(); } } @@ -2202,10 +2258,19 @@ void CodeBlock::finalizeUnconditionally() if (!!getJITCode()) { RepatchBuffer repatchBuffer(this); for (unsigned i = 0; i < numberOfCallLinkInfos(); ++i) { - if (callLinkInfo(i).isLinked() && !Heap::isMarked(callLinkInfo(i).callee.get())) { - if (verboseUnlinking) - dataLog("Clearing call from %p to %p.\n", this, callLinkInfo(i).callee.get()); - callLinkInfo(i).unlink(*m_globalData, repatchBuffer); + if (callLinkInfo(i).isLinked()) { + if (ClosureCallStubRoutine* stub = callLinkInfo(i).stub.get()) { + if (!Heap::isMarked(stub->structure()) + || !Heap::isMarked(stub->executable())) { + if (verboseUnlinking) + dataLogF("Clearing closure call from %p to %p, stub routine %p.\n", this, stub->executable(), stub); + callLinkInfo(i).unlink(*m_globalData, repatchBuffer); + } + } else if (!Heap::isMarked(callLinkInfo(i).callee.get())) { + if (verboseUnlinking) + dataLogF("Clearing call from %p to %p.\n", this, callLinkInfo(i).callee.get()); + callLinkInfo(i).unlink(*m_globalData, repatchBuffer); + } } if (!!callLinkInfo(i).lastSeenCallee && !Heap::isMarked(callLinkInfo(i).lastSeenCallee.get())) @@ -2238,7 +2303,7 @@ void CodeBlock::resetStubInternal(RepatchBuffer& repatchBuffer, StructureStubInf AccessType accessType = static_cast<AccessType>(stubInfo.accessType); if (verboseUnlinking) - dataLog("Clearing structure cache (kind %d) in %p.\n", stubInfo.accessType, this); + dataLogF("Clearing structure cache (kind %d) in %p.\n", stubInfo.accessType, this); if (isGetByIdAccess(accessType)) { if (getJITCode().jitType() == JITCode::DFGJIT) @@ -2560,6 +2625,35 @@ Instruction* CodeBlock::adjustPCIfAtCallSite(Instruction* potentialReturnPC) } #endif // ENABLE(LLINT) +#if ENABLE(JIT) +ClosureCallStubRoutine* CodeBlock::findClosureCallForReturnPC(ReturnAddressPtr returnAddress) +{ + for (unsigned i = m_callLinkInfos.size(); i--;) { + CallLinkInfo& info = m_callLinkInfos[i]; + if (!info.stub) + continue; + if (!info.stub->code().executableMemory()->contains(returnAddress.value())) + continue; + + return info.stub.get(); + } + + // The stub routine may have been jettisoned. This is rare, but we have to handle it. + const JITStubRoutineSet& set = m_globalData->heap.jitStubRoutines(); + for (unsigned i = set.size(); i--;) { + GCAwareJITStubRoutine* genericStub = set.at(i); + if (!genericStub->isClosureCall()) + continue; + ClosureCallStubRoutine* stub = static_cast<ClosureCallStubRoutine*>(genericStub); + if (!stub->code().executableMemory()->contains(returnAddress.value())) + continue; + return stub; + } + + return 0; +} +#endif + unsigned CodeBlock::bytecodeOffset(ExecState* exec, ReturnAddressPtr returnAddress) { UNUSED_PARAM(exec); @@ -2597,7 +2691,16 @@ unsigned CodeBlock::bytecodeOffset(ExecState* exec, ReturnAddressPtr returnAddre Vector<CallReturnOffsetToBytecodeOffset>& callIndices = m_rareData->m_callReturnIndexVector; if (!callIndices.size()) return 1; - return binarySearch<CallReturnOffsetToBytecodeOffset, unsigned, getCallReturnOffset>(callIndices.begin(), callIndices.size(), getJITCode().offsetOf(returnAddress.value()))->bytecodeOffset; + + if (getJITCode().getExecutableMemory()->contains(returnAddress.value())) { + unsigned callReturnOffset = getJITCode().offsetOf(returnAddress.value()); + CallReturnOffsetToBytecodeOffset* result = + binarySearch<CallReturnOffsetToBytecodeOffset, unsigned, getCallReturnOffset>(callIndices.begin(), callIndices.size(), callReturnOffset); + ASSERT(result->callReturnOffset == callReturnOffset); + return result->bytecodeOffset; + } + + return findClosureCallForReturnPC(returnAddress)->codeOrigin().bytecodeIndex; #endif // ENABLE(JIT) #if !ENABLE(LLINT) && !ENABLE(JIT) @@ -2605,6 +2708,26 @@ unsigned CodeBlock::bytecodeOffset(ExecState* exec, ReturnAddressPtr returnAddre #endif } +#if ENABLE(DFG_JIT) +bool CodeBlock::codeOriginForReturn(ReturnAddressPtr returnAddress, CodeOrigin& codeOrigin) +{ + if (!hasCodeOrigins()) + return false; + + if (!getJITCode().getExecutableMemory()->contains(returnAddress.value())) { + codeOrigin = findClosureCallForReturnPC(returnAddress)->codeOrigin(); + return true; + } + + unsigned offset = getJITCode().offsetOf(returnAddress.value()); + CodeOriginAtCallReturnOffset* entry = binarySearch<CodeOriginAtCallReturnOffset, unsigned, getCallReturnOffsetForCodeOrigin>(codeOrigins().begin(), codeOrigins().size(), offset, WTF::KeyMustNotBePresentInArray); + if (entry->callReturnOffset != offset) + return false; + codeOrigin = entry->codeOrigin; + return true; +} +#endif // ENABLE(DFG_JIT) + void CodeBlock::clearEvalCache() { if (!!m_alternative) @@ -2645,6 +2768,8 @@ void CodeBlock::reoptimize() ASSERT(replacement() != this); ASSERT(replacement()->alternative() == this); replacement()->tallyFrequentExitSites(); + if (DFG::shouldShowDisassembly()) + dataLogF("DFG CodeBlock %p will be jettisoned due to reoptimization of %p.\n", replacement(), this); replacement()->jettison(); countReoptimization(); optimizeAfterWarmUp(); @@ -2710,6 +2835,8 @@ void ProgramCodeBlock::jettison() { ASSERT(JITCode::isOptimizingJIT(getJITType())); ASSERT(this == replacement()); + if (DFG::shouldShowDisassembly()) + dataLogF("Jettisoning DFG CodeBlock %p.\n", this); static_cast<ProgramExecutable*>(ownerExecutable())->jettisonOptimizedCode(*globalData()); } @@ -2717,6 +2844,8 @@ void EvalCodeBlock::jettison() { ASSERT(JITCode::isOptimizingJIT(getJITType())); ASSERT(this == replacement()); + if (DFG::shouldShowDisassembly()) + dataLogF("Jettisoning DFG CodeBlock %p.\n", this); static_cast<EvalExecutable*>(ownerExecutable())->jettisonOptimizedCode(*globalData()); } @@ -2724,6 +2853,8 @@ void FunctionCodeBlock::jettison() { ASSERT(JITCode::isOptimizingJIT(getJITType())); ASSERT(this == replacement()); + if (DFG::shouldShowDisassembly()) + dataLogF("Jettisoning DFG CodeBlock %p.\n", this); static_cast<FunctionExecutable*>(ownerExecutable())->jettisonOptimizedCodeFor(*globalData(), m_isConstructor ? CodeForConstruct : CodeForCall); } @@ -2790,24 +2921,34 @@ void CodeBlock::updateAllPredictionsAndCountLiveness( #if ENABLE(DFG_JIT) m_lazyOperandValueProfiles.computeUpdatedPredictions(operation); #endif - - // Don't count the array profiles towards statistics, since each array profile - // site also has a value profile site - so we already know whether or not it's - // live. +} + +void CodeBlock::updateAllValueProfilePredictions(OperationInProgress operation) +{ + unsigned ignoredValue1, ignoredValue2; + updateAllPredictionsAndCountLiveness(operation, ignoredValue1, ignoredValue2); +} + +void CodeBlock::updateAllArrayPredictions(OperationInProgress operation) +{ for (unsigned i = m_arrayProfiles.size(); i--;) m_arrayProfiles[i].computeUpdatedPrediction(this, operation); + + // Don't count these either, for similar reasons. + for (unsigned i = m_arrayAllocationProfiles.size(); i--;) + m_arrayAllocationProfiles[i].updateIndexingType(); } void CodeBlock::updateAllPredictions(OperationInProgress operation) { - unsigned ignoredValue1, ignoredValue2; - updateAllPredictionsAndCountLiveness(operation, ignoredValue1, ignoredValue2); + updateAllValueProfilePredictions(operation); + updateAllArrayPredictions(operation); } bool CodeBlock::shouldOptimizeNow() { #if ENABLE(JIT_VERBOSE_OSR) - dataLog("Considering optimizing %p...\n", this); + dataLogF("Considering optimizing %p...\n", this); #endif #if ENABLE(VERBOSE_VALUE_PROFILE) @@ -2817,12 +2958,14 @@ bool CodeBlock::shouldOptimizeNow() if (m_optimizationDelayCounter >= Options::maximumOptimizationDelay()) return true; + updateAllArrayPredictions(); + unsigned numberOfLiveNonArgumentValueProfiles; unsigned numberOfSamplesInProfiles; updateAllPredictionsAndCountLiveness(NoOperation, numberOfLiveNonArgumentValueProfiles, numberOfSamplesInProfiles); #if ENABLE(JIT_VERBOSE_OSR) - dataLog("Profile hotness: %lf, %lf\n", (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles(), (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles()); + dataLogF("Profile hotness: %lf (%u / %u), %lf (%u / %u)\n", (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles(), numberOfLiveNonArgumentValueProfiles, numberOfValueProfiles(), (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles(), numberOfSamplesInProfiles, ValueProfile::numberOfBuckets * numberOfValueProfiles()); #endif if ((!numberOfValueProfiles() || (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles() >= Options::desiredProfileLivenessRate()) @@ -2853,7 +2996,7 @@ void CodeBlock::tallyFrequentExitSites() continue; #if DFG_ENABLE(DEBUG_VERBOSE) - dataLog("OSR exit #%u (bc#%u, @%u, %s) for code block %p occurred frequently; counting as frequent exit site.\n", i, exit.m_codeOrigin.bytecodeIndex, exit.m_nodeIndex, DFG::exitKindToString(exit.m_kind), this); + dataLogF("OSR exit #%u (bc#%u, @%u, %s) for code block %p occurred frequently; counting as frequent exit site.\n", i, exit.m_codeOrigin.bytecodeIndex, exit.m_nodeIndex, DFG::exitKindToString(exit.m_kind), this); #endif } } @@ -2862,30 +3005,30 @@ void CodeBlock::tallyFrequentExitSites() #if ENABLE(VERBOSE_VALUE_PROFILE) void CodeBlock::dumpValueProfiles() { - dataLog("ValueProfile for %p:\n", this); + dataLogF("ValueProfile for %p:\n", this); for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) { ValueProfile* profile = getFromAllValueProfiles(i); if (profile->m_bytecodeOffset < 0) { ASSERT(profile->m_bytecodeOffset == -1); - dataLog(" arg = %u: ", i); + dataLogF(" arg = %u: ", i); } else - dataLog(" bc = %d: ", profile->m_bytecodeOffset); + dataLogF(" bc = %d: ", profile->m_bytecodeOffset); if (!profile->numberOfSamples() && profile->m_prediction == SpecNone) { - dataLog("<empty>\n"); + dataLogF("<empty>\n"); continue; } profile->dump(WTF::dataFile()); - dataLog("\n"); + dataLogF("\n"); } - dataLog("RareCaseProfile for %p:\n", this); + dataLogF("RareCaseProfile for %p:\n", this); for (unsigned i = 0; i < numberOfRareCaseProfiles(); ++i) { RareCaseProfile* profile = rareCaseProfile(i); - dataLog(" bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter); + dataLogF(" bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter); } - dataLog("SpecialFastCaseProfile for %p:\n", this); + dataLogF("SpecialFastCaseProfile for %p:\n", this); for (unsigned i = 0; i < numberOfSpecialFastCaseProfiles(); ++i) { RareCaseProfile* profile = specialFastCaseProfile(i); - dataLog(" bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter); + dataLogF(" bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter); } } #endif // ENABLE(VERBOSE_VALUE_PROFILE) |