summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/tools
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/tools')
-rw-r--r--Source/JavaScriptCore/tools/CodeProfile.cpp16
-rw-r--r--Source/JavaScriptCore/tools/CodeProfile.h12
-rw-r--r--Source/JavaScriptCore/tools/CodeProfiling.cpp14
-rw-r--r--Source/JavaScriptCore/tools/FunctionOverrides.cpp250
-rw-r--r--Source/JavaScriptCore/tools/FunctionOverrides.h64
-rw-r--r--Source/JavaScriptCore/tools/JSDollarVM.cpp36
-rw-r--r--Source/JavaScriptCore/tools/JSDollarVM.h60
-rw-r--r--Source/JavaScriptCore/tools/JSDollarVMPrototype.cpp428
-rw-r--r--Source/JavaScriptCore/tools/JSDollarVMPrototype.h81
-rw-r--r--Source/JavaScriptCore/tools/ProfileTreeNode.h2
10 files changed, 940 insertions, 23 deletions
diff --git a/Source/JavaScriptCore/tools/CodeProfile.cpp b/Source/JavaScriptCore/tools/CodeProfile.cpp
index de86e52ef..c64f1d5a6 100644
--- a/Source/JavaScriptCore/tools/CodeProfile.cpp
+++ b/Source/JavaScriptCore/tools/CodeProfile.cpp
@@ -33,7 +33,7 @@
#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>
-#if PLATFORM(MAC)
+#if OS(DARWIN)
#include <cxxabi.h>
#include <dlfcn.h>
#include <execinfo.h>
@@ -56,7 +56,7 @@ const char* CodeProfile::s_codeTypeNames[CodeProfile::NumberOfCodeTypes] = {
// Helper function, find the symbol name for a pc in JSC.
static const char* symbolName(void* address)
{
-#if PLATFORM(MAC)
+#if OS(DARWIN)
Dl_info info;
if (!dladdr(address, &info) || !info.dli_sname)
return "<unknown>";
@@ -74,7 +74,7 @@ static const char* symbolName(void* address)
static bool truncateTrace(const char* symbolName)
{
return !strcmp(symbolName, "JSC::BytecodeGenerator::generate()")
- || !strcmp(symbolName, "JSC::Parser<JSC::Lexer<unsigned char> >::parseInner()")
+ || !strcmp(symbolName, "JSC::Parser<JSC::Lexer<unsigned char>>::parseInner()")
|| !strcmp(symbolName, "WTF::fastMalloc(unsigned long)")
|| !strcmp(symbolName, "WTF::calculateUTCOffset()")
|| !strcmp(symbolName, "JSC::DFG::ByteCodeParser::parseCodeBlock()");
@@ -105,9 +105,9 @@ void CodeProfile::sample(void* pc, void** framePointer)
type = RegExpCode;
else {
CodeBlock* codeBlock = static_cast<CodeBlock*>(ownerUID);
- if (codeBlock->getJITType() == JITCode::DFGJIT)
+ if (codeBlock->jitType() == JITCode::DFGJIT)
type = DFGJIT;
- else if (codeBlock->canCompileWithDFGState() != DFG::CanCompile)
+ else if (!canCompile(codeBlock->capabilityLevelState()))
type = BaselineOnly;
else if (codeBlock->replacement())
type = BaselineOSR;
@@ -123,7 +123,7 @@ void CodeProfile::sample(void* pc, void** framePointer)
if (type != EngineFrame)
return;
-#if PLATFORM(MAC) && CPU(X86_64)
+#if OS(DARWIN) && CPU(X86_64)
// Walk up the stack.
pc = framePointer[1];
framePointer = reinterpret_cast<void**>(*framePointer);
@@ -143,7 +143,7 @@ void CodeProfile::sample(void* pc, void** framePointer)
void CodeProfile::report()
{
- dataLogF("<CodeProfiling %s:%d>\n", m_file.data(), m_lineNo);
+ dataLogF("<CodeProfiling %s:%d>\n", m_file.data(), m_lineNumber);
// How many frames of C-code to print - 0, if not verbose, 1 if verbose, up to 1024 if very verbose.
unsigned recursionLimit = CodeProfiling::beVeryVerbose() ? 1024 : CodeProfiling::beVerbose();
@@ -186,7 +186,7 @@ void CodeProfile::report()
for (size_t i = 0 ; i < m_children.size(); ++i)
m_children[i]->report();
- dataLogF("</CodeProfiling %s:%d>\n", m_file.data(), m_lineNo);
+ dataLogF("</CodeProfiling %s:%d>\n", m_file.data(), m_lineNumber);
}
}
diff --git a/Source/JavaScriptCore/tools/CodeProfile.h b/Source/JavaScriptCore/tools/CodeProfile.h
index db380eedb..37ed22e46 100644
--- a/Source/JavaScriptCore/tools/CodeProfile.h
+++ b/Source/JavaScriptCore/tools/CodeProfile.h
@@ -37,11 +37,11 @@ class CodeProfile {
public:
CodeProfile(const SourceCode& source, CodeProfile* parent)
: m_file(source.provider()->url().utf8())
- , m_lineNo(source.firstLine())
+ , m_lineNumber(source.firstLine())
, m_parent(parent)
{
if (parent)
- parent->addChild(this);
+ parent->addChild(std::unique_ptr<CodeProfile>(this));
}
void sample(void* pc, void** framePointer);
@@ -52,9 +52,9 @@ public:
return m_parent;
}
- void addChild(CodeProfile* child)
+ void addChild(std::unique_ptr<CodeProfile> child)
{
- m_children.append(adoptPtr(child));
+ m_children.append(WTFMove(child));
}
private:
@@ -80,9 +80,9 @@ private:
};
CString m_file;
- unsigned m_lineNo;
+ unsigned m_lineNumber;
CodeProfile* m_parent;
- Vector< OwnPtr<CodeProfile> > m_children;
+ Vector<std::unique_ptr<CodeProfile>> m_children;
TieredMMapArray<CodeRecord> m_samples;
static const char* s_codeTypeNames[NumberOfCodeTypes];
diff --git a/Source/JavaScriptCore/tools/CodeProfiling.cpp b/Source/JavaScriptCore/tools/CodeProfiling.cpp
index f545be903..302b5f929 100644
--- a/Source/JavaScriptCore/tools/CodeProfiling.cpp
+++ b/Source/JavaScriptCore/tools/CodeProfiling.cpp
@@ -33,7 +33,7 @@
#include <signal.h>
#endif
-#if OS(LINUX)
+#if OS(LINUX) || OS(DARWIN)
#include <sys/time.h>
#endif
@@ -48,7 +48,7 @@ WTF::MetaAllocatorTracker* CodeProfiling::s_tracker = 0;
#pragma clang diagnostic ignored "-Wmissing-noreturn"
#endif
-#if (PLATFORM(MAC) && CPU(X86_64)) || (OS(LINUX) && CPU(X86) && !OS(ANDROID))
+#if (OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && CPU(X86_64)) || (OS(LINUX) && CPU(X86))
// Helper function to start & stop the timer.
// Presently we're using the wall-clock timer, since this seems to give the best results.
static void setProfileTimer(unsigned usec)
@@ -66,14 +66,14 @@ static void setProfileTimer(unsigned usec)
#pragma clang diagnostic pop
#endif
-#if PLATFORM(MAC) && CPU(X86_64)
+#if OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && CPU(X86_64)
static void profilingTimer(int, siginfo_t*, void* uap)
{
mcontext_t context = static_cast<ucontext_t*>(uap)->uc_mcontext;
CodeProfiling::sample(reinterpret_cast<void*>(context->__ss.__rip),
reinterpret_cast<void**>(context->__ss.__rbp));
}
-#elif OS(LINUX) && CPU(X86) && !OS(ANDROID)
+#elif OS(LINUX) && CPU(X86)
static void profilingTimer(int, siginfo_t*, void* uap)
{
mcontext_t context = static_cast<ucontext_t*>(uap)->uc_mcontext;
@@ -92,7 +92,6 @@ void CodeProfiling::sample(void* pc, void** framePointer)
void CodeProfiling::notifyAllocator(WTF::MetaAllocator* allocator)
{
-#if !OS(WINCE)
// Check for JSC_CODE_PROFILING.
const char* codeProfilingMode = getenv("JSC_CODE_PROFILING");
if (!codeProfilingMode)
@@ -119,7 +118,6 @@ void CodeProfiling::notifyAllocator(WTF::MetaAllocator* allocator)
ASSERT(!s_tracker);
s_tracker = new WTF::MetaAllocatorTracker();
allocator->trackAllocations(s_tracker);
-#endif
}
void* CodeProfiling::getOwnerUIDForPC(void* address)
@@ -143,7 +141,7 @@ void CodeProfiling::begin(const SourceCode& source)
if (alreadyProfiling)
return;
-#if (PLATFORM(MAC) && CPU(X86_64)) || (OS(LINUX) && CPU(X86) && !OS(ANDROID))
+#if (OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && CPU(X86_64)) || (OS(LINUX) && CPU(X86))
// Regsiter a signal handler & itimer.
struct sigaction action;
action.sa_sigaction = reinterpret_cast<void (*)(int, siginfo_t *, void *)>(profilingTimer);
@@ -167,7 +165,7 @@ void CodeProfiling::end()
if (s_profileStack)
return;
-#if (PLATFORM(MAC) && CPU(X86_64)) || (OS(LINUX) && CPU(X86) && !OS(ANDROID))
+#if (OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && CPU(X86_64)) || (OS(LINUX) && CPU(X86))
// Stop profiling
setProfileTimer(0);
#endif
diff --git a/Source/JavaScriptCore/tools/FunctionOverrides.cpp b/Source/JavaScriptCore/tools/FunctionOverrides.cpp
new file mode 100644
index 000000000..2e328c167
--- /dev/null
+++ b/Source/JavaScriptCore/tools/FunctionOverrides.cpp
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2015 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 "FunctionOverrides.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <wtf/DataLog.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringHash.h>
+
+namespace JSC {
+
+/*
+ The overrides file defines function bodies that we will want to override with
+ a replacement for debugging purposes. The overrides file may contain
+ 'override' and 'with' clauses like these:
+
+ // Example 1: function foo1(a)
+ override !@#$%{ print("In foo1"); }!@#$%
+ with abc{
+ print("I am overridden");
+ }abc
+
+ // Example 2: function foo2(a)
+ override %%%{
+ print("foo2's body has a string with }%% in it.");
+ // Because }%% appears in the function body here, we cannot use
+ // %% or % as the delimiter. %%% is ok though.
+ }%%%
+ with %%%{
+ print("Overridden foo2");
+ }%%%
+
+ 1. Comments are lines starting with //. All comments will be ignored.
+
+ 2. An 'override' clause is used to specify the original function body we
+ want to override. The with clause is used to specify the overriding
+ function body.
+
+ An 'override' clause must be followed immediately by a 'with' clause.
+
+ 3. An 'override' clause must be of the form:
+ override <delimiter>{...function body...}<delimiter>
+
+ The override keyword must be at the start of the line.
+
+ <delimiter> may be any string of any ASCII characters (except for '{',
+ '}', and whitespace characters) as long as the pattern of "}<delimiter>"
+ does not appear in the function body e.g. the override clause of Example 2
+ above illustrates this.
+
+ The start and end <delimiter> must be identical.
+
+ The space between the override keyword and the start <delimiter> is
+ required.
+
+ All characters between the pair of delimiters will be considered to
+ be part of the function body string. This allows us to also work
+ with script source that are multi-lined i.e. newlines are allowed.
+
+ 4. A 'with' clause is identical in form to an 'override' clause except that
+ it uses the 'with' keyword instead of the 'override' keyword.
+ */
+
+FunctionOverrides& FunctionOverrides::overrides()
+{
+ static LazyNeverDestroyed<FunctionOverrides> overrides;
+ static std::once_flag initializeListFlag;
+ std::call_once(initializeListFlag, [] {
+ const char* overridesFileName = Options::functionOverrides();
+ overrides.construct(overridesFileName);
+ });
+ return overrides;
+}
+
+FunctionOverrides::FunctionOverrides(const char* overridesFileName)
+{
+ parseOverridesInFile(overridesFileName);
+}
+
+static void initializeOverrideInfo(const SourceCode& origCode, const String& newBody, FunctionOverrides::OverrideInfo& info)
+{
+ String origProviderStr = origCode.provider()->source().toString();
+ unsigned origBraceStart = origCode.startOffset();
+ unsigned origFunctionStart = origProviderStr.reverseFind("function", origBraceStart);
+ unsigned headerLength = origBraceStart - origFunctionStart;
+ String origHeader = origProviderStr.substring(origFunctionStart, headerLength);
+
+ String newProviderStr;
+ newProviderStr.append(origHeader);
+ newProviderStr.append(newBody);
+
+ RefPtr<SourceProvider> newProvider = StringSourceProvider::create(newProviderStr, "<overridden>");
+
+ info.firstLine = 1;
+ info.lineCount = 1; // Faking it. This doesn't really matter for now.
+ info.startColumn = 1;
+ info.endColumn = 1; // Faking it. This doesn't really matter for now.
+ info.parametersStartOffset = newProviderStr.find("(");
+ info.typeProfilingStartOffset = newProviderStr.find("{");
+ info.typeProfilingEndOffset = newProviderStr.length() - 1;
+
+ info.sourceCode =
+ SourceCode(newProvider.release(), info.typeProfilingStartOffset, info.typeProfilingEndOffset + 1, 1, 1);
+}
+
+bool FunctionOverrides::initializeOverrideFor(const SourceCode& origCode, FunctionOverrides::OverrideInfo& result)
+{
+ ASSERT(Options::functionOverrides());
+ FunctionOverrides& overrides = FunctionOverrides::overrides();
+
+ auto it = overrides.m_entries.find(origCode.view().toString());
+ if (it == overrides.m_entries.end())
+ return false;
+
+ initializeOverrideInfo(origCode, it->value, result);
+ return true;
+}
+
+#define SYNTAX_ERROR "SYNTAX ERROR"
+#define IO_ERROR "IO ERROR"
+#define FAIL_WITH_ERROR(error, errorMessageInBrackets) \
+ do { \
+ dataLog("functionOverrides ", error, ": "); \
+ dataLog errorMessageInBrackets; \
+ exit(EXIT_FAILURE); \
+ } while (false)
+
+static bool hasDisallowedCharacters(const char* str, size_t length)
+{
+ while (length--) {
+ char c = *str++;
+ // '{' is also disallowed, but we don't need to check for it because
+ // parseClause() searches for '{' as the end of the start delimiter.
+ // As a result, the parsed delimiter string will never include '{'.
+ if (c == '}' || isASCIISpace(c))
+ return true;
+ }
+ return false;
+}
+
+static String parseClause(const char* keyword, size_t keywordLength, FILE* file, const char* line, char* buffer, size_t bufferSize)
+{
+ const char* keywordPos = strstr(line, keyword);
+ if (!keywordPos)
+ FAIL_WITH_ERROR(SYNTAX_ERROR, ("Expecting '", keyword, "' clause:\n", line, "\n"));
+ if (keywordPos != line)
+ FAIL_WITH_ERROR(SYNTAX_ERROR, ("Cannot have any characters before '", keyword, "':\n", line, "\n"));
+ if (line[keywordLength] != ' ')
+ FAIL_WITH_ERROR(SYNTAX_ERROR, ("'", keyword, "' must be followed by a ' ':\n", line, "\n"));
+
+ const char* delimiterStart = &line[keywordLength + 1];
+ const char* delimiterEnd = strstr(delimiterStart, "{");
+ if (!delimiterEnd)
+ FAIL_WITH_ERROR(SYNTAX_ERROR, ("Missing { after '", keyword, "' clause start delimiter:\n", line, "\n"));
+
+ size_t delimiterLength = delimiterEnd - delimiterStart;
+ String delimiter(delimiterStart, delimiterLength);
+
+ if (hasDisallowedCharacters(delimiterStart, delimiterLength))
+ FAIL_WITH_ERROR(SYNTAX_ERROR, ("Delimiter '", delimiter, "' cannot have '{', '}', or whitespace:\n", line, "\n"));
+
+ String terminatorString;
+ terminatorString.append("}");
+ terminatorString.append(delimiter);
+
+ const char* terminator = terminatorString.ascii().data();
+ line = delimiterEnd; // Start from the {.
+
+ StringBuilder builder;
+ do {
+ const char* p = strstr(line, terminator);
+ if (p) {
+ if (p[strlen(terminator)] != '\n')
+ FAIL_WITH_ERROR(SYNTAX_ERROR, ("Unexpected characters after '", keyword, "' clause end delimiter '", delimiter, "':\n", line, "\n"));
+
+ builder.append(line, p - line + 1);
+ return builder.toString();
+ }
+ builder.append(line);
+
+ } while ((line = fgets(buffer, bufferSize, file)));
+
+ FAIL_WITH_ERROR(SYNTAX_ERROR, ("'", keyword, "' clause end delimiter '", delimiter, "' not found:\n", builder.toString(), "\n", "Are you missing a '}' before the delimiter?\n"));
+}
+
+void FunctionOverrides::parseOverridesInFile(const char* fileName)
+{
+ if (!fileName)
+ return;
+
+ FILE* file = fopen(fileName, "r");
+ if (!file)
+ FAIL_WITH_ERROR(IO_ERROR, ("Failed to open file ", fileName, ". Did you add the file-read-data entitlement to WebProcess.sb?\n"));
+
+ char* line;
+ char buffer[BUFSIZ];
+ while ((line = fgets(buffer, sizeof(buffer), file))) {
+ if (strstr(line, "//") == line)
+ continue;
+
+ if (line[0] == '\n' || line[0] == '\0')
+ continue;
+
+ size_t keywordLength;
+
+ keywordLength = sizeof("override") - 1;
+ String keyStr = parseClause("override", keywordLength, file, line, buffer, sizeof(buffer));
+
+ line = fgets(buffer, sizeof(buffer), file);
+
+ keywordLength = sizeof("with") - 1;
+ String valueStr = parseClause("with", keywordLength, file, line, buffer, sizeof(buffer));
+
+ m_entries.add(keyStr, valueStr);
+ }
+
+ int result = fclose(file);
+ if (result)
+ dataLogF("Failed to close file %s: %s\n", fileName, strerror(errno));
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/tools/FunctionOverrides.h b/Source/JavaScriptCore/tools/FunctionOverrides.h
new file mode 100644
index 000000000..a0d8ad47a
--- /dev/null
+++ b/Source/JavaScriptCore/tools/FunctionOverrides.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015 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 FunctionOverrides_h
+#define FunctionOverrides_h
+
+#include "Options.h"
+#include "SourceCode.h"
+#include <wtf/HashMap.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+
+class ScriptExecutable;
+
+class FunctionOverrides {
+public:
+ struct OverrideInfo {
+ SourceCode sourceCode;
+ unsigned firstLine;
+ unsigned lineCount;
+ unsigned startColumn;
+ unsigned endColumn;
+ unsigned parametersStartOffset;
+ unsigned typeProfilingStartOffset;
+ unsigned typeProfilingEndOffset;
+ };
+
+ static FunctionOverrides& overrides();
+ FunctionOverrides(const char* functionOverridesFileName);
+
+ static bool initializeOverrideFor(const SourceCode& origCode, OverrideInfo& result);
+
+private:
+ void parseOverridesInFile(const char* fileName);
+
+ HashMap<String, String> m_entries;
+};
+
+} // namespace JSC
+
+#endif // FunctionOverrides_h
diff --git a/Source/JavaScriptCore/tools/JSDollarVM.cpp b/Source/JavaScriptCore/tools/JSDollarVM.cpp
new file mode 100644
index 000000000..ee5c3d18e
--- /dev/null
+++ b/Source/JavaScriptCore/tools/JSDollarVM.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 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 "JSDollarVM.h"
+
+#include "JSCJSValueInlines.h"
+#include "StructureInlines.h"
+
+namespace JSC {
+
+const ClassInfo JSDollarVM::s_info = { "DollarVM", &Base::s_info, 0, CREATE_METHOD_TABLE(JSDollarVM) };
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/tools/JSDollarVM.h b/Source/JavaScriptCore/tools/JSDollarVM.h
new file mode 100644
index 000000000..6b5be038f
--- /dev/null
+++ b/Source/JavaScriptCore/tools/JSDollarVM.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 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 JSDollarVM_h
+#define JSDollarVM_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+class JSDollarVM : public JSNonFinalObject {
+public:
+ typedef JSNonFinalObject Base;
+
+ DECLARE_EXPORT_INFO;
+
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+ {
+ return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
+ }
+
+ static JSDollarVM* create(VM& vm, Structure* structure)
+ {
+ JSDollarVM* instance = new (NotNull, allocateCell<JSDollarVM>(vm.heap)) JSDollarVM(vm, structure);
+ instance->finishCreation(vm);
+ return instance;
+ }
+
+private:
+ JSDollarVM(VM& vm, Structure* structure)
+ : Base(vm, structure)
+ {
+ }
+};
+
+} // namespace JSC
+
+#endif // JSDollarVM_h
diff --git a/Source/JavaScriptCore/tools/JSDollarVMPrototype.cpp b/Source/JavaScriptCore/tools/JSDollarVMPrototype.cpp
new file mode 100644
index 000000000..2d87eaacc
--- /dev/null
+++ b/Source/JavaScriptCore/tools/JSDollarVMPrototype.cpp
@@ -0,0 +1,428 @@
+/*
+ * Copyright (C) 2015 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 "JSDollarVMPrototype.h"
+
+#include "CodeBlock.h"
+#include "Heap.h"
+#include "HeapIterationScope.h"
+#include "JSCInlines.h"
+#include "JSFunction.h"
+#include "StackVisitor.h"
+#include <wtf/DataLog.h>
+
+namespace JSC {
+
+const ClassInfo JSDollarVMPrototype::s_info = { "DollarVMPrototype", &Base::s_info, 0, CREATE_METHOD_TABLE(JSDollarVMPrototype) };
+
+
+bool JSDollarVMPrototype::currentThreadOwnsJSLock(ExecState* exec)
+{
+ return exec->vm().apiLock().currentThreadIsHoldingLock();
+}
+
+static bool ensureCurrentThreadOwnsJSLock(ExecState* exec)
+{
+ if (JSDollarVMPrototype::currentThreadOwnsJSLock(exec))
+ return true;
+ dataLog("ERROR: current thread does not own the JSLock\n");
+ return false;
+}
+
+void JSDollarVMPrototype::addFunction(VM& vm, JSGlobalObject* globalObject, const char* name, NativeFunction function, unsigned arguments)
+{
+ Identifier identifier = Identifier::fromString(&vm, name);
+ putDirect(vm, identifier, JSFunction::create(vm, globalObject, arguments, identifier.string(), function));
+}
+
+static EncodedJSValue JSC_HOST_CALL functionCrash(ExecState*)
+{
+ CRASH();
+ return JSValue::encode(jsUndefined());
+}
+
+static EncodedJSValue JSC_HOST_CALL functionDFGTrue(ExecState*)
+{
+ return JSValue::encode(jsBoolean(false));
+}
+
+class CallerFrameJITTypeFunctor {
+public:
+ CallerFrameJITTypeFunctor()
+ : m_currentFrame(0)
+ , m_jitType(JITCode::None)
+ {
+ }
+
+ StackVisitor::Status operator()(StackVisitor& visitor)
+ {
+ if (m_currentFrame++ > 1) {
+ m_jitType = visitor->codeBlock()->jitType();
+ return StackVisitor::Done;
+ }
+ return StackVisitor::Continue;
+ }
+
+ JITCode::JITType jitType() { return m_jitType; }
+
+private:
+ unsigned m_currentFrame;
+ JITCode::JITType m_jitType;
+};
+
+static EncodedJSValue JSC_HOST_CALL functionLLintTrue(ExecState* exec)
+{
+ if (!exec)
+ return JSValue::encode(jsUndefined());
+ CallerFrameJITTypeFunctor functor;
+ exec->iterate(functor);
+ return JSValue::encode(jsBoolean(functor.jitType() == JITCode::InterpreterThunk));
+}
+
+static EncodedJSValue JSC_HOST_CALL functionJITTrue(ExecState* exec)
+{
+ if (!exec)
+ return JSValue::encode(jsUndefined());
+ CallerFrameJITTypeFunctor functor;
+ exec->iterate(functor);
+ return JSValue::encode(jsBoolean(functor.jitType() == JITCode::BaselineJIT));
+}
+
+void JSDollarVMPrototype::gc(ExecState* exec)
+{
+ if (!ensureCurrentThreadOwnsJSLock(exec))
+ return;
+ exec->heap()->collectAllGarbage();
+}
+
+static EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
+{
+ JSDollarVMPrototype::gc(exec);
+ return JSValue::encode(jsUndefined());
+}
+
+void JSDollarVMPrototype::edenGC(ExecState* exec)
+{
+ if (!ensureCurrentThreadOwnsJSLock(exec))
+ return;
+ exec->heap()->collectAndSweep(EdenCollection);
+}
+
+static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
+{
+ JSDollarVMPrototype::edenGC(exec);
+ return JSValue::encode(jsUndefined());
+}
+
+bool JSDollarVMPrototype::isInHeap(Heap* heap, void* ptr)
+{
+ return isInObjectSpace(heap, ptr) || isInStorageSpace(heap, ptr);
+}
+
+bool JSDollarVMPrototype::isInObjectSpace(Heap* heap, void* ptr)
+{
+ MarkedBlock* candidate = MarkedBlock::blockFor(ptr);
+ return heap->objectSpace().blocks().set().contains(candidate);
+}
+
+bool JSDollarVMPrototype::isInStorageSpace(Heap* heap, void* ptr)
+{
+ CopiedBlock* candidate = CopiedSpace::blockFor(ptr);
+ return heap->storageSpace().contains(candidate);
+}
+
+struct CellAddressCheckFunctor : MarkedBlock::CountFunctor {
+ CellAddressCheckFunctor(JSCell* candidate)
+ : candidate(candidate)
+ {
+ }
+
+ IterationStatus operator()(JSCell* cell)
+ {
+ if (cell == candidate) {
+ found = true;
+ return IterationStatus::Done;
+ }
+ return IterationStatus::Continue;
+ }
+
+ JSCell* candidate;
+ bool found { false };
+};
+
+bool JSDollarVMPrototype::isValidCell(Heap* heap, JSCell* candidate)
+{
+ HeapIterationScope iterationScope(*heap);
+ CellAddressCheckFunctor functor(candidate);
+ heap->objectSpace().forEachLiveCell(iterationScope, functor);
+ return functor.found;
+}
+
+bool JSDollarVMPrototype::isValidCodeBlock(ExecState* exec, CodeBlock* candidate)
+{
+ if (!ensureCurrentThreadOwnsJSLock(exec))
+ return false;
+
+ struct CodeBlockValidationFunctor {
+ CodeBlockValidationFunctor(CodeBlock* candidate)
+ : candidate(candidate)
+ {
+ }
+
+ bool operator()(CodeBlock* codeBlock)
+ {
+ if (codeBlock == candidate)
+ found = true;
+ return found;
+ }
+
+ CodeBlock* candidate;
+ bool found { false };
+ };
+
+ VM& vm = exec->vm();
+ CodeBlockValidationFunctor functor(candidate);
+ vm.heap.forEachCodeBlock(functor);
+ return functor.found;
+}
+
+CodeBlock* JSDollarVMPrototype::codeBlockForFrame(CallFrame* topCallFrame, unsigned frameNumber)
+{
+ if (!ensureCurrentThreadOwnsJSLock(topCallFrame))
+ return nullptr;
+
+ if (!topCallFrame)
+ return nullptr;
+
+ struct FetchCodeBlockFunctor {
+ public:
+ FetchCodeBlockFunctor(unsigned targetFrameNumber)
+ : targetFrame(targetFrameNumber)
+ {
+ }
+
+ StackVisitor::Status operator()(StackVisitor& visitor)
+ {
+ currentFrame++;
+ if (currentFrame == targetFrame) {
+ codeBlock = visitor->codeBlock();
+ return StackVisitor::Done;
+ }
+ return StackVisitor::Continue;
+ }
+
+ unsigned targetFrame;
+ unsigned currentFrame { 0 };
+ CodeBlock* codeBlock { nullptr };
+ };
+
+ FetchCodeBlockFunctor functor(frameNumber);
+ topCallFrame->iterate(functor);
+ return functor.codeBlock;
+}
+
+static EncodedJSValue JSC_HOST_CALL functionCodeBlockForFrame(ExecState* exec)
+{
+ if (exec->argumentCount() < 1)
+ return JSValue::encode(jsUndefined());
+
+ JSValue value = exec->uncheckedArgument(0);
+ if (!value.isUInt32())
+ return JSValue::encode(jsUndefined());
+
+ // We need to inc the frame number because the caller would consider
+ // its own frame as frame 0. Hence, we need discount the frame for this
+ // function.
+ unsigned frameNumber = value.asUInt32() + 1;
+ CodeBlock* codeBlock = JSDollarVMPrototype::codeBlockForFrame(exec, frameNumber);
+ return JSValue::encode(JSValue(bitwise_cast<double>(reinterpret_cast<uint64_t>(codeBlock))));
+}
+
+static CodeBlock* codeBlockFromArg(ExecState* exec)
+{
+ if (exec->argumentCount() < 1)
+ return nullptr;
+
+ JSValue value = exec->uncheckedArgument(0);
+ if (!value.isDouble()) {
+ dataLog("Invalid codeBlock: ", value, "\n");
+ return nullptr;
+ }
+
+ CodeBlock* codeBlock = reinterpret_cast<CodeBlock*>(bitwise_cast<uint64_t>(value.asDouble()));
+ if (JSDollarVMPrototype::isValidCodeBlock(exec, codeBlock))
+ return codeBlock;
+
+ dataLogF("Invalid codeBlock: %p ", codeBlock);
+ dataLog(value, "\n");
+ return nullptr;
+
+}
+
+static EncodedJSValue JSC_HOST_CALL functionPrintSourceFor(ExecState* exec)
+{
+ CodeBlock* codeBlock = codeBlockFromArg(exec);
+ if (codeBlock)
+ codeBlock->dumpSource();
+ return JSValue::encode(jsUndefined());
+}
+
+static EncodedJSValue JSC_HOST_CALL functionPrintByteCodeFor(ExecState* exec)
+{
+ CodeBlock* codeBlock = codeBlockFromArg(exec);
+ if (codeBlock)
+ codeBlock->dumpBytecode();
+ return JSValue::encode(jsUndefined());
+}
+
+static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
+{
+ for (unsigned i = 0; i < exec->argumentCount(); ++i) {
+ if (i)
+ dataLog(" ");
+ String argStr = exec->uncheckedArgument(i).toString(exec)->value(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ dataLog(argStr);
+ }
+ return JSValue::encode(jsUndefined());
+}
+
+class PrintFrameFunctor {
+public:
+ enum Action {
+ PrintOne,
+ PrintAll
+ };
+
+ PrintFrameFunctor(Action action, unsigned framesToSkip)
+ : m_action(action)
+ , m_framesToSkip(framesToSkip)
+ {
+ }
+
+ StackVisitor::Status operator()(StackVisitor& visitor)
+ {
+ m_currentFrame++;
+ if (m_currentFrame > m_framesToSkip)
+ visitor->print(2);
+
+ if (m_action == PrintOne && m_currentFrame > m_framesToSkip)
+ return StackVisitor::Done;
+ return StackVisitor::Continue;
+ }
+
+private:
+ Action m_action;
+ unsigned m_framesToSkip;
+ unsigned m_currentFrame { 0 };
+};
+
+static void printCallFrame(CallFrame* callFrame, unsigned framesToSkip)
+{
+ if (!ensureCurrentThreadOwnsJSLock(callFrame))
+ return;
+ PrintFrameFunctor functor(PrintFrameFunctor::PrintOne, framesToSkip);
+ callFrame->iterate(functor);
+}
+
+void JSDollarVMPrototype::printCallFrame(CallFrame* callFrame)
+{
+ JSC::printCallFrame(callFrame, 0);
+}
+
+static void printStack(CallFrame* topCallFrame, unsigned framesToSkip)
+{
+ if (!ensureCurrentThreadOwnsJSLock(topCallFrame))
+ return;
+ if (!topCallFrame)
+ return;
+ PrintFrameFunctor functor(PrintFrameFunctor::PrintAll, framesToSkip);
+ topCallFrame->iterate(functor);
+}
+
+void JSDollarVMPrototype::printStack(CallFrame* topCallFrame)
+{
+ JSC::printStack(topCallFrame, 0);
+}
+
+static EncodedJSValue JSC_HOST_CALL functionPrintCallFrame(ExecState* exec)
+{
+ // When the callers call this function, they are expecting to print their
+ // own frame. So skip 1 for this frame.
+ printCallFrame(exec, 1);
+ return JSValue::encode(jsUndefined());
+}
+
+static EncodedJSValue JSC_HOST_CALL functionPrintStack(ExecState* exec)
+{
+ // When the callers call this function, they are expecting to print the
+ // stack starting their own frame. So skip 1 for this frame.
+ printStack(exec, 1);
+ return JSValue::encode(jsUndefined());
+}
+
+void JSDollarVMPrototype::printValue(JSValue value)
+{
+ dataLog(value);
+}
+
+static EncodedJSValue JSC_HOST_CALL functionPrintValue(ExecState* exec)
+{
+ for (unsigned i = 0; i < exec->argumentCount(); ++i) {
+ if (i)
+ dataLog(" ");
+ dataLog(exec->uncheckedArgument(i));
+ }
+ return JSValue::encode(jsUndefined());
+}
+
+void JSDollarVMPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
+{
+ Base::finishCreation(vm);
+
+ addFunction(vm, globalObject, "crash", functionCrash, 0);
+
+ putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "dfgTrue"), 0, functionDFGTrue, DFGTrueIntrinsic, DontEnum);
+
+ addFunction(vm, globalObject, "llintTrue", functionLLintTrue, 0);
+ addFunction(vm, globalObject, "jitTrue", functionJITTrue, 0);
+
+ addFunction(vm, globalObject, "gc", functionGC, 0);
+ addFunction(vm, globalObject, "edenGC", functionEdenGC, 0);
+
+ addFunction(vm, globalObject, "codeBlockForFrame", functionCodeBlockForFrame, 1);
+ addFunction(vm, globalObject, "printSourceFor", functionPrintSourceFor, 1);
+ addFunction(vm, globalObject, "printByteCodeFor", functionPrintByteCodeFor, 1);
+
+ addFunction(vm, globalObject, "print", functionPrint, 1);
+ addFunction(vm, globalObject, "printCallFrame", functionPrintCallFrame, 0);
+ addFunction(vm, globalObject, "printStack", functionPrintStack, 0);
+
+ addFunction(vm, globalObject, "printValue", functionPrintValue, 1);
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/tools/JSDollarVMPrototype.h b/Source/JavaScriptCore/tools/JSDollarVMPrototype.h
new file mode 100644
index 000000000..4c58be299
--- /dev/null
+++ b/Source/JavaScriptCore/tools/JSDollarVMPrototype.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015 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 JSDollarVMPrototype_h
+#define JSDollarVMPrototype_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+class Heap;
+
+class JSDollarVMPrototype : public JSNonFinalObject {
+public:
+ typedef JSNonFinalObject Base;
+
+ DECLARE_INFO;
+
+ static JSDollarVMPrototype* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
+ {
+ JSDollarVMPrototype* prototype = new (NotNull, allocateCell<JSDollarVMPrototype>(vm.heap)) JSDollarVMPrototype(vm, structure);
+ prototype->finishCreation(vm, globalObject);
+ return prototype;
+ }
+
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+ {
+ return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
+ }
+
+ // The following are exported because they are designed to be callable from
+ // lldb. The JS versions are implemented on top of these.
+
+ JS_EXPORT_PRIVATE static bool currentThreadOwnsJSLock(ExecState*);
+ JS_EXPORT_PRIVATE static void gc(ExecState*);
+ JS_EXPORT_PRIVATE static void edenGC(ExecState*);
+ JS_EXPORT_PRIVATE static bool isInHeap(Heap*, void*);
+ JS_EXPORT_PRIVATE static bool isInObjectSpace(Heap*, void*);
+ JS_EXPORT_PRIVATE static bool isInStorageSpace(Heap*, void*);
+ JS_EXPORT_PRIVATE static bool isValidCell(Heap*, JSCell*);
+ JS_EXPORT_PRIVATE static bool isValidCodeBlock(ExecState*, CodeBlock*);
+ JS_EXPORT_PRIVATE static CodeBlock* codeBlockForFrame(CallFrame* topCallFrame, unsigned frameNumber);
+ JS_EXPORT_PRIVATE static void printCallFrame(CallFrame*);
+ JS_EXPORT_PRIVATE static void printStack(CallFrame* topCallFrame);
+ JS_EXPORT_PRIVATE static void printValue(JSValue);
+
+private:
+ JSDollarVMPrototype(VM& vm, Structure* structure)
+ : Base(vm, structure)
+ {
+ }
+
+ void finishCreation(VM&, JSGlobalObject*);
+ void addFunction(VM&, JSGlobalObject*, const char* name, NativeFunction, unsigned arguments);
+};
+
+} // namespace JSC
+
+#endif // JSDollarVMPrototype_h
diff --git a/Source/JavaScriptCore/tools/ProfileTreeNode.h b/Source/JavaScriptCore/tools/ProfileTreeNode.h
index 4daa7df4c..88d57f3dd 100644
--- a/Source/JavaScriptCore/tools/ProfileTreeNode.h
+++ b/Source/JavaScriptCore/tools/ProfileTreeNode.h
@@ -30,7 +30,7 @@ namespace JSC {
class ProfileTreeNode {
typedef HashMap<String, ProfileTreeNode> Map;
- typedef Map::ValueType MapEntry;
+ typedef Map::KeyValuePairType MapEntry;
public:
ProfileTreeNode()