Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Side by Side Diff: src/crankshaft-thread.cc

Issue 10417010: Run Crankshaft on a separate thread. (Closed) Base URL: https://chromiumcodereview.appspot.com/10387157
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include "crankshaft-thread.h"
29
30 #include <set>
31
32 #include "debug.h"
33 #include "flags.h"
34 #include "lithium.h"
35 #include "v8threads.h"
36
37 namespace v8 {
38 namespace internal {
39
40
41 static void FreeDeletedIsolates(std::set<Isolate*> *deleted_isolates) {
42 for (std::set<Isolate*>::iterator i = deleted_isolates->begin(),
danno 2012/05/22 10:32:19 We don't use STL in V8, you'll have to find anothe
43 e = deleted_isolates->end();
44 i != e; ++i)
45 // We simply call free on the Isolates since the destructor for
46 // each of these instances has already been called.
47 free(*i);
48 }
49
50 void CrankshaftThread::WorkerThread::Run() {
51 std::set<i::Isolate *> deleted_isolates;
52 // The loop lock is given up at two sites. For this reason,
53 // successfully acquiring the lock from another thread guarantees
54 // that this thread is one of those two places.
55 loop_lock_->Lock();
56
57 while (true) {
58 // Whenever loop_lock_ is unlocked isolate_ is set to the Isolate
59 // currently being processed.
60 Acquire_Store(&isolate_, static_cast<AtomicWord>(0));
61
62 loop_lock_->Unlock();
danno 2012/05/22 10:32:19 I don't think you need the loop lock at all. Just
sanjoy 2012/05/22 11:38:55 I needed a place in the code where I'm assured iso
63 queue_semaphore_->Wait();
64 loop_lock_->Lock();
65
66 if (Release_Load(&stop_loop_)) {
67 FreeDeletedIsolates(&deleted_isolates);
68 // We need to unlock the loop lock since it is possible the
69 // thread stopping the worker thread set stop_loop_ after we
70 // locked loop_lock_ and is currently waiting on loop_lock_.
71 loop_lock_->Unlock();
72 return;
73 }
74
75 WorkElement w_element;
76 work_queue_.Dequeue(&w_element);
77
78 if (!w_element.dummy) {
79 i::Isolate* isolate = w_element.isolate;
80 if (deleted_isolates.find(isolate) != deleted_isolates.end())
81 continue;
82
83 Acquire_Store(&isolate_, reinterpret_cast<AtomicWord>(isolate));
danno 2012/05/22 10:32:19 I think you can get rid of both isolate_ and loop_
84 loop_lock_->Unlock();
85
86 {
87 // Can't use the Locker object here since we can't unlock if
88 // this isolate has been marked for deletion.
89 isolate->thread_manager()->Lock();
90 loop_lock_->Lock();
91
92 bool to_stop = Release_Load(&stop_loop_);
93
94 if (isolate->to_delete()) {
95 // We don't delete the Isolate lest the same memory gets
96 // allocated to another Isolate and the crankshaft thread
97 // gets confused. We still invoke the destructor to free
98 // the Isolate's members.
99 isolate->~Isolate();
danno 2012/05/22 10:32:19 What happens if two functions from the isolate are
100 deleted_isolates.insert(isolate);
101 if (to_stop)
102 return;
103 else
104 continue;
105 }
106
107 if (to_stop) {
108 FreeDeletedIsolates(&deleted_isolates);
danno 2012/05/22 10:32:19 How big are the isolates? Can we really afford to
109 loop_lock_->Unlock();
110 return;
111 }
112
113 bool top_level = true;
114 if (isolate->thread_manager()->RestoreThread()) {
115 top_level = false;
116 } else {
117 i::ExecutionAccess access(isolate);
118 isolate->stack_guard()->ClearThread(access);
119 isolate->stack_guard()->InitThread(access);
120 }
danno 2012/05/22 10:32:19 Don't you have to do this after the Enter to ensur
sanjoy 2012/05/22 11:38:55 I don't think so, I've already acquired the isolat
121
122 isolate->Enter();
123 {
124 HandleScope scope(isolate);
125 if (!w_element.function->IsOptimized()) {
126 i::Handle<i::Context> ctx(w_element.function->context());
127 isolate->handle_scope_implementer()->EnterContext(ctx);
128 isolate->handle_scope_implementer()->SaveContext(
129 isolate->context());
130 isolate->set_context(*ctx);
131
132 while (CompileJSFunction(isolate,
danno 2012/05/22 10:32:19 This won't work. You will have to create a handle
133 w_element.function)->IsFailure()) {
134 }
135
136 isolate->handle_scope_implementer()->LeaveLastContext();
137 i::Context* last_context =
138 isolate->handle_scope_implementer()->RestoreContext();
139 isolate->set_context(last_context);
140 isolate->set_context_exit_happened(true);
141 #ifdef DEBUG
142 functions_compiled_++;
143 #endif
144 }
145 }
146 isolate->global_handles()->Destroy(
147 reinterpret_cast<Object **>(w_element.function.location()));
148 isolate->Exit();
149
150 if (top_level)
151 isolate->thread_manager()->ArchiveThread();
152 else
153 isolate->thread_manager()->FreeThreadResources();
154
155 isolate->thread_manager()->Unlock();
156 }
157 }
158 }
159 }
160
161
162 void CrankshaftThread::WorkerThread::AddElement(const WorkElement &we) {
163 {
164 // We need the queue_lock_ since UnboundQueue is single producer /
165 // single consumer, while we have a multiple producer / single
166 // consumer situation here.
167 ScopedLock lock(queue_lock_);
168 work_queue_.Enqueue(we);
169 }
170 queue_semaphore_->Signal();
171 }
172
173
174 void CrankshaftThread::WorkerThread::StopThread() {
175 ASSERT(!stop_loop_);
176 Acquire_Store(&stop_loop_, static_cast<AtomicWord>(true));
177
178 {
179 ScopedLock lock(loop_lock_);
180 // Once we have the loop_lock_, we're assured that the worker
181 // thread is in one of the two sites where it gives it up.
182 i::Isolate *isolate =
183 reinterpret_cast<i::Isolate *>(NoBarrier_Load(&isolate_));
184
185 if (!isolate) {
186 // If isolate is NULL, we the worker thread it is possible the
187 // worker thread waiting on queue_semaphore_. Insert a dummy
188 // element to get it past the semaphore.
189 WorkElement element;
190 element.dummy = true;
191 AddElement(element);
danno 2012/05/22 10:32:19 Why do you need the explicit dummy element? You se
sanjoy 2012/05/22 11:38:55 Right, it is not needed. I'll remove it in the ne
192 } else if (isolate->thread_manager() &&
193 isolate->thread_manager()->IsLockedByCurrentThread()) {
194 isolate->thread_manager()->ArchiveThread();
195 isolate->thread_manager()->Unlock();
196 } else {
197 ASSERT(!isolate->thread_manager()->IsLockedByCurrentThread() ||
198 isolate->to_delete());
199 }
200 }
201
202 Join();
203
204 ElementsAccessor::TearDown();
danno 2012/05/22 10:32:19 Why are these here? Shouldn't they be in V8 teardo
205 LOperand::TearDownCaches();
206 RegisteredExtension::UnregisterAll();
207
208 #ifdef DEBUG
209 PrintF(stderr, " > %d functions compiled concurrently!\n",
210 functions_compiled_);
danno 2012/05/22 10:32:19 use v8-counters for this
211 #endif
212 }
213
214
215 void CrankshaftThread::StartThread() {
216 ASSERT(FLAG_concurrent_crankshaft);
217 ASSERT(!worker_instance_);
218
219 #ifdef DEBUG
220 PrintF(stderr, " > Starting Crankshaft Thread\n");
danno 2012/05/22 10:32:19 Remove the print, please
221 #endif
danno 2012/05/22 10:32:19 Remove the print, please
222
223 Thread::Options o("CShaftThread");
224 worker_instance_ = new WorkerThread(o);
225 worker_instance_->Start();
226 }
227
228
229 void CrankshaftThread::StopThread() {
230 ASSERT(FLAG_concurrent_crankshaft);
231 ASSERT(worker_instance_);
232
233 worker_instance_->StopThread();
234 }
235
236
237 void CrankshaftThread::AddJob(Isolate *isolate,
238 i::Handle<JSFunction> function) {
239 ASSERT(FLAG_concurrent_crankshaft);
240 ASSERT(worker_instance_);
241 ASSERT(isolate->thread_manager()->IsLockedByCurrentThread());
242
243 WorkElement we;
244 we.function = function;
245 we.isolate = isolate;
246
247 worker_instance_->AddElement(we);
248
249 if (!isolate->debugger()->IsDebuggerActive()) {
250 Unlocker unlock(reinterpret_cast<v8::Isolate *>(isolate));
251 Thread::YieldCPU();
252 }
253 }
254
255
256 CrankshaftThread::WorkerThread *CrankshaftThread::worker_instance_ = NULL;
257
258 } } // namespace v8::internal
259
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698