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