]> git.saurik.com Git - apple/javascriptcore.git/blame - disassembler/Disassembler.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / disassembler / Disassembler.cpp
CommitLineData
f9bf01c6 1/*
ed1e77d3 2 * Copyright (C) 2012, 2013, 2015 Apple Inc. All rights reserved.
f9bf01c6
A
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
93a37866 27#include "Disassembler.h"
f9bf01c6 28
93a37866
A
29#include "MacroAssemblerCodeRef.h"
30#include <wtf/DataLog.h>
ed1e77d3
A
31#include <wtf/Deque.h>
32#include <wtf/NeverDestroyed.h>
33#include <wtf/StringPrintStream.h>
34#include <wtf/Threading.h>
35#include <wtf/ThreadingPrimitives.h>
f9bf01c6
A
36
37namespace JSC {
38
81345200 39void disassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out, InstructionSubsetHint subsetHint)
f9bf01c6 40{
81345200 41 if (tryToDisassemble(codePtr, size, prefix, out, subsetHint))
93a37866 42 return;
6fe7ccc8 43
93a37866 44 out.printf("%sdisassembly not available for range %p...%p\n", prefix, codePtr.executableAddress(), static_cast<char*>(codePtr.executableAddress()) + size);
f9bf01c6
A
45}
46
ed1e77d3
A
47namespace {
48
49// This is really a struct, except that it should be a class because that's what the WTF_* macros
50// expect.
51class DisassemblyTask {
52 WTF_MAKE_NONCOPYABLE(DisassemblyTask);
53 WTF_MAKE_FAST_ALLOCATED;
54public:
55 DisassemblyTask()
56 {
57 }
58
59 ~DisassemblyTask()
60 {
61 if (header)
62 free(header); // free() because it would have been copied by strdup.
63 }
64
65 char* header { nullptr };
66 MacroAssemblerCodeRef codeRef;
67 size_t size { 0 };
68 const char* prefix { nullptr };
69 InstructionSubsetHint subsetHint { MacroAssemblerSubset };
70};
71
72class AsynchronousDisassembler {
73public:
74 AsynchronousDisassembler()
75 {
76 createThread("Asynchronous Disassembler", [&] () { run(); });
77 }
78
79 void enqueue(std::unique_ptr<DisassemblyTask> task)
80 {
81 MutexLocker locker(m_lock);
82 m_queue.append(WTF::move(task));
83 m_condition.broadcast();
84 }
85
86 void waitUntilEmpty()
87 {
88 MutexLocker locker(m_lock);
89 while (!m_queue.isEmpty() || m_working)
90 m_condition.wait(m_lock);
91 }
92
93private:
94 NO_RETURN void run()
95 {
96 for (;;) {
97 std::unique_ptr<DisassemblyTask> task;
98 {
99 MutexLocker locker(m_lock);
100 m_working = false;
101 m_condition.broadcast();
102 while (m_queue.isEmpty())
103 m_condition.wait(m_lock);
104 task = m_queue.takeFirst();
105 m_working = true;
106 }
107
108 dataLog(task->header);
109 disassemble(
110 task->codeRef.code(), task->size, task->prefix, WTF::dataFile(),
111 task->subsetHint);
112 }
113 }
114
115 Mutex m_lock;
116 ThreadCondition m_condition;
117 Deque<std::unique_ptr<DisassemblyTask>> m_queue;
118 bool m_working { false };
119};
120
121bool hadAnyAsynchronousDisassembly = false;
122
123AsynchronousDisassembler& asynchronousDisassembler()
124{
125 static NeverDestroyed<AsynchronousDisassembler> disassembler;
126 hadAnyAsynchronousDisassembly = true;
127 return disassembler.get();
128}
129
130} // anonymous namespace
131
132void disassembleAsynchronously(
133 const CString& header, const MacroAssemblerCodeRef& codeRef, size_t size, const char* prefix,
134 InstructionSubsetHint subsetHint)
135{
136 std::unique_ptr<DisassemblyTask> task = std::make_unique<DisassemblyTask>();
137 task->header = strdup(header.data()); // Yuck! We need this because CString does racy refcounting.
138 task->codeRef = codeRef;
139 task->size = size;
140 task->prefix = prefix;
141 task->subsetHint = subsetHint;
142
143 asynchronousDisassembler().enqueue(WTF::move(task));
144}
145
146void waitForAsynchronousDisassembly()
147{
148 if (!hadAnyAsynchronousDisassembly)
149 return;
150
151 asynchronousDisassembler().waitUntilEmpty();
152}
153
6fe7ccc8 154} // namespace JSC
f9bf01c6 155