blob: 8a30e7924fb9215c278f1467ba1d99b35fc5e54a [file] [log] [blame]
Ben Murdoch8b112d22011-06-08 16:22:53 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Block44f0eee2011-05-26 01:26:41 +01002// 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 <stdlib.h>
29
30#include "v8.h"
31
32#include "ast.h"
33#include "bootstrapper.h"
34#include "codegen.h"
35#include "compilation-cache.h"
36#include "debug.h"
37#include "deoptimizer.h"
38#include "heap-profiler.h"
39#include "hydrogen.h"
40#include "isolate.h"
41#include "lithium-allocator.h"
42#include "log.h"
Ben Murdoch257744e2011-11-30 15:57:28 +000043#include "messages.h"
Steve Block44f0eee2011-05-26 01:26:41 +010044#include "regexp-stack.h"
45#include "runtime-profiler.h"
46#include "scanner.h"
47#include "scopeinfo.h"
48#include "serialize.h"
49#include "simulator.h"
50#include "spaces.h"
51#include "stub-cache.h"
52#include "version.h"
Ben Murdoch257744e2011-11-30 15:57:28 +000053#include "vm-state-inl.h"
Steve Block44f0eee2011-05-26 01:26:41 +010054
55
56namespace v8 {
57namespace internal {
58
Ben Murdoch8b112d22011-06-08 16:22:53 +010059Atomic32 ThreadId::highest_thread_id_ = 0;
60
61int ThreadId::AllocateThreadId() {
62 int new_id = NoBarrier_AtomicIncrement(&highest_thread_id_, 1);
63 return new_id;
64}
65
Ben Murdoch257744e2011-11-30 15:57:28 +000066
Ben Murdoch8b112d22011-06-08 16:22:53 +010067int ThreadId::GetCurrentThreadId() {
68 int thread_id = Thread::GetThreadLocalInt(Isolate::thread_id_key_);
69 if (thread_id == 0) {
70 thread_id = AllocateThreadId();
71 Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id);
72 }
73 return thread_id;
74}
Steve Block44f0eee2011-05-26 01:26:41 +010075
Ben Murdoch6d7cb002011-08-04 19:25:22 +010076
Ben Murdoch257744e2011-11-30 15:57:28 +000077ThreadLocalTop::ThreadLocalTop() {
78 InitializeInternal();
79}
80
81
82void ThreadLocalTop::InitializeInternal() {
83 c_entry_fp_ = 0;
84 handler_ = 0;
85#ifdef USE_SIMULATOR
86 simulator_ = NULL;
87#endif
Ben Murdoch257744e2011-11-30 15:57:28 +000088 js_entry_sp_ = NULL;
89 external_callback_ = NULL;
Ben Murdoch257744e2011-11-30 15:57:28 +000090 current_vm_state_ = EXTERNAL;
Ben Murdoch257744e2011-11-30 15:57:28 +000091 try_catch_handler_address_ = NULL;
92 context_ = NULL;
93 thread_id_ = ThreadId::Invalid();
94 external_caught_exception_ = false;
95 failed_access_check_callback_ = NULL;
96 save_context_ = NULL;
97 catcher_ = NULL;
98}
99
100
101void ThreadLocalTop::Initialize() {
102 InitializeInternal();
103#ifdef USE_SIMULATOR
104#ifdef V8_TARGET_ARCH_ARM
105 simulator_ = Simulator::current(isolate_);
106#elif V8_TARGET_ARCH_MIPS
107 simulator_ = Simulator::current(isolate_);
108#endif
109#endif
110 thread_id_ = ThreadId::Current();
111}
112
113
114v8::TryCatch* ThreadLocalTop::TryCatchHandler() {
115 return TRY_CATCH_FROM_ADDRESS(try_catch_handler_address());
116}
117
118
Steve Block44f0eee2011-05-26 01:26:41 +0100119// Create a dummy thread that will wait forever on a semaphore. The only
120// purpose for this thread is to have some stack area to save essential data
121// into for use by a stacks only core dump (aka minidump).
122class PreallocatedMemoryThread: public Thread {
123 public:
124 char* data() {
125 if (data_ready_semaphore_ != NULL) {
126 // Initial access is guarded until the data has been published.
127 data_ready_semaphore_->Wait();
128 delete data_ready_semaphore_;
129 data_ready_semaphore_ = NULL;
130 }
131 return data_;
132 }
133
134 unsigned length() {
135 if (data_ready_semaphore_ != NULL) {
136 // Initial access is guarded until the data has been published.
137 data_ready_semaphore_->Wait();
138 delete data_ready_semaphore_;
139 data_ready_semaphore_ = NULL;
140 }
141 return length_;
142 }
143
144 // Stop the PreallocatedMemoryThread and release its resources.
145 void StopThread() {
146 keep_running_ = false;
147 wait_for_ever_semaphore_->Signal();
148
149 // Wait for the thread to terminate.
150 Join();
151
152 if (data_ready_semaphore_ != NULL) {
153 delete data_ready_semaphore_;
154 data_ready_semaphore_ = NULL;
155 }
156
157 delete wait_for_ever_semaphore_;
158 wait_for_ever_semaphore_ = NULL;
159 }
160
161 protected:
162 // When the thread starts running it will allocate a fixed number of bytes
163 // on the stack and publish the location of this memory for others to use.
164 void Run() {
165 EmbeddedVector<char, 15 * 1024> local_buffer;
166
167 // Initialize the buffer with a known good value.
168 OS::StrNCpy(local_buffer, "Trace data was not generated.\n",
169 local_buffer.length());
170
171 // Publish the local buffer and signal its availability.
172 data_ = local_buffer.start();
173 length_ = local_buffer.length();
174 data_ready_semaphore_->Signal();
175
176 while (keep_running_) {
177 // This thread will wait here until the end of time.
178 wait_for_ever_semaphore_->Wait();
179 }
180
181 // Make sure we access the buffer after the wait to remove all possibility
182 // of it being optimized away.
183 OS::StrNCpy(local_buffer, "PreallocatedMemoryThread shutting down.\n",
184 local_buffer.length());
185 }
186
187
188 private:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000189 PreallocatedMemoryThread()
190 : Thread("v8:PreallocMem"),
Steve Block44f0eee2011-05-26 01:26:41 +0100191 keep_running_(true),
192 wait_for_ever_semaphore_(OS::CreateSemaphore(0)),
193 data_ready_semaphore_(OS::CreateSemaphore(0)),
194 data_(NULL),
195 length_(0) {
196 }
197
198 // Used to make sure that the thread keeps looping even for spurious wakeups.
199 bool keep_running_;
200
201 // This semaphore is used by the PreallocatedMemoryThread to wait for ever.
202 Semaphore* wait_for_ever_semaphore_;
203 // Semaphore to signal that the data has been initialized.
204 Semaphore* data_ready_semaphore_;
205
206 // Location and size of the preallocated memory block.
207 char* data_;
208 unsigned length_;
209
210 friend class Isolate;
211
212 DISALLOW_COPY_AND_ASSIGN(PreallocatedMemoryThread);
213};
214
215
216void Isolate::PreallocatedMemoryThreadStart() {
217 if (preallocated_memory_thread_ != NULL) return;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000218 preallocated_memory_thread_ = new PreallocatedMemoryThread();
Steve Block44f0eee2011-05-26 01:26:41 +0100219 preallocated_memory_thread_->Start();
220}
221
222
223void Isolate::PreallocatedMemoryThreadStop() {
224 if (preallocated_memory_thread_ == NULL) return;
225 preallocated_memory_thread_->StopThread();
226 // Done with the thread entirely.
227 delete preallocated_memory_thread_;
228 preallocated_memory_thread_ = NULL;
229}
230
231
232void Isolate::PreallocatedStorageInit(size_t size) {
233 ASSERT(free_list_.next_ == &free_list_);
234 ASSERT(free_list_.previous_ == &free_list_);
235 PreallocatedStorage* free_chunk =
236 reinterpret_cast<PreallocatedStorage*>(new char[size]);
237 free_list_.next_ = free_list_.previous_ = free_chunk;
238 free_chunk->next_ = free_chunk->previous_ = &free_list_;
239 free_chunk->size_ = size - sizeof(PreallocatedStorage);
240 preallocated_storage_preallocated_ = true;
241}
242
243
244void* Isolate::PreallocatedStorageNew(size_t size) {
245 if (!preallocated_storage_preallocated_) {
246 return FreeStoreAllocationPolicy::New(size);
247 }
248 ASSERT(free_list_.next_ != &free_list_);
249 ASSERT(free_list_.previous_ != &free_list_);
250
251 size = (size + kPointerSize - 1) & ~(kPointerSize - 1);
252 // Search for exact fit.
253 for (PreallocatedStorage* storage = free_list_.next_;
254 storage != &free_list_;
255 storage = storage->next_) {
256 if (storage->size_ == size) {
257 storage->Unlink();
258 storage->LinkTo(&in_use_list_);
259 return reinterpret_cast<void*>(storage + 1);
260 }
261 }
262 // Search for first fit.
263 for (PreallocatedStorage* storage = free_list_.next_;
264 storage != &free_list_;
265 storage = storage->next_) {
266 if (storage->size_ >= size + sizeof(PreallocatedStorage)) {
267 storage->Unlink();
268 storage->LinkTo(&in_use_list_);
269 PreallocatedStorage* left_over =
270 reinterpret_cast<PreallocatedStorage*>(
271 reinterpret_cast<char*>(storage + 1) + size);
272 left_over->size_ = storage->size_ - size - sizeof(PreallocatedStorage);
273 ASSERT(size + left_over->size_ + sizeof(PreallocatedStorage) ==
274 storage->size_);
275 storage->size_ = size;
276 left_over->LinkTo(&free_list_);
277 return reinterpret_cast<void*>(storage + 1);
278 }
279 }
280 // Allocation failure.
281 ASSERT(false);
282 return NULL;
283}
284
285
286// We don't attempt to coalesce.
287void Isolate::PreallocatedStorageDelete(void* p) {
288 if (p == NULL) {
289 return;
290 }
291 if (!preallocated_storage_preallocated_) {
292 FreeStoreAllocationPolicy::Delete(p);
293 return;
294 }
295 PreallocatedStorage* storage = reinterpret_cast<PreallocatedStorage*>(p) - 1;
296 ASSERT(storage->next_->previous_ == storage);
297 ASSERT(storage->previous_->next_ == storage);
298 storage->Unlink();
299 storage->LinkTo(&free_list_);
300}
301
302
303Isolate* Isolate::default_isolate_ = NULL;
304Thread::LocalStorageKey Isolate::isolate_key_;
305Thread::LocalStorageKey Isolate::thread_id_key_;
306Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
307Mutex* Isolate::process_wide_mutex_ = OS::CreateMutex();
308Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL;
Steve Block44f0eee2011-05-26 01:26:41 +0100309
310
311class IsolateInitializer {
312 public:
313 IsolateInitializer() {
314 Isolate::EnsureDefaultIsolate();
315 }
316};
317
318static IsolateInitializer* EnsureDefaultIsolateAllocated() {
319 // TODO(isolates): Use the system threading API to do this once?
320 static IsolateInitializer static_initializer;
321 return &static_initializer;
322}
323
324// This variable only needed to trigger static intialization.
325static IsolateInitializer* static_initializer = EnsureDefaultIsolateAllocated();
326
327
Ben Murdoch8b112d22011-06-08 16:22:53 +0100328
Steve Block44f0eee2011-05-26 01:26:41 +0100329
330
331Isolate::PerIsolateThreadData* Isolate::AllocatePerIsolateThreadData(
332 ThreadId thread_id) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100333 ASSERT(!thread_id.Equals(ThreadId::Invalid()));
Steve Block44f0eee2011-05-26 01:26:41 +0100334 PerIsolateThreadData* per_thread = new PerIsolateThreadData(this, thread_id);
335 {
336 ScopedLock lock(process_wide_mutex_);
337 ASSERT(thread_data_table_->Lookup(this, thread_id) == NULL);
338 thread_data_table_->Insert(per_thread);
339 ASSERT(thread_data_table_->Lookup(this, thread_id) == per_thread);
340 }
341 return per_thread;
342}
343
344
345Isolate::PerIsolateThreadData*
346 Isolate::FindOrAllocatePerThreadDataForThisThread() {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100347 ThreadId thread_id = ThreadId::Current();
Steve Block44f0eee2011-05-26 01:26:41 +0100348 PerIsolateThreadData* per_thread = NULL;
349 {
350 ScopedLock lock(process_wide_mutex_);
351 per_thread = thread_data_table_->Lookup(this, thread_id);
352 if (per_thread == NULL) {
353 per_thread = AllocatePerIsolateThreadData(thread_id);
354 }
355 }
356 return per_thread;
357}
358
359
Ben Murdoch257744e2011-11-30 15:57:28 +0000360Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() {
361 ThreadId thread_id = ThreadId::Current();
362 PerIsolateThreadData* per_thread = NULL;
363 {
364 ScopedLock lock(process_wide_mutex_);
365 per_thread = thread_data_table_->Lookup(this, thread_id);
366 }
367 return per_thread;
368}
369
370
Steve Block44f0eee2011-05-26 01:26:41 +0100371void Isolate::EnsureDefaultIsolate() {
372 ScopedLock lock(process_wide_mutex_);
373 if (default_isolate_ == NULL) {
374 isolate_key_ = Thread::CreateThreadLocalKey();
375 thread_id_key_ = Thread::CreateThreadLocalKey();
376 per_isolate_thread_data_key_ = Thread::CreateThreadLocalKey();
377 thread_data_table_ = new Isolate::ThreadDataTable();
378 default_isolate_ = new Isolate();
379 }
380 // Can't use SetIsolateThreadLocals(default_isolate_, NULL) here
381 // becase a non-null thread data may be already set.
Ben Murdoch257744e2011-11-30 15:57:28 +0000382 if (Thread::GetThreadLocal(isolate_key_) == NULL) {
383 Thread::SetThreadLocal(isolate_key_, default_isolate_);
384 }
385 CHECK(default_isolate_->PreInit());
Steve Block44f0eee2011-05-26 01:26:41 +0100386}
387
388
Ben Murdoch257744e2011-11-30 15:57:28 +0000389#ifdef ENABLE_DEBUGGER_SUPPORT
Steve Block44f0eee2011-05-26 01:26:41 +0100390Debugger* Isolate::GetDefaultIsolateDebugger() {
391 EnsureDefaultIsolate();
392 return default_isolate_->debugger();
393}
Ben Murdoch257744e2011-11-30 15:57:28 +0000394#endif
Steve Block44f0eee2011-05-26 01:26:41 +0100395
396
397StackGuard* Isolate::GetDefaultIsolateStackGuard() {
398 EnsureDefaultIsolate();
399 return default_isolate_->stack_guard();
400}
401
402
403void Isolate::EnterDefaultIsolate() {
404 EnsureDefaultIsolate();
405 ASSERT(default_isolate_ != NULL);
406
407 PerIsolateThreadData* data = CurrentPerIsolateThreadData();
408 // If not yet in default isolate - enter it.
409 if (data == NULL || data->isolate() != default_isolate_) {
410 default_isolate_->Enter();
411 }
412}
413
414
415Isolate* Isolate::GetDefaultIsolateForLocking() {
416 EnsureDefaultIsolate();
417 return default_isolate_;
418}
419
420
Ben Murdoch257744e2011-11-30 15:57:28 +0000421Address Isolate::get_address_from_id(Isolate::AddressId id) {
422 return isolate_addresses_[id];
423}
424
425
426char* Isolate::Iterate(ObjectVisitor* v, char* thread_storage) {
427 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage);
428 Iterate(v, thread);
429 return thread_storage + sizeof(ThreadLocalTop);
430}
431
432
433void Isolate::IterateThread(ThreadVisitor* v) {
434 v->VisitThread(this, thread_local_top());
435}
436
437
438void Isolate::IterateThread(ThreadVisitor* v, char* t) {
439 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t);
440 v->VisitThread(this, thread);
441}
442
443
444void Isolate::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
445 // Visit the roots from the top for a given thread.
446 Object* pending;
447 // The pending exception can sometimes be a failure. We can't show
448 // that to the GC, which only understands objects.
449 if (thread->pending_exception_->ToObject(&pending)) {
450 v->VisitPointer(&pending);
451 thread->pending_exception_ = pending; // In case GC updated it.
452 }
453 v->VisitPointer(&(thread->pending_message_obj_));
454 v->VisitPointer(BitCast<Object**>(&(thread->pending_message_script_)));
455 v->VisitPointer(BitCast<Object**>(&(thread->context_)));
456 Object* scheduled;
457 if (thread->scheduled_exception_->ToObject(&scheduled)) {
458 v->VisitPointer(&scheduled);
459 thread->scheduled_exception_ = scheduled;
460 }
461
462 for (v8::TryCatch* block = thread->TryCatchHandler();
463 block != NULL;
464 block = TRY_CATCH_FROM_ADDRESS(block->next_)) {
465 v->VisitPointer(BitCast<Object**>(&(block->exception_)));
466 v->VisitPointer(BitCast<Object**>(&(block->message_)));
467 }
468
469 // Iterate over pointers on native execution stack.
470 for (StackFrameIterator it(this, thread); !it.done(); it.Advance()) {
471 it.frame()->Iterate(v);
472 }
473}
474
475
476void Isolate::Iterate(ObjectVisitor* v) {
477 ThreadLocalTop* current_t = thread_local_top();
478 Iterate(v, current_t);
479}
480
481
482void Isolate::RegisterTryCatchHandler(v8::TryCatch* that) {
483 // The ARM simulator has a separate JS stack. We therefore register
484 // the C++ try catch handler with the simulator and get back an
485 // address that can be used for comparisons with addresses into the
486 // JS stack. When running without the simulator, the address
487 // returned will be the address of the C++ try catch handler itself.
488 Address address = reinterpret_cast<Address>(
489 SimulatorStack::RegisterCTryCatch(reinterpret_cast<uintptr_t>(that)));
490 thread_local_top()->set_try_catch_handler_address(address);
491}
492
493
494void Isolate::UnregisterTryCatchHandler(v8::TryCatch* that) {
495 ASSERT(thread_local_top()->TryCatchHandler() == that);
496 thread_local_top()->set_try_catch_handler_address(
497 reinterpret_cast<Address>(that->next_));
498 thread_local_top()->catcher_ = NULL;
499 SimulatorStack::UnregisterCTryCatch();
500}
501
502
503Handle<String> Isolate::StackTraceString() {
504 if (stack_trace_nesting_level_ == 0) {
505 stack_trace_nesting_level_++;
506 HeapStringAllocator allocator;
507 StringStream::ClearMentionedObjectCache();
508 StringStream accumulator(&allocator);
509 incomplete_message_ = &accumulator;
510 PrintStack(&accumulator);
511 Handle<String> stack_trace = accumulator.ToString();
512 incomplete_message_ = NULL;
513 stack_trace_nesting_level_ = 0;
514 return stack_trace;
515 } else if (stack_trace_nesting_level_ == 1) {
516 stack_trace_nesting_level_++;
517 OS::PrintError(
518 "\n\nAttempt to print stack while printing stack (double fault)\n");
519 OS::PrintError(
520 "If you are lucky you may find a partial stack dump on stdout.\n\n");
521 incomplete_message_->OutputToStdOut();
522 return factory()->empty_symbol();
523 } else {
524 OS::Abort();
525 // Unreachable
526 return factory()->empty_symbol();
527 }
528}
529
530
531Handle<JSArray> Isolate::CaptureCurrentStackTrace(
532 int frame_limit, StackTrace::StackTraceOptions options) {
533 // Ensure no negative values.
534 int limit = Max(frame_limit, 0);
535 Handle<JSArray> stack_trace = factory()->NewJSArray(frame_limit);
536
537 Handle<String> column_key = factory()->LookupAsciiSymbol("column");
538 Handle<String> line_key = factory()->LookupAsciiSymbol("lineNumber");
539 Handle<String> script_key = factory()->LookupAsciiSymbol("scriptName");
540 Handle<String> name_or_source_url_key =
541 factory()->LookupAsciiSymbol("nameOrSourceURL");
542 Handle<String> script_name_or_source_url_key =
543 factory()->LookupAsciiSymbol("scriptNameOrSourceURL");
544 Handle<String> function_key = factory()->LookupAsciiSymbol("functionName");
545 Handle<String> eval_key = factory()->LookupAsciiSymbol("isEval");
546 Handle<String> constructor_key =
547 factory()->LookupAsciiSymbol("isConstructor");
548
549 StackTraceFrameIterator it(this);
550 int frames_seen = 0;
551 while (!it.done() && (frames_seen < limit)) {
552 JavaScriptFrame* frame = it.frame();
553 // Set initial size to the maximum inlining level + 1 for the outermost
554 // function.
555 List<FrameSummary> frames(Compiler::kMaxInliningLevels + 1);
556 frame->Summarize(&frames);
557 for (int i = frames.length() - 1; i >= 0 && frames_seen < limit; i--) {
558 // Create a JSObject to hold the information for the StackFrame.
559 Handle<JSObject> stackFrame = factory()->NewJSObject(object_function());
560
561 Handle<JSFunction> fun = frames[i].function();
562 Handle<Script> script(Script::cast(fun->shared()->script()));
563
564 if (options & StackTrace::kLineNumber) {
565 int script_line_offset = script->line_offset()->value();
566 int position = frames[i].code()->SourcePosition(frames[i].pc());
567 int line_number = GetScriptLineNumber(script, position);
568 // line_number is already shifted by the script_line_offset.
569 int relative_line_number = line_number - script_line_offset;
570 if (options & StackTrace::kColumnOffset && relative_line_number >= 0) {
571 Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
572 int start = (relative_line_number == 0) ? 0 :
573 Smi::cast(line_ends->get(relative_line_number - 1))->value() + 1;
574 int column_offset = position - start;
575 if (relative_line_number == 0) {
576 // For the case where the code is on the same line as the script
577 // tag.
578 column_offset += script->column_offset()->value();
579 }
580 SetLocalPropertyNoThrow(stackFrame, column_key,
581 Handle<Smi>(Smi::FromInt(column_offset + 1)));
582 }
583 SetLocalPropertyNoThrow(stackFrame, line_key,
584 Handle<Smi>(Smi::FromInt(line_number + 1)));
585 }
586
587 if (options & StackTrace::kScriptName) {
588 Handle<Object> script_name(script->name(), this);
589 SetLocalPropertyNoThrow(stackFrame, script_key, script_name);
590 }
591
592 if (options & StackTrace::kScriptNameOrSourceURL) {
593 Handle<Object> script_name(script->name(), this);
594 Handle<JSValue> script_wrapper = GetScriptWrapper(script);
595 Handle<Object> property = GetProperty(script_wrapper,
596 name_or_source_url_key);
597 ASSERT(property->IsJSFunction());
598 Handle<JSFunction> method = Handle<JSFunction>::cast(property);
599 bool caught_exception;
600 Handle<Object> result = Execution::TryCall(method, script_wrapper, 0,
601 NULL, &caught_exception);
602 if (caught_exception) {
603 result = factory()->undefined_value();
604 }
605 SetLocalPropertyNoThrow(stackFrame, script_name_or_source_url_key,
606 result);
607 }
608
609 if (options & StackTrace::kFunctionName) {
610 Handle<Object> fun_name(fun->shared()->name(), this);
611 if (fun_name->ToBoolean()->IsFalse()) {
612 fun_name = Handle<Object>(fun->shared()->inferred_name(), this);
613 }
614 SetLocalPropertyNoThrow(stackFrame, function_key, fun_name);
615 }
616
617 if (options & StackTrace::kIsEval) {
618 int type = Smi::cast(script->compilation_type())->value();
619 Handle<Object> is_eval = (type == Script::COMPILATION_TYPE_EVAL) ?
620 factory()->true_value() : factory()->false_value();
621 SetLocalPropertyNoThrow(stackFrame, eval_key, is_eval);
622 }
623
624 if (options & StackTrace::kIsConstructor) {
625 Handle<Object> is_constructor = (frames[i].is_constructor()) ?
626 factory()->true_value() : factory()->false_value();
627 SetLocalPropertyNoThrow(stackFrame, constructor_key, is_constructor);
628 }
629
630 FixedArray::cast(stack_trace->elements())->set(frames_seen, *stackFrame);
631 frames_seen++;
632 }
633 it.Advance();
634 }
635
636 stack_trace->set_length(Smi::FromInt(frames_seen));
637 return stack_trace;
638}
639
640
641void Isolate::PrintStack() {
642 if (stack_trace_nesting_level_ == 0) {
643 stack_trace_nesting_level_++;
644
645 StringAllocator* allocator;
646 if (preallocated_message_space_ == NULL) {
647 allocator = new HeapStringAllocator();
648 } else {
649 allocator = preallocated_message_space_;
650 }
651
652 StringStream::ClearMentionedObjectCache();
653 StringStream accumulator(allocator);
654 incomplete_message_ = &accumulator;
655 PrintStack(&accumulator);
656 accumulator.OutputToStdOut();
657 accumulator.Log();
658 incomplete_message_ = NULL;
659 stack_trace_nesting_level_ = 0;
660 if (preallocated_message_space_ == NULL) {
661 // Remove the HeapStringAllocator created above.
662 delete allocator;
663 }
664 } else if (stack_trace_nesting_level_ == 1) {
665 stack_trace_nesting_level_++;
666 OS::PrintError(
667 "\n\nAttempt to print stack while printing stack (double fault)\n");
668 OS::PrintError(
669 "If you are lucky you may find a partial stack dump on stdout.\n\n");
670 incomplete_message_->OutputToStdOut();
671 }
672}
673
674
675static void PrintFrames(StringStream* accumulator,
676 StackFrame::PrintMode mode) {
677 StackFrameIterator it;
678 for (int i = 0; !it.done(); it.Advance()) {
679 it.frame()->Print(accumulator, mode, i++);
680 }
681}
682
683
684void Isolate::PrintStack(StringStream* accumulator) {
685 if (!IsInitialized()) {
686 accumulator->Add(
687 "\n==== Stack trace is not available ==========================\n\n");
688 accumulator->Add(
689 "\n==== Isolate for the thread is not initialized =============\n\n");
690 return;
691 }
692 // The MentionedObjectCache is not GC-proof at the moment.
693 AssertNoAllocation nogc;
694 ASSERT(StringStream::IsMentionedObjectCacheClear());
695
696 // Avoid printing anything if there are no frames.
697 if (c_entry_fp(thread_local_top()) == 0) return;
698
699 accumulator->Add(
700 "\n==== Stack trace ============================================\n\n");
701 PrintFrames(accumulator, StackFrame::OVERVIEW);
702
703 accumulator->Add(
704 "\n==== Details ================================================\n\n");
705 PrintFrames(accumulator, StackFrame::DETAILS);
706
707 accumulator->PrintMentionedObjectCache();
708 accumulator->Add("=====================\n\n");
709}
710
711
712void Isolate::SetFailedAccessCheckCallback(
713 v8::FailedAccessCheckCallback callback) {
714 thread_local_top()->failed_access_check_callback_ = callback;
715}
716
717
718void Isolate::ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type) {
719 if (!thread_local_top()->failed_access_check_callback_) return;
720
721 ASSERT(receiver->IsAccessCheckNeeded());
722 ASSERT(context());
723
724 // Get the data object from access check info.
725 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
726 if (!constructor->shared()->IsApiFunction()) return;
727 Object* data_obj =
728 constructor->shared()->get_api_func_data()->access_check_info();
729 if (data_obj == heap_.undefined_value()) return;
730
731 HandleScope scope;
732 Handle<JSObject> receiver_handle(receiver);
733 Handle<Object> data(AccessCheckInfo::cast(data_obj)->data());
734 thread_local_top()->failed_access_check_callback_(
735 v8::Utils::ToLocal(receiver_handle),
736 type,
737 v8::Utils::ToLocal(data));
738}
739
740
741enum MayAccessDecision {
742 YES, NO, UNKNOWN
743};
744
745
746static MayAccessDecision MayAccessPreCheck(Isolate* isolate,
747 JSObject* receiver,
748 v8::AccessType type) {
749 // During bootstrapping, callback functions are not enabled yet.
750 if (isolate->bootstrapper()->IsActive()) return YES;
751
752 if (receiver->IsJSGlobalProxy()) {
753 Object* receiver_context = JSGlobalProxy::cast(receiver)->context();
754 if (!receiver_context->IsContext()) return NO;
755
756 // Get the global context of current top context.
757 // avoid using Isolate::global_context() because it uses Handle.
758 Context* global_context = isolate->context()->global()->global_context();
759 if (receiver_context == global_context) return YES;
760
761 if (Context::cast(receiver_context)->security_token() ==
762 global_context->security_token())
763 return YES;
764 }
765
766 return UNKNOWN;
767}
768
769
770bool Isolate::MayNamedAccess(JSObject* receiver, Object* key,
771 v8::AccessType type) {
772 ASSERT(receiver->IsAccessCheckNeeded());
773
774 // The callers of this method are not expecting a GC.
775 AssertNoAllocation no_gc;
776
777 // Skip checks for hidden properties access. Note, we do not
778 // require existence of a context in this case.
779 if (key == heap_.hidden_symbol()) return true;
780
781 // Check for compatibility between the security tokens in the
782 // current lexical context and the accessed object.
783 ASSERT(context());
784
785 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type);
786 if (decision != UNKNOWN) return decision == YES;
787
788 // Get named access check callback
789 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
790 if (!constructor->shared()->IsApiFunction()) return false;
791
792 Object* data_obj =
793 constructor->shared()->get_api_func_data()->access_check_info();
794 if (data_obj == heap_.undefined_value()) return false;
795
796 Object* fun_obj = AccessCheckInfo::cast(data_obj)->named_callback();
797 v8::NamedSecurityCallback callback =
798 v8::ToCData<v8::NamedSecurityCallback>(fun_obj);
799
800 if (!callback) return false;
801
802 HandleScope scope(this);
803 Handle<JSObject> receiver_handle(receiver, this);
804 Handle<Object> key_handle(key, this);
805 Handle<Object> data(AccessCheckInfo::cast(data_obj)->data(), this);
806 LOG(this, ApiNamedSecurityCheck(key));
807 bool result = false;
808 {
809 // Leaving JavaScript.
810 VMState state(this, EXTERNAL);
811 result = callback(v8::Utils::ToLocal(receiver_handle),
812 v8::Utils::ToLocal(key_handle),
813 type,
814 v8::Utils::ToLocal(data));
815 }
816 return result;
817}
818
819
820bool Isolate::MayIndexedAccess(JSObject* receiver,
821 uint32_t index,
822 v8::AccessType type) {
823 ASSERT(receiver->IsAccessCheckNeeded());
824 // Check for compatibility between the security tokens in the
825 // current lexical context and the accessed object.
826 ASSERT(context());
827
828 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type);
829 if (decision != UNKNOWN) return decision == YES;
830
831 // Get indexed access check callback
832 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
833 if (!constructor->shared()->IsApiFunction()) return false;
834
835 Object* data_obj =
836 constructor->shared()->get_api_func_data()->access_check_info();
837 if (data_obj == heap_.undefined_value()) return false;
838
839 Object* fun_obj = AccessCheckInfo::cast(data_obj)->indexed_callback();
840 v8::IndexedSecurityCallback callback =
841 v8::ToCData<v8::IndexedSecurityCallback>(fun_obj);
842
843 if (!callback) return false;
844
845 HandleScope scope(this);
846 Handle<JSObject> receiver_handle(receiver, this);
847 Handle<Object> data(AccessCheckInfo::cast(data_obj)->data(), this);
848 LOG(this, ApiIndexedSecurityCheck(index));
849 bool result = false;
850 {
851 // Leaving JavaScript.
852 VMState state(this, EXTERNAL);
853 result = callback(v8::Utils::ToLocal(receiver_handle),
854 index,
855 type,
856 v8::Utils::ToLocal(data));
857 }
858 return result;
859}
860
861
862const char* const Isolate::kStackOverflowMessage =
863 "Uncaught RangeError: Maximum call stack size exceeded";
864
865
866Failure* Isolate::StackOverflow() {
867 HandleScope scope;
868 Handle<String> key = factory()->stack_overflow_symbol();
869 Handle<JSObject> boilerplate =
870 Handle<JSObject>::cast(GetProperty(js_builtins_object(), key));
871 Handle<Object> exception = Copy(boilerplate);
872 // TODO(1240995): To avoid having to call JavaScript code to compute
873 // the message for stack overflow exceptions which is very likely to
874 // double fault with another stack overflow exception, we use a
875 // precomputed message.
876 DoThrow(*exception, NULL);
877 return Failure::Exception();
878}
879
880
881Failure* Isolate::TerminateExecution() {
882 DoThrow(heap_.termination_exception(), NULL);
883 return Failure::Exception();
884}
885
886
887Failure* Isolate::Throw(Object* exception, MessageLocation* location) {
888 DoThrow(exception, location);
889 return Failure::Exception();
890}
891
892
893Failure* Isolate::ReThrow(MaybeObject* exception, MessageLocation* location) {
894 bool can_be_caught_externally = false;
895 bool catchable_by_javascript = is_catchable_by_javascript(exception);
896 ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
897
898 thread_local_top()->catcher_ = can_be_caught_externally ?
899 try_catch_handler() : NULL;
900
901 // Set the exception being re-thrown.
902 set_pending_exception(exception);
903 if (exception->IsFailure()) return exception->ToFailureUnchecked();
904 return Failure::Exception();
905}
906
907
908Failure* Isolate::ThrowIllegalOperation() {
909 return Throw(heap_.illegal_access_symbol());
910}
911
912
913void Isolate::ScheduleThrow(Object* exception) {
914 // When scheduling a throw we first throw the exception to get the
915 // error reporting if it is uncaught before rescheduling it.
916 Throw(exception);
917 thread_local_top()->scheduled_exception_ = pending_exception();
918 thread_local_top()->external_caught_exception_ = false;
919 clear_pending_exception();
920}
921
922
923Failure* Isolate::PromoteScheduledException() {
924 MaybeObject* thrown = scheduled_exception();
925 clear_scheduled_exception();
926 // Re-throw the exception to avoid getting repeated error reporting.
927 return ReThrow(thrown);
928}
929
930
931void Isolate::PrintCurrentStackTrace(FILE* out) {
932 StackTraceFrameIterator it(this);
933 while (!it.done()) {
934 HandleScope scope;
935 // Find code position if recorded in relocation info.
936 JavaScriptFrame* frame = it.frame();
937 int pos = frame->LookupCode()->SourcePosition(frame->pc());
938 Handle<Object> pos_obj(Smi::FromInt(pos));
939 // Fetch function and receiver.
940 Handle<JSFunction> fun(JSFunction::cast(frame->function()));
941 Handle<Object> recv(frame->receiver());
942 // Advance to the next JavaScript frame and determine if the
943 // current frame is the top-level frame.
944 it.Advance();
945 Handle<Object> is_top_level = it.done()
946 ? factory()->true_value()
947 : factory()->false_value();
948 // Generate and print stack trace line.
949 Handle<String> line =
950 Execution::GetStackTraceLine(recv, fun, pos_obj, is_top_level);
951 if (line->length() > 0) {
952 line->PrintOn(out);
953 fprintf(out, "\n");
954 }
955 }
956}
957
958
959void Isolate::ComputeLocation(MessageLocation* target) {
960 *target = MessageLocation(Handle<Script>(heap_.empty_script()), -1, -1);
961 StackTraceFrameIterator it(this);
962 if (!it.done()) {
963 JavaScriptFrame* frame = it.frame();
964 JSFunction* fun = JSFunction::cast(frame->function());
965 Object* script = fun->shared()->script();
966 if (script->IsScript() &&
967 !(Script::cast(script)->source()->IsUndefined())) {
968 int pos = frame->LookupCode()->SourcePosition(frame->pc());
969 // Compute the location from the function and the reloc info.
970 Handle<Script> casted_script(Script::cast(script));
971 *target = MessageLocation(casted_script, pos, pos + 1);
972 }
973 }
974}
975
976
977bool Isolate::ShouldReportException(bool* can_be_caught_externally,
978 bool catchable_by_javascript) {
979 // Find the top-most try-catch handler.
980 StackHandler* handler =
981 StackHandler::FromAddress(Isolate::handler(thread_local_top()));
982 while (handler != NULL && !handler->is_try_catch()) {
983 handler = handler->next();
984 }
985
986 // Get the address of the external handler so we can compare the address to
987 // determine which one is closer to the top of the stack.
988 Address external_handler_address =
989 thread_local_top()->try_catch_handler_address();
990
991 // The exception has been externally caught if and only if there is
992 // an external handler which is on top of the top-most try-catch
993 // handler.
994 *can_be_caught_externally = external_handler_address != NULL &&
995 (handler == NULL || handler->address() > external_handler_address ||
996 !catchable_by_javascript);
997
998 if (*can_be_caught_externally) {
999 // Only report the exception if the external handler is verbose.
1000 return try_catch_handler()->is_verbose_;
1001 } else {
1002 // Report the exception if it isn't caught by JavaScript code.
1003 return handler == NULL;
1004 }
1005}
1006
1007
1008void Isolate::DoThrow(MaybeObject* exception, MessageLocation* location) {
1009 ASSERT(!has_pending_exception());
1010
1011 HandleScope scope;
1012 Object* exception_object = Smi::FromInt(0);
1013 bool is_object = exception->ToObject(&exception_object);
1014 Handle<Object> exception_handle(exception_object);
1015
1016 // Determine reporting and whether the exception is caught externally.
1017 bool catchable_by_javascript = is_catchable_by_javascript(exception);
1018 // Only real objects can be caught by JS.
1019 ASSERT(!catchable_by_javascript || is_object);
1020 bool can_be_caught_externally = false;
1021 bool should_report_exception =
1022 ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
1023 bool report_exception = catchable_by_javascript && should_report_exception;
1024
1025#ifdef ENABLE_DEBUGGER_SUPPORT
1026 // Notify debugger of exception.
1027 if (catchable_by_javascript) {
1028 debugger_->OnException(exception_handle, report_exception);
1029 }
1030#endif
1031
1032 // Generate the message.
1033 Handle<Object> message_obj;
1034 MessageLocation potential_computed_location;
1035 bool try_catch_needs_message =
1036 can_be_caught_externally &&
1037 try_catch_handler()->capture_message_;
1038 if (report_exception || try_catch_needs_message) {
1039 if (location == NULL) {
1040 // If no location was specified we use a computed one instead
1041 ComputeLocation(&potential_computed_location);
1042 location = &potential_computed_location;
1043 }
1044 if (!bootstrapper()->IsActive()) {
1045 // It's not safe to try to make message objects or collect stack
1046 // traces while the bootstrapper is active since the infrastructure
1047 // may not have been properly initialized.
1048 Handle<String> stack_trace;
1049 if (FLAG_trace_exception) stack_trace = StackTraceString();
1050 Handle<JSArray> stack_trace_object;
1051 if (report_exception && capture_stack_trace_for_uncaught_exceptions_) {
1052 stack_trace_object = CaptureCurrentStackTrace(
1053 stack_trace_for_uncaught_exceptions_frame_limit_,
1054 stack_trace_for_uncaught_exceptions_options_);
1055 }
1056 ASSERT(is_object); // Can't use the handle unless there's a real object.
1057 message_obj = MessageHandler::MakeMessageObject("uncaught_exception",
1058 location, HandleVector<Object>(&exception_handle, 1), stack_trace,
1059 stack_trace_object);
1060 }
1061 }
1062
1063 // Save the message for reporting if the the exception remains uncaught.
1064 thread_local_top()->has_pending_message_ = report_exception;
1065 if (!message_obj.is_null()) {
1066 thread_local_top()->pending_message_obj_ = *message_obj;
1067 if (location != NULL) {
1068 thread_local_top()->pending_message_script_ = *location->script();
1069 thread_local_top()->pending_message_start_pos_ = location->start_pos();
1070 thread_local_top()->pending_message_end_pos_ = location->end_pos();
1071 }
1072 }
1073
1074 // Do not forget to clean catcher_ if currently thrown exception cannot
1075 // be caught. If necessary, ReThrow will update the catcher.
1076 thread_local_top()->catcher_ = can_be_caught_externally ?
1077 try_catch_handler() : NULL;
1078
1079 // NOTE: Notifying the debugger or generating the message
1080 // may have caused new exceptions. For now, we just ignore
1081 // that and set the pending exception to the original one.
1082 if (is_object) {
1083 set_pending_exception(*exception_handle);
1084 } else {
1085 // Failures are not on the heap so they neither need nor work with handles.
1086 ASSERT(exception_handle->IsFailure());
1087 set_pending_exception(exception);
1088 }
1089}
1090
1091
1092bool Isolate::IsExternallyCaught() {
1093 ASSERT(has_pending_exception());
1094
1095 if ((thread_local_top()->catcher_ == NULL) ||
1096 (try_catch_handler() != thread_local_top()->catcher_)) {
1097 // When throwing the exception, we found no v8::TryCatch
1098 // which should care about this exception.
1099 return false;
1100 }
1101
1102 if (!is_catchable_by_javascript(pending_exception())) {
1103 return true;
1104 }
1105
1106 // Get the address of the external handler so we can compare the address to
1107 // determine which one is closer to the top of the stack.
1108 Address external_handler_address =
1109 thread_local_top()->try_catch_handler_address();
1110 ASSERT(external_handler_address != NULL);
1111
1112 // The exception has been externally caught if and only if there is
1113 // an external handler which is on top of the top-most try-finally
1114 // handler.
1115 // There should be no try-catch blocks as they would prohibit us from
1116 // finding external catcher in the first place (see catcher_ check above).
1117 //
1118 // Note, that finally clause would rethrow an exception unless it's
1119 // aborted by jumps in control flow like return, break, etc. and we'll
1120 // have another chances to set proper v8::TryCatch.
1121 StackHandler* handler =
1122 StackHandler::FromAddress(Isolate::handler(thread_local_top()));
1123 while (handler != NULL && handler->address() < external_handler_address) {
1124 ASSERT(!handler->is_try_catch());
1125 if (handler->is_try_finally()) return false;
1126
1127 handler = handler->next();
1128 }
1129
1130 return true;
1131}
1132
1133
1134void Isolate::ReportPendingMessages() {
1135 ASSERT(has_pending_exception());
1136 PropagatePendingExceptionToExternalTryCatch();
1137
1138 // If the pending exception is OutOfMemoryException set out_of_memory in
1139 // the global context. Note: We have to mark the global context here
1140 // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to
1141 // set it.
1142 HandleScope scope;
1143 if (thread_local_top_.pending_exception_ == Failure::OutOfMemoryException()) {
1144 context()->mark_out_of_memory();
1145 } else if (thread_local_top_.pending_exception_ ==
1146 heap()->termination_exception()) {
1147 // Do nothing: if needed, the exception has been already propagated to
1148 // v8::TryCatch.
1149 } else {
1150 if (thread_local_top_.has_pending_message_) {
1151 thread_local_top_.has_pending_message_ = false;
1152 if (!thread_local_top_.pending_message_obj_->IsTheHole()) {
1153 HandleScope scope;
1154 Handle<Object> message_obj(thread_local_top_.pending_message_obj_);
1155 if (thread_local_top_.pending_message_script_ != NULL) {
1156 Handle<Script> script(thread_local_top_.pending_message_script_);
1157 int start_pos = thread_local_top_.pending_message_start_pos_;
1158 int end_pos = thread_local_top_.pending_message_end_pos_;
1159 MessageLocation location(script, start_pos, end_pos);
1160 MessageHandler::ReportMessage(this, &location, message_obj);
1161 } else {
1162 MessageHandler::ReportMessage(this, NULL, message_obj);
1163 }
1164 }
1165 }
1166 }
1167 clear_pending_message();
1168}
1169
1170
1171void Isolate::TraceException(bool flag) {
1172 FLAG_trace_exception = flag; // TODO(isolates): This is an unfortunate use.
1173}
1174
1175
1176bool Isolate::OptionalRescheduleException(bool is_bottom_call) {
1177 ASSERT(has_pending_exception());
1178 PropagatePendingExceptionToExternalTryCatch();
1179
1180 // Allways reschedule out of memory exceptions.
1181 if (!is_out_of_memory()) {
1182 bool is_termination_exception =
1183 pending_exception() == heap_.termination_exception();
1184
1185 // Do not reschedule the exception if this is the bottom call.
1186 bool clear_exception = is_bottom_call;
1187
1188 if (is_termination_exception) {
1189 if (is_bottom_call) {
1190 thread_local_top()->external_caught_exception_ = false;
1191 clear_pending_exception();
1192 return false;
1193 }
1194 } else if (thread_local_top()->external_caught_exception_) {
1195 // If the exception is externally caught, clear it if there are no
1196 // JavaScript frames on the way to the C++ frame that has the
1197 // external handler.
1198 ASSERT(thread_local_top()->try_catch_handler_address() != NULL);
1199 Address external_handler_address =
1200 thread_local_top()->try_catch_handler_address();
1201 JavaScriptFrameIterator it;
1202 if (it.done() || (it.frame()->sp() > external_handler_address)) {
1203 clear_exception = true;
1204 }
1205 }
1206
1207 // Clear the exception if needed.
1208 if (clear_exception) {
1209 thread_local_top()->external_caught_exception_ = false;
1210 clear_pending_exception();
1211 return false;
1212 }
1213 }
1214
1215 // Reschedule the exception.
1216 thread_local_top()->scheduled_exception_ = pending_exception();
1217 clear_pending_exception();
1218 return true;
1219}
1220
1221
1222void Isolate::SetCaptureStackTraceForUncaughtExceptions(
1223 bool capture,
1224 int frame_limit,
1225 StackTrace::StackTraceOptions options) {
1226 capture_stack_trace_for_uncaught_exceptions_ = capture;
1227 stack_trace_for_uncaught_exceptions_frame_limit_ = frame_limit;
1228 stack_trace_for_uncaught_exceptions_options_ = options;
1229}
1230
1231
1232bool Isolate::is_out_of_memory() {
1233 if (has_pending_exception()) {
1234 MaybeObject* e = pending_exception();
1235 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) {
1236 return true;
1237 }
1238 }
1239 if (has_scheduled_exception()) {
1240 MaybeObject* e = scheduled_exception();
1241 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) {
1242 return true;
1243 }
1244 }
1245 return false;
1246}
1247
1248
1249Handle<Context> Isolate::global_context() {
1250 GlobalObject* global = thread_local_top()->context_->global();
1251 return Handle<Context>(global->global_context());
1252}
1253
1254
1255Handle<Context> Isolate::GetCallingGlobalContext() {
1256 JavaScriptFrameIterator it;
1257#ifdef ENABLE_DEBUGGER_SUPPORT
1258 if (debug_->InDebugger()) {
1259 while (!it.done()) {
1260 JavaScriptFrame* frame = it.frame();
1261 Context* context = Context::cast(frame->context());
1262 if (context->global_context() == *debug_->debug_context()) {
1263 it.Advance();
1264 } else {
1265 break;
1266 }
1267 }
1268 }
1269#endif // ENABLE_DEBUGGER_SUPPORT
1270 if (it.done()) return Handle<Context>::null();
1271 JavaScriptFrame* frame = it.frame();
1272 Context* context = Context::cast(frame->context());
1273 return Handle<Context>(context->global_context());
1274}
1275
1276
1277char* Isolate::ArchiveThread(char* to) {
1278 if (RuntimeProfiler::IsEnabled() && current_vm_state() == JS) {
1279 RuntimeProfiler::IsolateExitedJS(this);
1280 }
1281 memcpy(to, reinterpret_cast<char*>(thread_local_top()),
1282 sizeof(ThreadLocalTop));
1283 InitializeThreadLocal();
1284 return to + sizeof(ThreadLocalTop);
1285}
1286
1287
1288char* Isolate::RestoreThread(char* from) {
1289 memcpy(reinterpret_cast<char*>(thread_local_top()), from,
1290 sizeof(ThreadLocalTop));
1291 // This might be just paranoia, but it seems to be needed in case a
1292 // thread_local_top_ is restored on a separate OS thread.
1293#ifdef USE_SIMULATOR
1294#ifdef V8_TARGET_ARCH_ARM
1295 thread_local_top()->simulator_ = Simulator::current(this);
1296#elif V8_TARGET_ARCH_MIPS
1297 thread_local_top()->simulator_ = Simulator::current(this);
1298#endif
1299#endif
1300 if (RuntimeProfiler::IsEnabled() && current_vm_state() == JS) {
1301 RuntimeProfiler::IsolateEnteredJS(this);
1302 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001303 ASSERT(context() == NULL || context()->IsContext());
Ben Murdoch257744e2011-11-30 15:57:28 +00001304 return from + sizeof(ThreadLocalTop);
1305}
1306
1307
Steve Block44f0eee2011-05-26 01:26:41 +01001308Isolate::ThreadDataTable::ThreadDataTable()
1309 : list_(NULL) {
1310}
1311
1312
1313Isolate::PerIsolateThreadData*
Ben Murdoch8b112d22011-06-08 16:22:53 +01001314 Isolate::ThreadDataTable::Lookup(Isolate* isolate,
1315 ThreadId thread_id) {
Steve Block44f0eee2011-05-26 01:26:41 +01001316 for (PerIsolateThreadData* data = list_; data != NULL; data = data->next_) {
1317 if (data->Matches(isolate, thread_id)) return data;
1318 }
1319 return NULL;
1320}
1321
1322
1323void Isolate::ThreadDataTable::Insert(Isolate::PerIsolateThreadData* data) {
1324 if (list_ != NULL) list_->prev_ = data;
1325 data->next_ = list_;
1326 list_ = data;
1327}
1328
1329
1330void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) {
1331 if (list_ == data) list_ = data->next_;
1332 if (data->next_ != NULL) data->next_->prev_ = data->prev_;
1333 if (data->prev_ != NULL) data->prev_->next_ = data->next_;
1334}
1335
1336
Ben Murdoch8b112d22011-06-08 16:22:53 +01001337void Isolate::ThreadDataTable::Remove(Isolate* isolate,
1338 ThreadId thread_id) {
Steve Block44f0eee2011-05-26 01:26:41 +01001339 PerIsolateThreadData* data = Lookup(isolate, thread_id);
1340 if (data != NULL) {
1341 Remove(data);
1342 }
1343}
1344
1345
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001346void Isolate::ThreadDataTable::RemoveAllThreads(Isolate* isolate) {
1347 PerIsolateThreadData* data = list_;
1348 while (data != NULL) {
1349 PerIsolateThreadData* next = data->next_;
1350 if (data->isolate() == isolate) Remove(data);
1351 data = next;
1352 }
1353}
1354
1355
Steve Block44f0eee2011-05-26 01:26:41 +01001356#ifdef DEBUG
1357#define TRACE_ISOLATE(tag) \
1358 do { \
1359 if (FLAG_trace_isolates) { \
1360 PrintF("Isolate %p " #tag "\n", reinterpret_cast<void*>(this)); \
1361 } \
1362 } while (false)
1363#else
1364#define TRACE_ISOLATE(tag)
1365#endif
1366
1367
1368Isolate::Isolate()
1369 : state_(UNINITIALIZED),
1370 entry_stack_(NULL),
1371 stack_trace_nesting_level_(0),
1372 incomplete_message_(NULL),
1373 preallocated_memory_thread_(NULL),
1374 preallocated_message_space_(NULL),
1375 bootstrapper_(NULL),
1376 runtime_profiler_(NULL),
1377 compilation_cache_(NULL),
Ben Murdoch257744e2011-11-30 15:57:28 +00001378 counters_(new Counters()),
Steve Block44f0eee2011-05-26 01:26:41 +01001379 code_range_(NULL),
1380 break_access_(OS::CreateMutex()),
Ben Murdoch257744e2011-11-30 15:57:28 +00001381 logger_(new Logger()),
1382 stats_table_(new StatsTable()),
Steve Block44f0eee2011-05-26 01:26:41 +01001383 stub_cache_(NULL),
1384 deoptimizer_data_(NULL),
1385 capture_stack_trace_for_uncaught_exceptions_(false),
1386 stack_trace_for_uncaught_exceptions_frame_limit_(0),
1387 stack_trace_for_uncaught_exceptions_options_(StackTrace::kOverview),
1388 transcendental_cache_(NULL),
1389 memory_allocator_(NULL),
1390 keyed_lookup_cache_(NULL),
1391 context_slot_cache_(NULL),
1392 descriptor_lookup_cache_(NULL),
1393 handle_scope_implementer_(NULL),
Ben Murdoch8b112d22011-06-08 16:22:53 +01001394 unicode_cache_(NULL),
Steve Block44f0eee2011-05-26 01:26:41 +01001395 in_use_list_(0),
1396 free_list_(0),
1397 preallocated_storage_preallocated_(false),
1398 pc_to_code_cache_(NULL),
1399 write_input_buffer_(NULL),
1400 global_handles_(NULL),
1401 context_switcher_(NULL),
1402 thread_manager_(NULL),
1403 ast_sentinels_(NULL),
1404 string_tracker_(NULL),
1405 regexp_stack_(NULL),
Ben Murdoch257744e2011-11-30 15:57:28 +00001406 embedder_data_(NULL) {
Steve Block44f0eee2011-05-26 01:26:41 +01001407 TRACE_ISOLATE(constructor);
1408
1409 memset(isolate_addresses_, 0,
1410 sizeof(isolate_addresses_[0]) * (k_isolate_address_count + 1));
1411
1412 heap_.isolate_ = this;
1413 zone_.isolate_ = this;
1414 stack_guard_.isolate_ = this;
1415
Ben Murdoch257744e2011-11-30 15:57:28 +00001416 // ThreadManager is initialized early to support locking an isolate
1417 // before it is entered.
1418 thread_manager_ = new ThreadManager();
1419 thread_manager_->isolate_ = this;
1420
Steve Block44f0eee2011-05-26 01:26:41 +01001421#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
1422 defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
1423 simulator_initialized_ = false;
1424 simulator_i_cache_ = NULL;
1425 simulator_redirection_ = NULL;
1426#endif
1427
1428#ifdef DEBUG
1429 // heap_histograms_ initializes itself.
1430 memset(&js_spill_information_, 0, sizeof(js_spill_information_));
1431 memset(code_kind_statistics_, 0,
1432 sizeof(code_kind_statistics_[0]) * Code::NUMBER_OF_KINDS);
1433#endif
1434
1435#ifdef ENABLE_DEBUGGER_SUPPORT
1436 debug_ = NULL;
1437 debugger_ = NULL;
1438#endif
1439
Steve Block44f0eee2011-05-26 01:26:41 +01001440 handle_scope_data_.Initialize();
1441
1442#define ISOLATE_INIT_EXECUTE(type, name, initial_value) \
1443 name##_ = (initial_value);
1444 ISOLATE_INIT_LIST(ISOLATE_INIT_EXECUTE)
1445#undef ISOLATE_INIT_EXECUTE
1446
1447#define ISOLATE_INIT_ARRAY_EXECUTE(type, name, length) \
1448 memset(name##_, 0, sizeof(type) * length);
1449 ISOLATE_INIT_ARRAY_LIST(ISOLATE_INIT_ARRAY_EXECUTE)
1450#undef ISOLATE_INIT_ARRAY_EXECUTE
1451}
1452
1453void Isolate::TearDown() {
1454 TRACE_ISOLATE(tear_down);
1455
1456 // Temporarily set this isolate as current so that various parts of
1457 // the isolate can access it in their destructors without having a
1458 // direct pointer. We don't use Enter/Exit here to avoid
1459 // initializing the thread data.
1460 PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData();
1461 Isolate* saved_isolate = UncheckedCurrent();
1462 SetIsolateThreadLocals(this, NULL);
1463
1464 Deinit();
1465
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001466 { ScopedLock lock(process_wide_mutex_);
1467 thread_data_table_->RemoveAllThreads(this);
1468 }
1469
Steve Block44f0eee2011-05-26 01:26:41 +01001470 if (!IsDefaultIsolate()) {
1471 delete this;
1472 }
1473
1474 // Restore the previous current isolate.
1475 SetIsolateThreadLocals(saved_isolate, saved_data);
1476}
1477
1478
1479void Isolate::Deinit() {
1480 if (state_ == INITIALIZED) {
1481 TRACE_ISOLATE(deinit);
1482
1483 if (FLAG_hydrogen_stats) HStatistics::Instance()->Print();
1484
1485 // We must stop the logger before we tear down other components.
1486 logger_->EnsureTickerStopped();
1487
1488 delete deoptimizer_data_;
1489 deoptimizer_data_ = NULL;
1490 if (FLAG_preemption) {
1491 v8::Locker locker;
1492 v8::Locker::StopPreemption();
1493 }
1494 builtins_.TearDown();
1495 bootstrapper_->TearDown();
1496
1497 // Remove the external reference to the preallocated stack memory.
1498 delete preallocated_message_space_;
1499 preallocated_message_space_ = NULL;
1500 PreallocatedMemoryThreadStop();
1501
1502 HeapProfiler::TearDown();
1503 CpuProfiler::TearDown();
1504 if (runtime_profiler_ != NULL) {
1505 runtime_profiler_->TearDown();
1506 delete runtime_profiler_;
1507 runtime_profiler_ = NULL;
1508 }
1509 heap_.TearDown();
1510 logger_->TearDown();
1511
1512 // The default isolate is re-initializable due to legacy API.
Ben Murdoch257744e2011-11-30 15:57:28 +00001513 state_ = PREINITIALIZED;
Steve Block44f0eee2011-05-26 01:26:41 +01001514 }
1515}
1516
1517
1518void Isolate::SetIsolateThreadLocals(Isolate* isolate,
1519 PerIsolateThreadData* data) {
1520 Thread::SetThreadLocal(isolate_key_, isolate);
1521 Thread::SetThreadLocal(per_isolate_thread_data_key_, data);
1522}
1523
1524
1525Isolate::~Isolate() {
1526 TRACE_ISOLATE(destructor);
1527
Ben Murdoch8b112d22011-06-08 16:22:53 +01001528 delete unicode_cache_;
1529 unicode_cache_ = NULL;
Steve Block44f0eee2011-05-26 01:26:41 +01001530
1531 delete regexp_stack_;
1532 regexp_stack_ = NULL;
1533
1534 delete ast_sentinels_;
1535 ast_sentinels_ = NULL;
1536
1537 delete descriptor_lookup_cache_;
1538 descriptor_lookup_cache_ = NULL;
1539 delete context_slot_cache_;
1540 context_slot_cache_ = NULL;
1541 delete keyed_lookup_cache_;
1542 keyed_lookup_cache_ = NULL;
1543
1544 delete transcendental_cache_;
1545 transcendental_cache_ = NULL;
1546 delete stub_cache_;
1547 stub_cache_ = NULL;
1548 delete stats_table_;
1549 stats_table_ = NULL;
1550
1551 delete logger_;
1552 logger_ = NULL;
1553
1554 delete counters_;
1555 counters_ = NULL;
Steve Block44f0eee2011-05-26 01:26:41 +01001556
1557 delete handle_scope_implementer_;
1558 handle_scope_implementer_ = NULL;
1559 delete break_access_;
1560 break_access_ = NULL;
1561
1562 delete compilation_cache_;
1563 compilation_cache_ = NULL;
1564 delete bootstrapper_;
1565 bootstrapper_ = NULL;
1566 delete pc_to_code_cache_;
1567 pc_to_code_cache_ = NULL;
1568 delete write_input_buffer_;
1569 write_input_buffer_ = NULL;
1570
1571 delete context_switcher_;
1572 context_switcher_ = NULL;
1573 delete thread_manager_;
1574 thread_manager_ = NULL;
1575
1576 delete string_tracker_;
1577 string_tracker_ = NULL;
1578
1579 delete memory_allocator_;
1580 memory_allocator_ = NULL;
1581 delete code_range_;
1582 code_range_ = NULL;
1583 delete global_handles_;
1584 global_handles_ = NULL;
1585
1586#ifdef ENABLE_DEBUGGER_SUPPORT
1587 delete debugger_;
1588 debugger_ = NULL;
1589 delete debug_;
1590 debug_ = NULL;
1591#endif
1592}
1593
1594
Ben Murdoch257744e2011-11-30 15:57:28 +00001595bool Isolate::PreInit() {
1596 if (state_ != UNINITIALIZED) return true;
1597
1598 TRACE_ISOLATE(preinit);
1599
1600 ASSERT(Isolate::Current() == this);
1601#ifdef ENABLE_DEBUGGER_SUPPORT
1602 debug_ = new Debug(this);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001603 debugger_ = new Debugger(this);
Ben Murdoch257744e2011-11-30 15:57:28 +00001604#endif
1605
1606 memory_allocator_ = new MemoryAllocator();
1607 memory_allocator_->isolate_ = this;
1608 code_range_ = new CodeRange();
1609 code_range_->isolate_ = this;
1610
1611 // Safe after setting Heap::isolate_, initializing StackGuard and
1612 // ensuring that Isolate::Current() == this.
1613 heap_.SetStackLimits();
1614
1615#ifdef DEBUG
1616 DisallowAllocationFailure disallow_allocation_failure;
1617#endif
1618
1619#define C(name) isolate_addresses_[Isolate::k_##name] = \
1620 reinterpret_cast<Address>(name());
1621 ISOLATE_ADDRESS_LIST(C)
Ben Murdoch257744e2011-11-30 15:57:28 +00001622#undef C
1623
1624 string_tracker_ = new StringTracker();
1625 string_tracker_->isolate_ = this;
1626 compilation_cache_ = new CompilationCache(this);
1627 transcendental_cache_ = new TranscendentalCache();
1628 keyed_lookup_cache_ = new KeyedLookupCache();
1629 context_slot_cache_ = new ContextSlotCache();
1630 descriptor_lookup_cache_ = new DescriptorLookupCache();
1631 unicode_cache_ = new UnicodeCache();
1632 pc_to_code_cache_ = new PcToCodeCache(this);
1633 write_input_buffer_ = new StringInputBuffer();
1634 global_handles_ = new GlobalHandles(this);
1635 bootstrapper_ = new Bootstrapper();
1636 handle_scope_implementer_ = new HandleScopeImplementer(this);
1637 stub_cache_ = new StubCache(this);
1638 ast_sentinels_ = new AstSentinels();
1639 regexp_stack_ = new RegExpStack();
1640 regexp_stack_->isolate_ = this;
1641
Ben Murdoch257744e2011-11-30 15:57:28 +00001642 state_ = PREINITIALIZED;
1643 return true;
1644}
1645
1646
Steve Block44f0eee2011-05-26 01:26:41 +01001647void Isolate::InitializeThreadLocal() {
Ben Murdoch257744e2011-11-30 15:57:28 +00001648 thread_local_top_.isolate_ = this;
Steve Block44f0eee2011-05-26 01:26:41 +01001649 thread_local_top_.Initialize();
1650 clear_pending_exception();
1651 clear_pending_message();
1652 clear_scheduled_exception();
1653}
1654
1655
Ben Murdoch8b112d22011-06-08 16:22:53 +01001656void Isolate::PropagatePendingExceptionToExternalTryCatch() {
1657 ASSERT(has_pending_exception());
1658
1659 bool external_caught = IsExternallyCaught();
1660 thread_local_top_.external_caught_exception_ = external_caught;
1661
1662 if (!external_caught) return;
1663
1664 if (thread_local_top_.pending_exception_ == Failure::OutOfMemoryException()) {
1665 // Do not propagate OOM exception: we should kill VM asap.
1666 } else if (thread_local_top_.pending_exception_ ==
1667 heap()->termination_exception()) {
1668 try_catch_handler()->can_continue_ = false;
1669 try_catch_handler()->exception_ = heap()->null_value();
1670 } else {
1671 // At this point all non-object (failure) exceptions have
1672 // been dealt with so this shouldn't fail.
1673 ASSERT(!pending_exception()->IsFailure());
1674 try_catch_handler()->can_continue_ = true;
1675 try_catch_handler()->exception_ = pending_exception();
1676 if (!thread_local_top_.pending_message_obj_->IsTheHole()) {
1677 try_catch_handler()->message_ = thread_local_top_.pending_message_obj_;
1678 }
1679 }
1680}
1681
1682
Steve Block44f0eee2011-05-26 01:26:41 +01001683bool Isolate::Init(Deserializer* des) {
1684 ASSERT(state_ != INITIALIZED);
Ben Murdoch257744e2011-11-30 15:57:28 +00001685
Steve Block44f0eee2011-05-26 01:26:41 +01001686 TRACE_ISOLATE(init);
1687
Ben Murdoch257744e2011-11-30 15:57:28 +00001688 bool create_heap_objects = des == NULL;
1689
Steve Block44f0eee2011-05-26 01:26:41 +01001690#ifdef DEBUG
1691 // The initialization process does not handle memory exhaustion.
1692 DisallowAllocationFailure disallow_allocation_failure;
1693#endif
1694
Ben Murdoch257744e2011-11-30 15:57:28 +00001695 if (state_ == UNINITIALIZED && !PreInit()) return false;
Steve Block44f0eee2011-05-26 01:26:41 +01001696
1697 // Enable logging before setting up the heap
1698 logger_->Setup();
1699
1700 CpuProfiler::Setup();
1701 HeapProfiler::Setup();
1702
Steve Block44f0eee2011-05-26 01:26:41 +01001703 // Initialize other runtime facilities
1704#if defined(USE_SIMULATOR)
1705#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
Ben Murdoch257744e2011-11-30 15:57:28 +00001706 Simulator::Initialize(this);
Steve Block44f0eee2011-05-26 01:26:41 +01001707#endif
1708#endif
1709
1710 { // NOLINT
1711 // Ensure that the thread has a valid stack guard. The v8::Locker object
1712 // will ensure this too, but we don't have to use lockers if we are only
1713 // using one thread.
1714 ExecutionAccess lock(this);
1715 stack_guard_.InitThread(lock);
1716 }
1717
Ben Murdoch257744e2011-11-30 15:57:28 +00001718 // Setup the object heap
Steve Block44f0eee2011-05-26 01:26:41 +01001719 ASSERT(!heap_.HasBeenSetup());
1720 if (!heap_.Setup(create_heap_objects)) {
1721 V8::SetFatalError();
1722 return false;
1723 }
1724
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001725 InitializeThreadLocal();
1726
Steve Block44f0eee2011-05-26 01:26:41 +01001727 bootstrapper_->Initialize(create_heap_objects);
1728 builtins_.Setup(create_heap_objects);
1729
Steve Block44f0eee2011-05-26 01:26:41 +01001730 // Only preallocate on the first initialization.
1731 if (FLAG_preallocate_message_memory && preallocated_message_space_ == NULL) {
1732 // Start the thread which will set aside some memory.
1733 PreallocatedMemoryThreadStart();
1734 preallocated_message_space_ =
1735 new NoAllocationStringAllocator(
1736 preallocated_memory_thread_->data(),
1737 preallocated_memory_thread_->length());
1738 PreallocatedStorageInit(preallocated_memory_thread_->length() / 4);
1739 }
1740
1741 if (FLAG_preemption) {
1742 v8::Locker locker;
1743 v8::Locker::StartPreemption(100);
1744 }
1745
1746#ifdef ENABLE_DEBUGGER_SUPPORT
1747 debug_->Setup(create_heap_objects);
1748#endif
1749 stub_cache_->Initialize(create_heap_objects);
1750
1751 // If we are deserializing, read the state into the now-empty heap.
1752 if (des != NULL) {
1753 des->Deserialize();
1754 stub_cache_->Clear();
1755 }
1756
1757 // Deserializing may put strange things in the root array's copy of the
1758 // stack guard.
1759 heap_.SetStackLimits();
1760
Steve Block44f0eee2011-05-26 01:26:41 +01001761 deoptimizer_data_ = new DeoptimizerData;
1762 runtime_profiler_ = new RuntimeProfiler(this);
1763 runtime_profiler_->Setup();
1764
1765 // If we are deserializing, log non-function code objects and compiled
1766 // functions found in the snapshot.
Ben Murdoch257744e2011-11-30 15:57:28 +00001767 if (des != NULL && (FLAG_log_code || FLAG_ll_prof)) {
Steve Block44f0eee2011-05-26 01:26:41 +01001768 HandleScope scope;
1769 LOG(this, LogCodeObjects());
1770 LOG(this, LogCompiledFunctions());
1771 }
1772
1773 state_ = INITIALIZED;
1774 return true;
1775}
1776
1777
1778void Isolate::Enter() {
1779 Isolate* current_isolate = NULL;
1780 PerIsolateThreadData* current_data = CurrentPerIsolateThreadData();
1781 if (current_data != NULL) {
1782 current_isolate = current_data->isolate_;
1783 ASSERT(current_isolate != NULL);
1784 if (current_isolate == this) {
1785 ASSERT(Current() == this);
1786 ASSERT(entry_stack_ != NULL);
1787 ASSERT(entry_stack_->previous_thread_data == NULL ||
Ben Murdoch8b112d22011-06-08 16:22:53 +01001788 entry_stack_->previous_thread_data->thread_id().Equals(
1789 ThreadId::Current()));
Steve Block44f0eee2011-05-26 01:26:41 +01001790 // Same thread re-enters the isolate, no need to re-init anything.
1791 entry_stack_->entry_count++;
1792 return;
1793 }
1794 }
1795
1796 // Threads can have default isolate set into TLS as Current but not yet have
1797 // PerIsolateThreadData for it, as it requires more advanced phase of the
1798 // initialization. For example, a thread might be the one that system used for
1799 // static initializers - in this case the default isolate is set in TLS but
1800 // the thread did not yet Enter the isolate. If PerisolateThreadData is not
1801 // there, use the isolate set in TLS.
1802 if (current_isolate == NULL) {
1803 current_isolate = Isolate::UncheckedCurrent();
1804 }
1805
1806 PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread();
1807 ASSERT(data != NULL);
1808 ASSERT(data->isolate_ == this);
1809
1810 EntryStackItem* item = new EntryStackItem(current_data,
1811 current_isolate,
1812 entry_stack_);
1813 entry_stack_ = item;
1814
1815 SetIsolateThreadLocals(this, data);
1816
Ben Murdoch257744e2011-11-30 15:57:28 +00001817 CHECK(PreInit());
1818
Steve Block44f0eee2011-05-26 01:26:41 +01001819 // In case it's the first time some thread enters the isolate.
1820 set_thread_id(data->thread_id());
1821}
1822
1823
1824void Isolate::Exit() {
1825 ASSERT(entry_stack_ != NULL);
1826 ASSERT(entry_stack_->previous_thread_data == NULL ||
Ben Murdoch8b112d22011-06-08 16:22:53 +01001827 entry_stack_->previous_thread_data->thread_id().Equals(
1828 ThreadId::Current()));
Steve Block44f0eee2011-05-26 01:26:41 +01001829
1830 if (--entry_stack_->entry_count > 0) return;
1831
1832 ASSERT(CurrentPerIsolateThreadData() != NULL);
1833 ASSERT(CurrentPerIsolateThreadData()->isolate_ == this);
1834
1835 // Pop the stack.
1836 EntryStackItem* item = entry_stack_;
1837 entry_stack_ = item->previous_item;
1838
1839 PerIsolateThreadData* previous_thread_data = item->previous_thread_data;
1840 Isolate* previous_isolate = item->previous_isolate;
1841
1842 delete item;
1843
1844 // Reinit the current thread for the isolate it was running before this one.
1845 SetIsolateThreadLocals(previous_isolate, previous_thread_data);
1846}
1847
1848
Steve Block44f0eee2011-05-26 01:26:41 +01001849#ifdef DEBUG
1850#define ISOLATE_FIELD_OFFSET(type, name, ignored) \
1851const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_);
1852ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
1853ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
1854#undef ISOLATE_FIELD_OFFSET
1855#endif
1856
1857} } // namespace v8::internal