diff options
Diffstat (limited to 'Source/JavaScriptCore/bytecode')
-rw-r--r-- | Source/JavaScriptCore/bytecode/CallLinkInfo.h | 6 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/CodeBlock.cpp | 84 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/CodeBlock.h | 19 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/CodeBlockHash.cpp | 90 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/CodeBlockHash.h | 78 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/CodeBlockWithJITType.h | 56 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/CodeOrigin.cpp | 62 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/CodeOrigin.h | 32 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/CodeType.cpp | 52 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/CodeType.h | 22 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/ExecutionCounter.cpp | 6 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/ExecutionCounter.h | 3 |
12 files changed, 429 insertions, 81 deletions
diff --git a/Source/JavaScriptCore/bytecode/CallLinkInfo.h b/Source/JavaScriptCore/bytecode/CallLinkInfo.h index 89403b0ca..57608435c 100644 --- a/Source/JavaScriptCore/bytecode/CallLinkInfo.h +++ b/Source/JavaScriptCore/bytecode/CallLinkInfo.h @@ -28,6 +28,7 @@ #include "ClosureCallStubRoutine.h" #include "CodeLocation.h" +#include "CodeSpecializationKind.h" #include "JITWriteBarrier.h" #include "JSFunction.h" #include "Opcode.h" @@ -65,6 +66,11 @@ struct CallLinkInfo : public BasicRawSentinelNode<CallLinkInfo> { if (isOnList()) remove(); } + + CodeSpecializationKind specializationKind() const + { + return specializationFromIsConstruct(callType == Construct); + } CodeLocationNearCall callReturnLocation; CodeLocationDataLabelPtr hotPathBegin; diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp index 6e1edaa0e..00209f236 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp @@ -62,6 +62,24 @@ namespace JSC { using namespace DFG; #endif +CodeBlockHash CodeBlock::hash() const +{ + return CodeBlockHash(ownerExecutable()->source(), specializationKind()); +} + +void CodeBlock::dumpAssumingJITType(PrintStream& out, JITCode::JITType jitType) const +{ + out.print("#", hash(), ":[", RawPointer(this), ", ", jitType, codeType()); + if (codeType() == FunctionCode) + out.print(specializationKind()); + out.print("]"); +} + +void CodeBlock::dump(PrintStream& out) const +{ + dumpAssumingJITType(out, getJITType()); +} + static String escapeQuotes(const String& str) { String result = str; @@ -480,7 +498,7 @@ 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() +void CodeBlock::dumpBytecode() { // 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. @@ -491,12 +509,12 @@ void CodeBlock::dump() for (size_t i = 0; i < instructions().size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(instructions()[i].u.opcode)]) ++instructionCount; + dataLog(*this); dataLogF( - "%lu m_instructions; %lu bytes at %p (%s); %d parameter(s); %d callee register(s); %d variable(s)", + ": %lu m_instructions; %lu bytes; %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); + m_numParameters, m_numCalleeRegisters, m_numVars); if (symbolTable() && symbolTable()->captureCount()) dataLogF("; %d captured var(s)", symbolTable()->captureCount()); if (usesArguments()) { @@ -512,7 +530,7 @@ void CodeBlock::dump() const Instruction* begin = instructions().begin(); const Instruction* end = instructions().end(); for (const Instruction* it = begin; it != end; ++it) - dump(exec, begin, it); + dumpBytecode(exec, begin, it); if (!m_identifiers.isEmpty()) { dataLogF("\nIdentifiers:\n"); @@ -607,7 +625,7 @@ void CodeBlock::dump() dataLogF("\n"); } -void CodeBlock::dump(ExecState* exec, const Instruction* begin, const Instruction*& it) +void CodeBlock::dumpBytecode(ExecState* exec, const Instruction* begin, const Instruction*& it) { int location = it - begin; switch (exec->interpreter()->getOpcodeID(it->u.opcode)) { @@ -1458,11 +1476,11 @@ void CodeBlock::dump(ExecState* exec, const Instruction* begin, const Instructio } } -void CodeBlock::dump(unsigned bytecodeOffset) +void CodeBlock::dumpBytecode(unsigned bytecodeOffset) { ExecState* exec = m_globalObject->globalExec(); const Instruction* it = instructions().begin() + bytecodeOffset; - dump(exec, instructions().begin(), it); + dumpBytecode(exec, instructions().begin(), it); } #if DUMP_CODE_BLOCK_STATISTICS @@ -1892,7 +1910,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin m_instructions = WTF::RefCountedArray<Instruction>(instructions); if (Options::dumpGeneratedBytecodes()) - dump(); + dumpBytecode(); m_globalData->finishedCompiling(this); } @@ -2186,7 +2204,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) - dataLogF("Clearing LLInt call from %p.\n", this); + dataLog("Clearing LLInt call from ", *this, "\n"); m_llintCallLinkInfos[i].unlink(); } if (!!m_llintCallLinkInfos[i].lastSeenCallee && !Heap::isMarked(m_llintCallLinkInfos[i].lastSeenCallee.get())) @@ -2199,14 +2217,14 @@ void CodeBlock::finalizeUnconditionally() // Check if we're not live. If we are, then jettison. if (!(shouldImmediatelyAssumeLivenessDuringScan() || m_dfgData->livenessHasBeenProved)) { if (verboseUnlinking) - dataLogF("Code block %p (executable %p) has dead weak references, jettisoning during GC.\n", this, ownerExecutable()); + dataLog(*this, " has dead weak references, jettisoning during GC.\n"); // 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); + dataLog(*this, "will be jettisoned because of the following dead references:\n"); for (unsigned i = 0; i < m_dfgData->transitions.size(); ++i) { WeakReferenceTransition& transition = m_dfgData->transitions[i]; JSCell* origin = transition.m_codeOrigin.get(); @@ -2234,7 +2252,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) - dataLogF("Clearing putToBase info in %p.\n", this); + dataLog("Clearing putToBase info in ", *this, "\n"); m_putToBaseOperations[i].m_structure.clear(); } } @@ -2248,7 +2266,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) - dataLogF("Clearing resolve info in %p.\n", this); + dataLog("Clearing resolve info in ", *this, "\n"); m_resolveOperations[i].last().m_structure.clear(); } } @@ -2262,13 +2280,23 @@ void CodeBlock::finalizeUnconditionally() 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); + if (verboseUnlinking) { + dataLog( + "Clearing closure call from ", *this, " to ", + stub->executable()->hashFor(callLinkInfo(i).specializationKind()), + ", stub routine ", RawPointer(stub), ".\n"); + } 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()); + if (verboseUnlinking) { + dataLog( + "Clearing call from ", *this, " to ", + RawPointer(callLinkInfo(i).callee.get()), " (", + callLinkInfo(i).callee.get()->executable()->hashFor( + callLinkInfo(i).specializationKind()), + ").\n"); + } callLinkInfo(i).unlink(*m_globalData, repatchBuffer); } } @@ -2303,7 +2331,7 @@ void CodeBlock::resetStubInternal(RepatchBuffer& repatchBuffer, StructureStubInf AccessType accessType = static_cast<AccessType>(stubInfo.accessType); if (verboseUnlinking) - dataLogF("Clearing structure cache (kind %d) in %p.\n", stubInfo.accessType, this); + dataLog("Clearing structure cache (kind ", static_cast<int>(stubInfo.accessType), ") in ", *this, ".\n"); if (isGetByIdAccess(accessType)) { if (getJITCode().jitType() == JITCode::DFGJIT) @@ -2769,7 +2797,7 @@ void CodeBlock::reoptimize() ASSERT(replacement()->alternative() == this); replacement()->tallyFrequentExitSites(); if (DFG::shouldShowDisassembly()) - dataLogF("DFG CodeBlock %p will be jettisoned due to reoptimization of %p.\n", replacement(), this); + dataLog(*replacement(), " will be jettisoned due to reoptimization of ", *this, ".\n"); replacement()->jettison(); countReoptimization(); optimizeAfterWarmUp(); @@ -2836,7 +2864,7 @@ void ProgramCodeBlock::jettison() ASSERT(JITCode::isOptimizingJIT(getJITType())); ASSERT(this == replacement()); if (DFG::shouldShowDisassembly()) - dataLogF("Jettisoning DFG CodeBlock %p.\n", this); + dataLog("Jettisoning ", *this, ".\n"); static_cast<ProgramExecutable*>(ownerExecutable())->jettisonOptimizedCode(*globalData()); } @@ -2845,7 +2873,7 @@ void EvalCodeBlock::jettison() ASSERT(JITCode::isOptimizingJIT(getJITType())); ASSERT(this == replacement()); if (DFG::shouldShowDisassembly()) - dataLogF("Jettisoning DFG CodeBlock %p.\n", this); + dataLog("Jettisoning ", *this, ".\n"); static_cast<EvalExecutable*>(ownerExecutable())->jettisonOptimizedCode(*globalData()); } @@ -2854,7 +2882,7 @@ void FunctionCodeBlock::jettison() ASSERT(JITCode::isOptimizingJIT(getJITType())); ASSERT(this == replacement()); if (DFG::shouldShowDisassembly()) - dataLogF("Jettisoning DFG CodeBlock %p.\n", this); + dataLog("Jettisoning ", *this, ".\n"); static_cast<FunctionExecutable*>(ownerExecutable())->jettisonOptimizedCodeFor(*globalData(), m_isConstructor ? CodeForConstruct : CodeForCall); } @@ -2948,7 +2976,7 @@ void CodeBlock::updateAllPredictions(OperationInProgress operation) bool CodeBlock::shouldOptimizeNow() { #if ENABLE(JIT_VERBOSE_OSR) - dataLogF("Considering optimizing %p...\n", this); + dataLog("Considering optimizing ", *this, "...\n"); #endif #if ENABLE(VERBOSE_VALUE_PROFILE) @@ -2996,7 +3024,7 @@ void CodeBlock::tallyFrequentExitSites() continue; #if DFG_ENABLE(DEBUG_VERBOSE) - 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); + dataLog("OSR exit #", i, " (bc#", exit.m_codeOrigin.bytecodeIndex, ", @", exit.m_nodeIndex, ", ", DFG::exitKindToString(exit.m_kind), ") for ", *this, " occurred frequently: counting as frequent exit site.\n"); #endif } } @@ -3005,7 +3033,7 @@ void CodeBlock::tallyFrequentExitSites() #if ENABLE(VERBOSE_VALUE_PROFILE) void CodeBlock::dumpValueProfiles() { - dataLogF("ValueProfile for %p:\n", this); + dataLog("ValueProfile for ", *this, ":\n"); for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) { ValueProfile* profile = getFromAllValueProfiles(i); if (profile->m_bytecodeOffset < 0) { @@ -3020,12 +3048,12 @@ void CodeBlock::dumpValueProfiles() profile->dump(WTF::dataFile()); dataLogF("\n"); } - dataLogF("RareCaseProfile for %p:\n", this); + dataLog("RareCaseProfile for ", *this, ":\n"); for (unsigned i = 0; i < numberOfRareCaseProfiles(); ++i) { RareCaseProfile* profile = rareCaseProfile(i); dataLogF(" bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter); } - dataLogF("SpecialFastCaseProfile for %p:\n", this); + dataLog("SpecialFastCaseProfile for ", *this, ":\n"); for (unsigned i = 0; i < numberOfSpecialFastCaseProfiles(); ++i) { RareCaseProfile* profile = specialFastCaseProfile(i); dataLogF(" bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter); diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h index 63a03630e..20f1e7452 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.h +++ b/Source/JavaScriptCore/bytecode/CodeBlock.h @@ -35,6 +35,7 @@ #include "BytecodeConventions.h" #include "CallLinkInfo.h" #include "CallReturnOffsetToBytecodeOffset.h" +#include "CodeBlockHash.h" #include "CodeOrigin.h" #include "CodeType.h" #include "Comment.h" @@ -128,6 +129,10 @@ namespace JSC { public: JS_EXPORT_PRIVATE virtual ~CodeBlock(); + CodeBlockHash hash() const; + void dumpAssumingJITType(PrintStream&, JITCode::JITType) const; + void dump(PrintStream&) const; + int numParameters() const { return m_numParameters; } void setNumParameters(int newValue); @@ -138,11 +143,9 @@ namespace JSC { PassOwnPtr<CodeBlock> releaseAlternative() { return m_alternative.release(); } void setAlternative(PassOwnPtr<CodeBlock> alternative) { m_alternative = alternative; } - CodeSpecializationKind specializationKind() + CodeSpecializationKind specializationKind() const { - if (m_isConstructor) - return CodeForConstruct; - return CodeForCall; + return specializationFromIsConstruct(m_isConstructor); } #if ENABLE(JIT) @@ -163,8 +166,8 @@ namespace JSC { static void dumpStatistics(); - void dump(); - void dump(unsigned bytecodeOffset); + void dumpBytecode(); + void dumpBytecode(unsigned bytecodeOffset); void printStructures(const Instruction*); void printStructure(const char* name, const Instruction*, int operand); @@ -472,7 +475,7 @@ namespace JSC { } JITCode& getJITCode() { return m_jitCode; } MacroAssemblerCodePtr getJITCodeWithArityCheck() { return m_jitCodeWithArityCheck; } - JITCode::JITType getJITType() { return m_jitCode.jitType(); } + JITCode::JITType getJITType() const { return m_jitCode.jitType(); } ExecutableMemoryHandle* executableMemory() { return getJITCode().getExecutableMemory(); } virtual JSObject* compileOptimized(ExecState*, JSScope*, unsigned bytecodeIndex) = 0; virtual void jettison() = 0; @@ -1212,7 +1215,7 @@ namespace JSC { m_constantRegisters[i].set(*m_globalData, ownerExecutable(), constants[i].get()); } - void dump(ExecState*, const Instruction* begin, const Instruction*&); + void dumpBytecode(ExecState*, const Instruction* begin, const Instruction*&); CString registerName(ExecState*, int r) const; void printUnaryOp(ExecState*, int location, const Instruction*&, const char* op); diff --git a/Source/JavaScriptCore/bytecode/CodeBlockHash.cpp b/Source/JavaScriptCore/bytecode/CodeBlockHash.cpp new file mode 100644 index 000000000..79fe9ccb5 --- /dev/null +++ b/Source/JavaScriptCore/bytecode/CodeBlockHash.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CodeBlockHash.h" + +#include "SourceCode.h" +#include <wtf/SHA1.h> + +namespace JSC { + +#define TABLE ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") + +CodeBlockHash::CodeBlockHash(const char* string) + : m_hash(0) +{ + if (strlen(string) != 6) + CRASH(); + + for (unsigned i = 0; i < 6; ++i) { + m_hash *= 62; + unsigned c = string[i]; + if (c >= 'A' && c <= 'Z') { + m_hash += c - 'A'; + continue; + } + if (c >= 'a' && c <= 'z') { + m_hash += c - 'a' + 26; + continue; + } + ASSERT(c >= '0' && c <= '9'); + m_hash += c - '0' + 26 * 2; + } +} + +CodeBlockHash::CodeBlockHash(const SourceCode& sourceCode, CodeSpecializationKind kind) + : m_hash(0) +{ + SHA1 sha1; + sha1.addBytes(sourceCode.toString().utf8()); + Vector<uint8_t, 20> digest; + sha1.computeHash(digest); + m_hash += digest[0] | (digest[1] << 8) | (digest[2] << 16) | (digest[3] << 24); + m_hash ^= static_cast<unsigned>(kind); +} + +void CodeBlockHash::dump(PrintStream& out) const +{ + ASSERT(strlen(TABLE) == 62); + + char buffer[7]; + unsigned accumulator = m_hash; + for (unsigned i = 6; i--;) { + buffer[i] = TABLE[accumulator % 62]; + accumulator /= 62; + } + buffer[6] = 0; + +#if !ASSERT_DISABLED + CodeBlockHash recompute(buffer); + ASSERT(recompute == *this); +#endif // !ASSERT_DISABLED + + out.print(buffer); +} + +} // namespace JSC + diff --git a/Source/JavaScriptCore/bytecode/CodeBlockHash.h b/Source/JavaScriptCore/bytecode/CodeBlockHash.h new file mode 100644 index 000000000..20de8ed48 --- /dev/null +++ b/Source/JavaScriptCore/bytecode/CodeBlockHash.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CodeBlockHash_h +#define CodeBlockHash_h + +#include "CodeSpecializationKind.h" +#include <wtf/PrintStream.h> + +// CodeBlock hashes are useful for informally identifying code blocks. They correspond +// to the low 32 bits of a SHA1 hash of the source code with two low bit flipped +// according to the role that the code block serves (call, construct). Additionally, the +// hashes are typically operated over using a string in which the hash is transformed +// into a 6-byte alphanumeric representation. This can be retrieved by using +// toString(const CodeBlockHash&). Finally, we support CodeBlockHashes for native +// functions, in which case the hash is replaced by the function address. + +namespace JSC { + +class SourceCode; + +class CodeBlockHash { +public: + CodeBlockHash() + : m_hash(0) + { + } + + explicit CodeBlockHash(unsigned hash) + : m_hash(hash) + { + } + + CodeBlockHash(const SourceCode&, CodeSpecializationKind); + + explicit CodeBlockHash(const char*); + + unsigned hash() const { return m_hash; } + + void dump(PrintStream&) const; + + // Comparison methods useful for bisection. + bool operator==(const CodeBlockHash& other) const { return hash() == other.hash(); } + bool operator!=(const CodeBlockHash& other) const { return hash() != other.hash(); } + bool operator<(const CodeBlockHash& other) const { return hash() < other.hash(); } + bool operator>(const CodeBlockHash& other) const { return hash() > other.hash(); } + bool operator<=(const CodeBlockHash& other) const { return hash() <= other.hash(); } + bool operator>=(const CodeBlockHash& other) const { return hash() >= other.hash(); } + +private: + unsigned m_hash; +}; + +} // namespace JSC + +#endif // CodeBlockHash_h diff --git a/Source/JavaScriptCore/bytecode/CodeBlockWithJITType.h b/Source/JavaScriptCore/bytecode/CodeBlockWithJITType.h new file mode 100644 index 000000000..d87085841 --- /dev/null +++ b/Source/JavaScriptCore/bytecode/CodeBlockWithJITType.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CodeBlockWithJITType_h +#define CodeBlockWithJITType_h + +#include "CodeBlock.h" + +namespace JSC { + +// We sometimes what to print the CodeBlock's ID before setting its JITCode. At that +// point the CodeBlock will claim a bogus JITType. This helper class lets us do that. + +class CodeBlockWithJITType { +public: + CodeBlockWithJITType(CodeBlock* codeBlock, JITCode::JITType jitType) + : m_codeBlock(codeBlock) + , m_jitType(jitType) + { + } + + void dump(PrintStream& out) const + { + m_codeBlock->dumpAssumingJITType(out, m_jitType); + } +private: + CodeBlock* m_codeBlock; + JITCode::JITType m_jitType; +}; + +} // namespace JSC + +#endif // CodeBlockWithJITType_h + diff --git a/Source/JavaScriptCore/bytecode/CodeOrigin.cpp b/Source/JavaScriptCore/bytecode/CodeOrigin.cpp new file mode 100644 index 000000000..92e2b0fc9 --- /dev/null +++ b/Source/JavaScriptCore/bytecode/CodeOrigin.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CodeOrigin.h" + +#include "Executable.h" + +namespace JSC { + +unsigned CodeOrigin::inlineDepthForCallFrame(InlineCallFrame* inlineCallFrame) +{ + unsigned result = 1; + for (InlineCallFrame* current = inlineCallFrame; current; current = current->caller.inlineCallFrame) + result++; + return result; +} + +unsigned CodeOrigin::inlineDepth() const +{ + return inlineDepthForCallFrame(inlineCallFrame); +} + +Vector<CodeOrigin> CodeOrigin::inlineStack() const +{ + Vector<CodeOrigin> result(inlineDepth()); + result.last() = *this; + unsigned index = result.size() - 2; + for (InlineCallFrame* current = inlineCallFrame; current; current = current->caller.inlineCallFrame) + result[index--] = current->caller; + return result; +} + +CodeBlockHash InlineCallFrame::hash() const +{ + return executable->hashFor(specializationKind()); +} + +} // namespace JSC + diff --git a/Source/JavaScriptCore/bytecode/CodeOrigin.h b/Source/JavaScriptCore/bytecode/CodeOrigin.h index c9c0f7005..d8fbf7328 100644 --- a/Source/JavaScriptCore/bytecode/CodeOrigin.h +++ b/Source/JavaScriptCore/bytecode/CodeOrigin.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,6 +26,8 @@ #ifndef CodeOrigin_h #define CodeOrigin_h +#include "CodeBlockHash.h" +#include "CodeSpecializationKind.h" #include "ValueRecovery.h" #include "WriteBarrier.h" #include <wtf/BitVector.h> @@ -98,6 +100,10 @@ struct InlineCallFrame { BitVector capturedVars; // Indexed by the machine call frame's variable numbering. unsigned stackOffset : 31; bool isCall : 1; + + CodeSpecializationKind specializationKind() const { return specializationFromIsCall(isCall); } + + CodeBlockHash hash() const; }; struct CodeOriginAtCallReturnOffset { @@ -105,36 +111,12 @@ struct CodeOriginAtCallReturnOffset { unsigned callReturnOffset; }; -inline unsigned CodeOrigin::inlineDepthForCallFrame(InlineCallFrame* inlineCallFrame) -{ - unsigned result = 1; - for (InlineCallFrame* current = inlineCallFrame; current; current = current->caller.inlineCallFrame) - result++; - return result; -} - -inline unsigned CodeOrigin::inlineDepth() const -{ - return inlineDepthForCallFrame(inlineCallFrame); -} - inline bool CodeOrigin::operator==(const CodeOrigin& other) const { return bytecodeIndex == other.bytecodeIndex && inlineCallFrame == other.inlineCallFrame; } -// Get the inline stack. This is slow, and is intended for debugging only. -inline Vector<CodeOrigin> CodeOrigin::inlineStack() const -{ - Vector<CodeOrigin> result(inlineDepth()); - result.last() = *this; - unsigned index = result.size() - 2; - for (InlineCallFrame* current = inlineCallFrame; current; current = current->caller.inlineCallFrame) - result[index--] = current->caller; - return result; -} - inline unsigned getCallReturnOffsetForCodeOrigin(CodeOriginAtCallReturnOffset* data) { return data->callReturnOffset; diff --git a/Source/JavaScriptCore/bytecode/CodeType.cpp b/Source/JavaScriptCore/bytecode/CodeType.cpp new file mode 100644 index 000000000..8b2cad56a --- /dev/null +++ b/Source/JavaScriptCore/bytecode/CodeType.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CodeType.h" + +#include <wtf/PrintStream.h> + +namespace WTF { + +void printInternal(PrintStream& out, JSC::CodeType codeType) +{ + switch (codeType) { + case JSC::GlobalCode: + out.print("Global"); + return; + case JSC::EvalCode: + out.print("Eval"); + return; + case JSC::FunctionCode: + out.print("Function"); + return; + default: + CRASH(); + return; + } +} + +} // namespace WTF + diff --git a/Source/JavaScriptCore/bytecode/CodeType.h b/Source/JavaScriptCore/bytecode/CodeType.h index d33677ae7..04afc1109 100644 --- a/Source/JavaScriptCore/bytecode/CodeType.h +++ b/Source/JavaScriptCore/bytecode/CodeType.h @@ -32,22 +32,14 @@ namespace JSC { enum CodeType { GlobalCode, EvalCode, FunctionCode }; -inline const char* codeTypeToString(CodeType codeType) -{ - switch (codeType) { - case GlobalCode: - return "GlobalCode"; - case EvalCode: - return "EvalCode"; - case FunctionCode: - return "FunctionCode"; - default: - ASSERT_NOT_REACHED(); - return 0; - } -} - } // namespace JSC +namespace WTF { + +class PrintStream; +void printInternal(PrintStream&, JSC::CodeType); + +} // namespace WTF + #endif // CodeType_h diff --git a/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp b/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp index 12a404981..e619a0376 100644 --- a/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp +++ b/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp @@ -160,11 +160,9 @@ void ExecutionCounter::reset() m_activeThreshold = 0; } -const char* ExecutionCounter::status() const +void ExecutionCounter::dump(PrintStream& out) const { - static char result[80]; - snprintf(result, sizeof(result), "%lf/%lf, %d", count(), static_cast<double>(m_activeThreshold), m_counter); - return result; + out.printf("%lf/%lf, %d", count(), static_cast<double>(m_activeThreshold), m_counter); } } // namespace JSC diff --git a/Source/JavaScriptCore/bytecode/ExecutionCounter.h b/Source/JavaScriptCore/bytecode/ExecutionCounter.h index f40650a31..c755c0445 100644 --- a/Source/JavaScriptCore/bytecode/ExecutionCounter.h +++ b/Source/JavaScriptCore/bytecode/ExecutionCounter.h @@ -28,6 +28,7 @@ #include "JSGlobalObject.h" #include "Options.h" +#include <wtf/PrintStream.h> #include <wtf/SimpleStats.h> namespace JSC { @@ -41,7 +42,7 @@ public: void setNewThreshold(int32_t threshold, CodeBlock*); void deferIndefinitely(); double count() const { return static_cast<double>(m_totalCount) + m_counter; } - const char* status() const; + void dump(PrintStream&) const; static double applyMemoryUsageHeuristics(int32_t value, CodeBlock*); static int32_t applyMemoryUsageHeuristicsAndConvertToInt(int32_t value, CodeBlock*); template<typename T> |