blob: b8a7fb75ac6c56733977c3274990e5b33164728b [file] [log] [blame]
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001// Copyright 2006-2010 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include <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"
43#include "regexp-stack.h"
44#include "runtime-profiler.h"
45#include "scanner.h"
46#include "scopeinfo.h"
47#include "serialize.h"
48#include "simulator.h"
49#include "spaces.h"
50#include "stub-cache.h"
51#include "version.h"
52
53
54namespace v8 {
55namespace internal {
56
57
58// Create a dummy thread that will wait forever on a semaphore. The only
59// purpose for this thread is to have some stack area to save essential data
60// into for use by a stacks only core dump (aka minidump).
61class PreallocatedMemoryThread: public Thread {
62 public:
63 char* data() {
64 if (data_ready_semaphore_ != NULL) {
65 // Initial access is guarded until the data has been published.
66 data_ready_semaphore_->Wait();
67 delete data_ready_semaphore_;
68 data_ready_semaphore_ = NULL;
69 }
70 return data_;
71 }
72
73 unsigned length() {
74 if (data_ready_semaphore_ != NULL) {
75 // Initial access is guarded until the data has been published.
76 data_ready_semaphore_->Wait();
77 delete data_ready_semaphore_;
78 data_ready_semaphore_ = NULL;
79 }
80 return length_;
81 }
82
83 // Stop the PreallocatedMemoryThread and release its resources.
84 void StopThread() {
85 keep_running_ = false;
86 wait_for_ever_semaphore_->Signal();
87
88 // Wait for the thread to terminate.
89 Join();
90
91 if (data_ready_semaphore_ != NULL) {
92 delete data_ready_semaphore_;
93 data_ready_semaphore_ = NULL;
94 }
95
96 delete wait_for_ever_semaphore_;
97 wait_for_ever_semaphore_ = NULL;
98 }
99
100 protected:
101 // When the thread starts running it will allocate a fixed number of bytes
102 // on the stack and publish the location of this memory for others to use.
103 void Run() {
104 EmbeddedVector<char, 15 * 1024> local_buffer;
105
106 // Initialize the buffer with a known good value.
107 OS::StrNCpy(local_buffer, "Trace data was not generated.\n",
108 local_buffer.length());
109
110 // Publish the local buffer and signal its availability.
111 data_ = local_buffer.start();
112 length_ = local_buffer.length();
113 data_ready_semaphore_->Signal();
114
115 while (keep_running_) {
116 // This thread will wait here until the end of time.
117 wait_for_ever_semaphore_->Wait();
118 }
119
120 // Make sure we access the buffer after the wait to remove all possibility
121 // of it being optimized away.
122 OS::StrNCpy(local_buffer, "PreallocatedMemoryThread shutting down.\n",
123 local_buffer.length());
124 }
125
126
127 private:
128 explicit PreallocatedMemoryThread(Isolate* isolate)
129 : Thread(isolate, "v8:PreallocMem"),
130 keep_running_(true),
131 wait_for_ever_semaphore_(OS::CreateSemaphore(0)),
132 data_ready_semaphore_(OS::CreateSemaphore(0)),
133 data_(NULL),
134 length_(0) {
135 }
136
137 // Used to make sure that the thread keeps looping even for spurious wakeups.
138 bool keep_running_;
139
140 // This semaphore is used by the PreallocatedMemoryThread to wait for ever.
141 Semaphore* wait_for_ever_semaphore_;
142 // Semaphore to signal that the data has been initialized.
143 Semaphore* data_ready_semaphore_;
144
145 // Location and size of the preallocated memory block.
146 char* data_;
147 unsigned length_;
148
149 friend class Isolate;
150
151 DISALLOW_COPY_AND_ASSIGN(PreallocatedMemoryThread);
152};
153
154
155void Isolate::PreallocatedMemoryThreadStart() {
156 if (preallocated_memory_thread_ != NULL) return;
157 preallocated_memory_thread_ = new PreallocatedMemoryThread(this);
158 preallocated_memory_thread_->Start();
159}
160
161
162void Isolate::PreallocatedMemoryThreadStop() {
163 if (preallocated_memory_thread_ == NULL) return;
164 preallocated_memory_thread_->StopThread();
165 // Done with the thread entirely.
166 delete preallocated_memory_thread_;
167 preallocated_memory_thread_ = NULL;
168}
169
170
lrn@chromium.org7516f052011-03-30 08:52:27 +0000171void Isolate::PreallocatedStorageInit(size_t size) {
172 ASSERT(free_list_.next_ == &free_list_);
173 ASSERT(free_list_.previous_ == &free_list_);
174 PreallocatedStorage* free_chunk =
175 reinterpret_cast<PreallocatedStorage*>(new char[size]);
176 free_list_.next_ = free_list_.previous_ = free_chunk;
177 free_chunk->next_ = free_chunk->previous_ = &free_list_;
178 free_chunk->size_ = size - sizeof(PreallocatedStorage);
179 preallocated_storage_preallocated_ = true;
180}
181
182
183void* Isolate::PreallocatedStorageNew(size_t size) {
184 if (!preallocated_storage_preallocated_) {
185 return FreeStoreAllocationPolicy::New(size);
186 }
187 ASSERT(free_list_.next_ != &free_list_);
188 ASSERT(free_list_.previous_ != &free_list_);
189
190 size = (size + kPointerSize - 1) & ~(kPointerSize - 1);
191 // Search for exact fit.
192 for (PreallocatedStorage* storage = free_list_.next_;
193 storage != &free_list_;
194 storage = storage->next_) {
195 if (storage->size_ == size) {
196 storage->Unlink();
197 storage->LinkTo(&in_use_list_);
198 return reinterpret_cast<void*>(storage + 1);
199 }
200 }
201 // Search for first fit.
202 for (PreallocatedStorage* storage = free_list_.next_;
203 storage != &free_list_;
204 storage = storage->next_) {
205 if (storage->size_ >= size + sizeof(PreallocatedStorage)) {
206 storage->Unlink();
207 storage->LinkTo(&in_use_list_);
208 PreallocatedStorage* left_over =
209 reinterpret_cast<PreallocatedStorage*>(
210 reinterpret_cast<char*>(storage + 1) + size);
211 left_over->size_ = storage->size_ - size - sizeof(PreallocatedStorage);
212 ASSERT(size + left_over->size_ + sizeof(PreallocatedStorage) ==
213 storage->size_);
214 storage->size_ = size;
215 left_over->LinkTo(&free_list_);
216 return reinterpret_cast<void*>(storage + 1);
217 }
218 }
219 // Allocation failure.
220 ASSERT(false);
221 return NULL;
222}
223
224
225// We don't attempt to coalesce.
226void Isolate::PreallocatedStorageDelete(void* p) {
227 if (p == NULL) {
228 return;
229 }
230 if (!preallocated_storage_preallocated_) {
231 FreeStoreAllocationPolicy::Delete(p);
232 return;
233 }
234 PreallocatedStorage* storage = reinterpret_cast<PreallocatedStorage*>(p) - 1;
235 ASSERT(storage->next_->previous_ == storage);
236 ASSERT(storage->previous_->next_ == storage);
237 storage->Unlink();
238 storage->LinkTo(&free_list_);
239}
240
241
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000242Isolate* Isolate::default_isolate_ = NULL;
243Thread::LocalStorageKey Isolate::isolate_key_;
244Thread::LocalStorageKey Isolate::thread_id_key_;
245Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
246Mutex* Isolate::process_wide_mutex_ = OS::CreateMutex();
247Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL;
248Isolate::ThreadId Isolate::highest_thread_id_ = 0;
249
250
251class IsolateInitializer {
252 public:
253 IsolateInitializer() {
254 Isolate::EnsureDefaultIsolate();
255 }
256};
257
258static IsolateInitializer* EnsureDefaultIsolateAllocated() {
259 // TODO(isolates): Use the system threading API to do this once?
260 static IsolateInitializer static_initializer;
261 return &static_initializer;
262}
263
264// This variable only needed to trigger static intialization.
265static IsolateInitializer* static_initializer = EnsureDefaultIsolateAllocated();
266
267
268Isolate::ThreadId Isolate::AllocateThreadId() {
269 ThreadId new_id;
270 {
271 ScopedLock lock(process_wide_mutex_);
272 new_id = ++highest_thread_id_;
273 }
274 return new_id;
275}
276
277
278Isolate::PerIsolateThreadData* Isolate::AllocatePerIsolateThreadData(
279 ThreadId thread_id) {
280 ASSERT(thread_id != 0);
281 ASSERT(Thread::GetThreadLocalInt(thread_id_key_) == thread_id);
282 PerIsolateThreadData* per_thread = new PerIsolateThreadData(this, thread_id);
283 {
284 ScopedLock lock(process_wide_mutex_);
285 ASSERT(thread_data_table_->Lookup(this, thread_id) == NULL);
286 thread_data_table_->Insert(per_thread);
287 ASSERT(thread_data_table_->Lookup(this, thread_id) == per_thread);
288 }
289 return per_thread;
290}
291
292
293Isolate::PerIsolateThreadData*
294 Isolate::FindOrAllocatePerThreadDataForThisThread() {
295 ThreadId thread_id = Thread::GetThreadLocalInt(thread_id_key_);
296 if (thread_id == 0) {
297 thread_id = AllocateThreadId();
298 Thread::SetThreadLocalInt(thread_id_key_, thread_id);
299 }
300 PerIsolateThreadData* per_thread = NULL;
301 {
302 ScopedLock lock(process_wide_mutex_);
303 per_thread = thread_data_table_->Lookup(this, thread_id);
304 if (per_thread == NULL) {
305 per_thread = AllocatePerIsolateThreadData(thread_id);
306 }
307 }
308 return per_thread;
309}
310
311
312void Isolate::EnsureDefaultIsolate() {
313 ScopedLock lock(process_wide_mutex_);
314 if (default_isolate_ == NULL) {
315 isolate_key_ = Thread::CreateThreadLocalKey();
316 thread_id_key_ = Thread::CreateThreadLocalKey();
317 per_isolate_thread_data_key_ = Thread::CreateThreadLocalKey();
318 thread_data_table_ = new Isolate::ThreadDataTable();
319 default_isolate_ = new Isolate();
320 }
321 // Can't use SetIsolateThreadLocals(default_isolate_, NULL) here
322 // becase a non-null thread data may be already set.
323 Thread::SetThreadLocal(isolate_key_, default_isolate_);
324 CHECK(default_isolate_->PreInit());
325}
326
327
328Debugger* Isolate::GetDefaultIsolateDebugger() {
329 EnsureDefaultIsolate();
330 return default_isolate_->debugger();
331}
332
333
334StackGuard* Isolate::GetDefaultIsolateStackGuard() {
335 EnsureDefaultIsolate();
336 return default_isolate_->stack_guard();
337}
338
339
340void Isolate::EnterDefaultIsolate() {
341 EnsureDefaultIsolate();
342 ASSERT(default_isolate_ != NULL);
343
344 PerIsolateThreadData* data = CurrentPerIsolateThreadData();
345 // If not yet in default isolate - enter it.
346 if (data == NULL || data->isolate() != default_isolate_) {
347 default_isolate_->Enter();
348 }
349}
350
351
352Isolate* Isolate::GetDefaultIsolateForLocking() {
353 EnsureDefaultIsolate();
354 return default_isolate_;
355}
356
357
358Isolate::ThreadDataTable::ThreadDataTable()
359 : list_(NULL) {
360}
361
362
363Isolate::PerIsolateThreadData*
364 Isolate::ThreadDataTable::Lookup(Isolate* isolate, ThreadId thread_id) {
365 for (PerIsolateThreadData* data = list_; data != NULL; data = data->next_) {
366 if (data->Matches(isolate, thread_id)) return data;
367 }
368 return NULL;
369}
370
371
372void Isolate::ThreadDataTable::Insert(Isolate::PerIsolateThreadData* data) {
373 if (list_ != NULL) list_->prev_ = data;
374 data->next_ = list_;
375 list_ = data;
376}
377
378
379void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) {
380 if (list_ == data) list_ = data->next_;
381 if (data->next_ != NULL) data->next_->prev_ = data->prev_;
382 if (data->prev_ != NULL) data->prev_->next_ = data->next_;
383}
384
385
386void Isolate::ThreadDataTable::Remove(Isolate* isolate, ThreadId thread_id) {
387 PerIsolateThreadData* data = Lookup(isolate, thread_id);
388 if (data != NULL) {
389 Remove(data);
390 }
391}
392
393
394#ifdef DEBUG
395#define TRACE_ISOLATE(tag) \
396 do { \
397 if (FLAG_trace_isolates) { \
398 PrintF("Isolate %p " #tag "\n", reinterpret_cast<void*>(this)); \
399 } \
400 } while (false)
401#else
402#define TRACE_ISOLATE(tag)
403#endif
404
405
406Isolate::Isolate()
407 : state_(UNINITIALIZED),
408 entry_stack_(NULL),
409 stack_trace_nesting_level_(0),
410 incomplete_message_(NULL),
411 preallocated_memory_thread_(NULL),
412 preallocated_message_space_(NULL),
413 bootstrapper_(NULL),
414 runtime_profiler_(NULL),
415 compilation_cache_(NULL),
416 counters_(new Counters()),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000417 code_range_(NULL),
418 break_access_(OS::CreateMutex()),
419 logger_(new Logger()),
420 stats_table_(new StatsTable()),
421 stub_cache_(NULL),
422 deoptimizer_data_(NULL),
423 capture_stack_trace_for_uncaught_exceptions_(false),
424 stack_trace_for_uncaught_exceptions_frame_limit_(0),
425 stack_trace_for_uncaught_exceptions_options_(StackTrace::kOverview),
426 transcendental_cache_(NULL),
427 memory_allocator_(NULL),
428 keyed_lookup_cache_(NULL),
429 context_slot_cache_(NULL),
430 descriptor_lookup_cache_(NULL),
431 handle_scope_implementer_(NULL),
432 scanner_constants_(NULL),
433 in_use_list_(0),
434 free_list_(0),
435 preallocated_storage_preallocated_(false),
436 pc_to_code_cache_(NULL),
437 write_input_buffer_(NULL),
438 global_handles_(NULL),
439 context_switcher_(NULL),
440 thread_manager_(NULL),
441 ast_sentinels_(NULL),
442 string_tracker_(NULL),
443 regexp_stack_(NULL),
444 frame_element_constant_list_(0),
445 result_constant_list_(0) {
446 TRACE_ISOLATE(constructor);
447
448 memset(isolate_addresses_, 0,
449 sizeof(isolate_addresses_[0]) * (k_isolate_address_count + 1));
450
451 heap_.isolate_ = this;
452 zone_.isolate_ = this;
453 stack_guard_.isolate_ = this;
454
lrn@chromium.org7516f052011-03-30 08:52:27 +0000455#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
456 defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000457 simulator_initialized_ = false;
458 simulator_i_cache_ = NULL;
459 simulator_redirection_ = NULL;
460#endif
461
462#ifdef DEBUG
463 // heap_histograms_ initializes itself.
464 memset(&js_spill_information_, 0, sizeof(js_spill_information_));
465 memset(code_kind_statistics_, 0,
466 sizeof(code_kind_statistics_[0]) * Code::NUMBER_OF_KINDS);
467#endif
468
469#ifdef ENABLE_DEBUGGER_SUPPORT
470 debug_ = NULL;
471 debugger_ = NULL;
472#endif
473
474#ifdef ENABLE_LOGGING_AND_PROFILING
475 producer_heap_profile_ = NULL;
476#endif
477
478 handle_scope_data_.Initialize();
479
480#define ISOLATE_INIT_EXECUTE(type, name, initial_value) \
481 name##_ = (initial_value);
482 ISOLATE_INIT_LIST(ISOLATE_INIT_EXECUTE)
483#undef ISOLATE_INIT_EXECUTE
484
485#define ISOLATE_INIT_ARRAY_EXECUTE(type, name, length) \
486 memset(name##_, 0, sizeof(type) * length);
487 ISOLATE_INIT_ARRAY_LIST(ISOLATE_INIT_ARRAY_EXECUTE)
488#undef ISOLATE_INIT_ARRAY_EXECUTE
489}
490
491void Isolate::TearDown() {
492 TRACE_ISOLATE(tear_down);
493
494 // Temporarily set this isolate as current so that various parts of
495 // the isolate can access it in their destructors without having a
496 // direct pointer. We don't use Enter/Exit here to avoid
497 // initializing the thread data.
498 PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData();
499 Isolate* saved_isolate = UncheckedCurrent();
500 SetIsolateThreadLocals(this, NULL);
501
502 Deinit();
503
504 if (!IsDefaultIsolate()) {
505 delete this;
506 }
507
508 // Restore the previous current isolate.
509 SetIsolateThreadLocals(saved_isolate, saved_data);
510}
511
512
513void Isolate::Deinit() {
514 if (state_ == INITIALIZED) {
515 TRACE_ISOLATE(deinit);
516
517 if (FLAG_hydrogen_stats) HStatistics::Instance()->Print();
518
519 // We must stop the logger before we tear down other components.
520 logger_->EnsureTickerStopped();
521
522 delete deoptimizer_data_;
523 deoptimizer_data_ = NULL;
524 if (FLAG_preemption) {
525 v8::Locker locker;
526 v8::Locker::StopPreemption();
527 }
528 builtins_.TearDown();
529 bootstrapper_->TearDown();
530
531 // Remove the external reference to the preallocated stack memory.
532 delete preallocated_message_space_;
533 preallocated_message_space_ = NULL;
534 PreallocatedMemoryThreadStop();
535
536 HeapProfiler::TearDown();
537 CpuProfiler::TearDown();
538 if (runtime_profiler_ != NULL) {
539 runtime_profiler_->TearDown();
540 delete runtime_profiler_;
541 runtime_profiler_ = NULL;
542 }
543 heap_.TearDown();
544 logger_->TearDown();
545
546 // The default isolate is re-initializable due to legacy API.
547 state_ = PREINITIALIZED;
548 }
549}
550
551
552void Isolate::SetIsolateThreadLocals(Isolate* isolate,
553 PerIsolateThreadData* data) {
554 Thread::SetThreadLocal(isolate_key_, isolate);
555 Thread::SetThreadLocal(per_isolate_thread_data_key_, data);
556}
557
558
559Isolate::~Isolate() {
560 TRACE_ISOLATE(destructor);
561
562#ifdef ENABLE_LOGGING_AND_PROFILING
563 delete producer_heap_profile_;
564 producer_heap_profile_ = NULL;
565#endif
566
567 delete scanner_constants_;
568 scanner_constants_ = NULL;
569
570 delete regexp_stack_;
571 regexp_stack_ = NULL;
572
573 delete ast_sentinels_;
574 ast_sentinels_ = NULL;
575
576 delete descriptor_lookup_cache_;
577 descriptor_lookup_cache_ = NULL;
578 delete context_slot_cache_;
579 context_slot_cache_ = NULL;
580 delete keyed_lookup_cache_;
581 keyed_lookup_cache_ = NULL;
582
583 delete transcendental_cache_;
584 transcendental_cache_ = NULL;
585 delete stub_cache_;
586 stub_cache_ = NULL;
587 delete stats_table_;
588 stats_table_ = NULL;
589
590 delete logger_;
591 logger_ = NULL;
592
593 delete counters_;
594 counters_ = NULL;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000595
596 delete handle_scope_implementer_;
597 handle_scope_implementer_ = NULL;
598 delete break_access_;
599 break_access_ = NULL;
600
601 delete compilation_cache_;
602 compilation_cache_ = NULL;
603 delete bootstrapper_;
604 bootstrapper_ = NULL;
605 delete pc_to_code_cache_;
606 pc_to_code_cache_ = NULL;
607 delete write_input_buffer_;
608 write_input_buffer_ = NULL;
609
610 delete context_switcher_;
611 context_switcher_ = NULL;
612 delete thread_manager_;
613 thread_manager_ = NULL;
614
615 delete string_tracker_;
616 string_tracker_ = NULL;
617
618 delete memory_allocator_;
619 memory_allocator_ = NULL;
620 delete code_range_;
621 code_range_ = NULL;
622 delete global_handles_;
623 global_handles_ = NULL;
624
625#ifdef ENABLE_DEBUGGER_SUPPORT
626 delete debugger_;
627 debugger_ = NULL;
628 delete debug_;
629 debug_ = NULL;
630#endif
631}
632
633
634bool Isolate::PreInit() {
635 if (state_ != UNINITIALIZED) return true;
636
637 TRACE_ISOLATE(preinit);
638
639 ASSERT(Isolate::Current() == this);
640
641#ifdef ENABLE_DEBUGGER_SUPPORT
642 debug_ = new Debug(this);
643 debugger_ = new Debugger();
644 debugger_->isolate_ = this;
645#endif
646
647 memory_allocator_ = new MemoryAllocator();
648 memory_allocator_->isolate_ = this;
649 code_range_ = new CodeRange();
650 code_range_->isolate_ = this;
651
652 // Safe after setting Heap::isolate_, initializing StackGuard and
653 // ensuring that Isolate::Current() == this.
654 heap_.SetStackLimits();
655
656#ifdef DEBUG
657 DisallowAllocationFailure disallow_allocation_failure;
658#endif
659
660#define C(name) isolate_addresses_[Isolate::k_##name] = \
661 reinterpret_cast<Address>(name());
662 ISOLATE_ADDRESS_LIST(C)
663 ISOLATE_ADDRESS_LIST_PROF(C)
664#undef C
665
666 string_tracker_ = new StringTracker();
667 string_tracker_->isolate_ = this;
668 thread_manager_ = new ThreadManager();
669 thread_manager_->isolate_ = this;
670 compilation_cache_ = new CompilationCache(this);
671 transcendental_cache_ = new TranscendentalCache();
672 keyed_lookup_cache_ = new KeyedLookupCache();
673 context_slot_cache_ = new ContextSlotCache();
674 descriptor_lookup_cache_ = new DescriptorLookupCache();
675 scanner_constants_ = new ScannerConstants();
676 pc_to_code_cache_ = new PcToCodeCache(this);
677 write_input_buffer_ = new StringInputBuffer();
678 global_handles_ = new GlobalHandles(this);
679 bootstrapper_ = new Bootstrapper();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000680 handle_scope_implementer_ = new HandleScopeImplementer();
681 stub_cache_ = new StubCache(this);
682 ast_sentinels_ = new AstSentinels();
683 regexp_stack_ = new RegExpStack();
684 regexp_stack_->isolate_ = this;
685
686#ifdef ENABLE_LOGGING_AND_PROFILING
687 producer_heap_profile_ = new ProducerHeapProfile();
688 producer_heap_profile_->isolate_ = this;
689#endif
690
691 state_ = PREINITIALIZED;
692 return true;
693}
694
695
696void Isolate::InitializeThreadLocal() {
697 thread_local_top_.Initialize();
698 clear_pending_exception();
699 clear_pending_message();
700 clear_scheduled_exception();
701}
702
703
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000704void Isolate::PropagatePendingExceptionToExternalTryCatch() {
705 ASSERT(has_pending_exception());
706
707 bool external_caught = IsExternallyCaught();
708 thread_local_top_.external_caught_exception_ = external_caught;
709
710 if (!external_caught) return;
711
712 if (thread_local_top_.pending_exception_ == Failure::OutOfMemoryException()) {
713 // Do not propagate OOM exception: we should kill VM asap.
714 } else if (thread_local_top_.pending_exception_ ==
715 heap()->termination_exception()) {
716 try_catch_handler()->can_continue_ = false;
717 try_catch_handler()->exception_ = heap()->null_value();
718 } else {
719 // At this point all non-object (failure) exceptions have
720 // been dealt with so this shouldn't fail.
721 ASSERT(!pending_exception()->IsFailure());
722 try_catch_handler()->can_continue_ = true;
723 try_catch_handler()->exception_ = pending_exception();
724 if (!thread_local_top_.pending_message_obj_->IsTheHole()) {
725 try_catch_handler()->message_ = thread_local_top_.pending_message_obj_;
726 }
727 }
728}
729
730
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000731bool Isolate::Init(Deserializer* des) {
732 ASSERT(state_ != INITIALIZED);
733
734 TRACE_ISOLATE(init);
735
736 bool create_heap_objects = des == NULL;
737
738#ifdef DEBUG
739 // The initialization process does not handle memory exhaustion.
740 DisallowAllocationFailure disallow_allocation_failure;
741#endif
742
743 if (state_ == UNINITIALIZED && !PreInit()) return false;
744
745 // Enable logging before setting up the heap
746 logger_->Setup();
747
748 CpuProfiler::Setup();
749 HeapProfiler::Setup();
750
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000751 // Initialize other runtime facilities
752#if defined(USE_SIMULATOR)
lrn@chromium.org7516f052011-03-30 08:52:27 +0000753#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000754 Simulator::Initialize();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000755#endif
756#endif
757
758 { // NOLINT
759 // Ensure that the thread has a valid stack guard. The v8::Locker object
760 // will ensure this too, but we don't have to use lockers if we are only
761 // using one thread.
762 ExecutionAccess lock(this);
763 stack_guard_.InitThread(lock);
764 }
765
766 // Setup the object heap
767 ASSERT(!heap_.HasBeenSetup());
768 if (!heap_.Setup(create_heap_objects)) {
769 V8::SetFatalError();
770 return false;
771 }
772
773 bootstrapper_->Initialize(create_heap_objects);
774 builtins_.Setup(create_heap_objects);
775
776 InitializeThreadLocal();
777
778 // Only preallocate on the first initialization.
779 if (FLAG_preallocate_message_memory && preallocated_message_space_ == NULL) {
780 // Start the thread which will set aside some memory.
781 PreallocatedMemoryThreadStart();
782 preallocated_message_space_ =
783 new NoAllocationStringAllocator(
784 preallocated_memory_thread_->data(),
785 preallocated_memory_thread_->length());
786 PreallocatedStorageInit(preallocated_memory_thread_->length() / 4);
787 }
788
789 if (FLAG_preemption) {
790 v8::Locker locker;
791 v8::Locker::StartPreemption(100);
792 }
793
794#ifdef ENABLE_DEBUGGER_SUPPORT
795 debug_->Setup(create_heap_objects);
796#endif
797 stub_cache_->Initialize(create_heap_objects);
798
799 // If we are deserializing, read the state into the now-empty heap.
800 if (des != NULL) {
801 des->Deserialize();
802 stub_cache_->Clear();
803 }
804
805 // Deserializing may put strange things in the root array's copy of the
806 // stack guard.
807 heap_.SetStackLimits();
808
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000809 deoptimizer_data_ = new DeoptimizerData;
810 runtime_profiler_ = new RuntimeProfiler(this);
811 runtime_profiler_->Setup();
812
813 // If we are deserializing, log non-function code objects and compiled
814 // functions found in the snapshot.
815 if (des != NULL && FLAG_log_code) {
816 HandleScope scope;
817 LOG(this, LogCodeObjects());
818 LOG(this, LogCompiledFunctions());
819 }
820
821 state_ = INITIALIZED;
822 return true;
823}
824
825
826void Isolate::Enter() {
827 Isolate* current_isolate = NULL;
828 PerIsolateThreadData* current_data = CurrentPerIsolateThreadData();
829 if (current_data != NULL) {
830 current_isolate = current_data->isolate_;
831 ASSERT(current_isolate != NULL);
832 if (current_isolate == this) {
833 ASSERT(Current() == this);
834 ASSERT(entry_stack_ != NULL);
835 ASSERT(entry_stack_->previous_thread_data == NULL ||
836 entry_stack_->previous_thread_data->thread_id() ==
837 Thread::GetThreadLocalInt(thread_id_key_));
838 // Same thread re-enters the isolate, no need to re-init anything.
839 entry_stack_->entry_count++;
840 return;
841 }
842 }
843
844 // Threads can have default isolate set into TLS as Current but not yet have
845 // PerIsolateThreadData for it, as it requires more advanced phase of the
846 // initialization. For example, a thread might be the one that system used for
847 // static initializers - in this case the default isolate is set in TLS but
848 // the thread did not yet Enter the isolate. If PerisolateThreadData is not
849 // there, use the isolate set in TLS.
850 if (current_isolate == NULL) {
851 current_isolate = Isolate::UncheckedCurrent();
852 }
853
854 PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread();
855 ASSERT(data != NULL);
856 ASSERT(data->isolate_ == this);
857
858 EntryStackItem* item = new EntryStackItem(current_data,
859 current_isolate,
860 entry_stack_);
861 entry_stack_ = item;
862
863 SetIsolateThreadLocals(this, data);
864
865 CHECK(PreInit());
866
867 // In case it's the first time some thread enters the isolate.
868 set_thread_id(data->thread_id());
869}
870
871
872void Isolate::Exit() {
873 ASSERT(entry_stack_ != NULL);
874 ASSERT(entry_stack_->previous_thread_data == NULL ||
875 entry_stack_->previous_thread_data->thread_id() ==
876 Thread::GetThreadLocalInt(thread_id_key_));
877
878 if (--entry_stack_->entry_count > 0) return;
879
880 ASSERT(CurrentPerIsolateThreadData() != NULL);
881 ASSERT(CurrentPerIsolateThreadData()->isolate_ == this);
882
883 // Pop the stack.
884 EntryStackItem* item = entry_stack_;
885 entry_stack_ = item->previous_item;
886
887 PerIsolateThreadData* previous_thread_data = item->previous_thread_data;
888 Isolate* previous_isolate = item->previous_isolate;
889
890 delete item;
891
892 // Reinit the current thread for the isolate it was running before this one.
893 SetIsolateThreadLocals(previous_isolate, previous_thread_data);
894}
895
896
897void Isolate::ResetEagerOptimizingData() {
898 compilation_cache_->ResetEagerOptimizingData();
899}
900
901
902#ifdef DEBUG
903#define ISOLATE_FIELD_OFFSET(type, name, ignored) \
904const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_);
905ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
906ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
907#undef ISOLATE_FIELD_OFFSET
908#endif
909
910} } // namespace v8::internal