summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/bytecode
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2012-11-30 16:58:06 +0100
committerSimon Hausmann <simon.hausmann@digia.com>2012-11-30 17:03:09 +0100
commit32ea33253afbbdefd2680aa95ab5f57455272ae7 (patch)
tree2389569585b666c310fbb36d3fb8e6ab94462967 /Source/JavaScriptCore/bytecode
parent41c25f231cbca1babc445187283524cc6c751c71 (diff)
downloadqtwebkit-32ea33253afbbdefd2680aa95ab5f57455272ae7.tar.gz
Imported WebKit commit 6a4a1d32e1d779548c726c4826cba9d69eb87601 (http://svn.webkit.org/repository/webkit/trunk@136242)
Final import for the Qt 5.x series that implements the QtWebKit / QtWebKitWidgets split Extra fixes will be cherry-picked. Change-Id: I844f1ebb99c6d6b75db31d6538c2acd628e79681 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'Source/JavaScriptCore/bytecode')
-rw-r--r--Source/JavaScriptCore/bytecode/CallLinkInfo.h6
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.cpp84
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.h19
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlockHash.cpp90
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlockHash.h78
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlockWithJITType.h56
-rw-r--r--Source/JavaScriptCore/bytecode/CodeOrigin.cpp62
-rw-r--r--Source/JavaScriptCore/bytecode/CodeOrigin.h32
-rw-r--r--Source/JavaScriptCore/bytecode/CodeType.cpp52
-rw-r--r--Source/JavaScriptCore/bytecode/CodeType.h22
-rw-r--r--Source/JavaScriptCore/bytecode/ExecutionCounter.cpp6
-rw-r--r--Source/JavaScriptCore/bytecode/ExecutionCounter.h3
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>