]> git.saurik.com Git - apple/javascriptcore.git/blob - disassembler/Disassembler.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / disassembler / Disassembler.cpp
1 /*
2 * Copyright (C) 2012, 2013, 2015 Apple Inc. All rights reserved.
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"
27 #include "Disassembler.h"
28
29 #include "MacroAssemblerCodeRef.h"
30 #include <wtf/DataLog.h>
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>
36
37 namespace JSC {
38
39 void disassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out, InstructionSubsetHint subsetHint)
40 {
41 if (tryToDisassemble(codePtr, size, prefix, out, subsetHint))
42 return;
43
44 out.printf("%sdisassembly not available for range %p...%p\n", prefix, codePtr.executableAddress(), static_cast<char*>(codePtr.executableAddress()) + size);
45 }
46
47 namespace {
48
49 // This is really a struct, except that it should be a class because that's what the WTF_* macros
50 // expect.
51 class DisassemblyTask {
52 WTF_MAKE_NONCOPYABLE(DisassemblyTask);
53 WTF_MAKE_FAST_ALLOCATED;
54 public:
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
72 class AsynchronousDisassembler {
73 public:
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
93 private:
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
121 bool hadAnyAsynchronousDisassembly = false;
122
123 AsynchronousDisassembler& asynchronousDisassembler()
124 {
125 static NeverDestroyed<AsynchronousDisassembler> disassembler;
126 hadAnyAsynchronousDisassembly = true;
127 return disassembler.get();
128 }
129
130 } // anonymous namespace
131
132 void 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
146 void waitForAsynchronousDisassembly()
147 {
148 if (!hadAnyAsynchronousDisassembly)
149 return;
150
151 asynchronousDisassembler().waitUntilEmpty();
152 }
153
154 } // namespace JSC
155