blob: a1635321302c5e30c31b07ab4d8154edf5c224d0 [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()),
417 cpu_features_(NULL),
418 code_range_(NULL),
419 break_access_(OS::CreateMutex()),
420 logger_(new Logger()),
421 stats_table_(new StatsTable()),
422 stub_cache_(NULL),
423 deoptimizer_data_(NULL),
424 capture_stack_trace_for_uncaught_exceptions_(false),
425 stack_trace_for_uncaught_exceptions_frame_limit_(0),
426 stack_trace_for_uncaught_exceptions_options_(StackTrace::kOverview),
427 transcendental_cache_(NULL),
428 memory_allocator_(NULL),
429 keyed_lookup_cache_(NULL),
430 context_slot_cache_(NULL),
431 descriptor_lookup_cache_(NULL),
432 handle_scope_implementer_(NULL),
433 scanner_constants_(NULL),
434 in_use_list_(0),
435 free_list_(0),
436 preallocated_storage_preallocated_(false),
437 pc_to_code_cache_(NULL),
438 write_input_buffer_(NULL),
439 global_handles_(NULL),
440 context_switcher_(NULL),
441 thread_manager_(NULL),
442 ast_sentinels_(NULL),
443 string_tracker_(NULL),
444 regexp_stack_(NULL),
445 frame_element_constant_list_(0),
446 result_constant_list_(0) {
447 TRACE_ISOLATE(constructor);
448
449 memset(isolate_addresses_, 0,
450 sizeof(isolate_addresses_[0]) * (k_isolate_address_count + 1));
451
452 heap_.isolate_ = this;
453 zone_.isolate_ = this;
454 stack_guard_.isolate_ = this;
455
lrn@chromium.org7516f052011-03-30 08:52:27 +0000456#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
457 defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000458 simulator_initialized_ = false;
459 simulator_i_cache_ = NULL;
460 simulator_redirection_ = NULL;
461#endif
462
463#ifdef DEBUG
464 // heap_histograms_ initializes itself.
465 memset(&js_spill_information_, 0, sizeof(js_spill_information_));
466 memset(code_kind_statistics_, 0,
467 sizeof(code_kind_statistics_[0]) * Code::NUMBER_OF_KINDS);
468#endif
469
470#ifdef ENABLE_DEBUGGER_SUPPORT
471 debug_ = NULL;
472 debugger_ = NULL;
473#endif
474
475#ifdef ENABLE_LOGGING_AND_PROFILING
476 producer_heap_profile_ = NULL;
477#endif
478
479 handle_scope_data_.Initialize();
480
481#define ISOLATE_INIT_EXECUTE(type, name, initial_value) \
482 name##_ = (initial_value);
483 ISOLATE_INIT_LIST(ISOLATE_INIT_EXECUTE)
484#undef ISOLATE_INIT_EXECUTE
485
486#define ISOLATE_INIT_ARRAY_EXECUTE(type, name, length) \
487 memset(name##_, 0, sizeof(type) * length);
488 ISOLATE_INIT_ARRAY_LIST(ISOLATE_INIT_ARRAY_EXECUTE)
489#undef ISOLATE_INIT_ARRAY_EXECUTE
490}
491
492void Isolate::TearDown() {
493 TRACE_ISOLATE(tear_down);
494
495 // Temporarily set this isolate as current so that various parts of
496 // the isolate can access it in their destructors without having a
497 // direct pointer. We don't use Enter/Exit here to avoid
498 // initializing the thread data.
499 PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData();
500 Isolate* saved_isolate = UncheckedCurrent();
501 SetIsolateThreadLocals(this, NULL);
502
503 Deinit();
504
505 if (!IsDefaultIsolate()) {
506 delete this;
507 }
508
509 // Restore the previous current isolate.
510 SetIsolateThreadLocals(saved_isolate, saved_data);
511}
512
513
514void Isolate::Deinit() {
515 if (state_ == INITIALIZED) {
516 TRACE_ISOLATE(deinit);
517
518 if (FLAG_hydrogen_stats) HStatistics::Instance()->Print();
519
520 // We must stop the logger before we tear down other components.
521 logger_->EnsureTickerStopped();
522
523 delete deoptimizer_data_;
524 deoptimizer_data_ = NULL;
525 if (FLAG_preemption) {
526 v8::Locker locker;
527 v8::Locker::StopPreemption();
528 }
529 builtins_.TearDown();
530 bootstrapper_->TearDown();
531
532 // Remove the external reference to the preallocated stack memory.
533 delete preallocated_message_space_;
534 preallocated_message_space_ = NULL;
535 PreallocatedMemoryThreadStop();
536
537 HeapProfiler::TearDown();
538 CpuProfiler::TearDown();
539 if (runtime_profiler_ != NULL) {
540 runtime_profiler_->TearDown();
541 delete runtime_profiler_;
542 runtime_profiler_ = NULL;
543 }
544 heap_.TearDown();
545 logger_->TearDown();
546
547 // The default isolate is re-initializable due to legacy API.
548 state_ = PREINITIALIZED;
549 }
550}
551
552
553void Isolate::SetIsolateThreadLocals(Isolate* isolate,
554 PerIsolateThreadData* data) {
555 Thread::SetThreadLocal(isolate_key_, isolate);
556 Thread::SetThreadLocal(per_isolate_thread_data_key_, data);
557}
558
559
560Isolate::~Isolate() {
561 TRACE_ISOLATE(destructor);
562
563#ifdef ENABLE_LOGGING_AND_PROFILING
564 delete producer_heap_profile_;
565 producer_heap_profile_ = NULL;
566#endif
567
568 delete scanner_constants_;
569 scanner_constants_ = NULL;
570
571 delete regexp_stack_;
572 regexp_stack_ = NULL;
573
574 delete ast_sentinels_;
575 ast_sentinels_ = NULL;
576
577 delete descriptor_lookup_cache_;
578 descriptor_lookup_cache_ = NULL;
579 delete context_slot_cache_;
580 context_slot_cache_ = NULL;
581 delete keyed_lookup_cache_;
582 keyed_lookup_cache_ = NULL;
583
584 delete transcendental_cache_;
585 transcendental_cache_ = NULL;
586 delete stub_cache_;
587 stub_cache_ = NULL;
588 delete stats_table_;
589 stats_table_ = NULL;
590
591 delete logger_;
592 logger_ = NULL;
593
594 delete counters_;
595 counters_ = NULL;
596 delete cpu_features_;
597 cpu_features_ = NULL;
598
599 delete handle_scope_implementer_;
600 handle_scope_implementer_ = NULL;
601 delete break_access_;
602 break_access_ = NULL;
603
604 delete compilation_cache_;
605 compilation_cache_ = NULL;
606 delete bootstrapper_;
607 bootstrapper_ = NULL;
608 delete pc_to_code_cache_;
609 pc_to_code_cache_ = NULL;
610 delete write_input_buffer_;
611 write_input_buffer_ = NULL;
612
613 delete context_switcher_;
614 context_switcher_ = NULL;
615 delete thread_manager_;
616 thread_manager_ = NULL;
617
618 delete string_tracker_;
619 string_tracker_ = NULL;
620
621 delete memory_allocator_;
622 memory_allocator_ = NULL;
623 delete code_range_;
624 code_range_ = NULL;
625 delete global_handles_;
626 global_handles_ = NULL;
627
628#ifdef ENABLE_DEBUGGER_SUPPORT
629 delete debugger_;
630 debugger_ = NULL;
631 delete debug_;
632 debug_ = NULL;
633#endif
634}
635
636
637bool Isolate::PreInit() {
638 if (state_ != UNINITIALIZED) return true;
639
640 TRACE_ISOLATE(preinit);
641
642 ASSERT(Isolate::Current() == this);
643
644#ifdef ENABLE_DEBUGGER_SUPPORT
645 debug_ = new Debug(this);
646 debugger_ = new Debugger();
647 debugger_->isolate_ = this;
648#endif
649
650 memory_allocator_ = new MemoryAllocator();
651 memory_allocator_->isolate_ = this;
652 code_range_ = new CodeRange();
653 code_range_->isolate_ = this;
654
655 // Safe after setting Heap::isolate_, initializing StackGuard and
656 // ensuring that Isolate::Current() == this.
657 heap_.SetStackLimits();
658
659#ifdef DEBUG
660 DisallowAllocationFailure disallow_allocation_failure;
661#endif
662
663#define C(name) isolate_addresses_[Isolate::k_##name] = \
664 reinterpret_cast<Address>(name());
665 ISOLATE_ADDRESS_LIST(C)
666 ISOLATE_ADDRESS_LIST_PROF(C)
667#undef C
668
669 string_tracker_ = new StringTracker();
670 string_tracker_->isolate_ = this;
671 thread_manager_ = new ThreadManager();
672 thread_manager_->isolate_ = this;
673 compilation_cache_ = new CompilationCache(this);
674 transcendental_cache_ = new TranscendentalCache();
675 keyed_lookup_cache_ = new KeyedLookupCache();
676 context_slot_cache_ = new ContextSlotCache();
677 descriptor_lookup_cache_ = new DescriptorLookupCache();
678 scanner_constants_ = new ScannerConstants();
679 pc_to_code_cache_ = new PcToCodeCache(this);
680 write_input_buffer_ = new StringInputBuffer();
681 global_handles_ = new GlobalHandles(this);
682 bootstrapper_ = new Bootstrapper();
683 cpu_features_ = new CpuFeatures();
684 handle_scope_implementer_ = new HandleScopeImplementer();
685 stub_cache_ = new StubCache(this);
686 ast_sentinels_ = new AstSentinels();
687 regexp_stack_ = new RegExpStack();
688 regexp_stack_->isolate_ = this;
689
690#ifdef ENABLE_LOGGING_AND_PROFILING
691 producer_heap_profile_ = new ProducerHeapProfile();
692 producer_heap_profile_->isolate_ = this;
693#endif
694
695 state_ = PREINITIALIZED;
696 return true;
697}
698
699
700void Isolate::InitializeThreadLocal() {
701 thread_local_top_.Initialize();
702 clear_pending_exception();
703 clear_pending_message();
704 clear_scheduled_exception();
705}
706
707
708bool Isolate::Init(Deserializer* des) {
709 ASSERT(state_ != INITIALIZED);
710
711 TRACE_ISOLATE(init);
712
713 bool create_heap_objects = des == NULL;
714
715#ifdef DEBUG
716 // The initialization process does not handle memory exhaustion.
717 DisallowAllocationFailure disallow_allocation_failure;
718#endif
719
720 if (state_ == UNINITIALIZED && !PreInit()) return false;
721
722 // Enable logging before setting up the heap
723 logger_->Setup();
724
725 CpuProfiler::Setup();
726 HeapProfiler::Setup();
727
728 // Setup the platform OS support.
729 OS::Setup();
730
731 // Initialize other runtime facilities
732#if defined(USE_SIMULATOR)
lrn@chromium.org7516f052011-03-30 08:52:27 +0000733#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000734 Simulator::Initialize();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000735#endif
736#endif
737
738 { // NOLINT
739 // Ensure that the thread has a valid stack guard. The v8::Locker object
740 // will ensure this too, but we don't have to use lockers if we are only
741 // using one thread.
742 ExecutionAccess lock(this);
743 stack_guard_.InitThread(lock);
744 }
745
746 // Setup the object heap
747 ASSERT(!heap_.HasBeenSetup());
748 if (!heap_.Setup(create_heap_objects)) {
749 V8::SetFatalError();
750 return false;
751 }
752
753 bootstrapper_->Initialize(create_heap_objects);
754 builtins_.Setup(create_heap_objects);
755
756 InitializeThreadLocal();
757
758 // Only preallocate on the first initialization.
759 if (FLAG_preallocate_message_memory && preallocated_message_space_ == NULL) {
760 // Start the thread which will set aside some memory.
761 PreallocatedMemoryThreadStart();
762 preallocated_message_space_ =
763 new NoAllocationStringAllocator(
764 preallocated_memory_thread_->data(),
765 preallocated_memory_thread_->length());
766 PreallocatedStorageInit(preallocated_memory_thread_->length() / 4);
767 }
768
769 if (FLAG_preemption) {
770 v8::Locker locker;
771 v8::Locker::StartPreemption(100);
772 }
773
774#ifdef ENABLE_DEBUGGER_SUPPORT
775 debug_->Setup(create_heap_objects);
776#endif
777 stub_cache_->Initialize(create_heap_objects);
778
779 // If we are deserializing, read the state into the now-empty heap.
780 if (des != NULL) {
781 des->Deserialize();
782 stub_cache_->Clear();
783 }
784
785 // Deserializing may put strange things in the root array's copy of the
786 // stack guard.
787 heap_.SetStackLimits();
788
789 // Setup the CPU support. Must be done after heap setup and after
790 // any deserialization because we have to have the initial heap
791 // objects in place for creating the code object used for probing.
792 CPU::Setup();
793
794 deoptimizer_data_ = new DeoptimizerData;
795 runtime_profiler_ = new RuntimeProfiler(this);
796 runtime_profiler_->Setup();
797
798 // If we are deserializing, log non-function code objects and compiled
799 // functions found in the snapshot.
800 if (des != NULL && FLAG_log_code) {
801 HandleScope scope;
802 LOG(this, LogCodeObjects());
803 LOG(this, LogCompiledFunctions());
804 }
805
806 state_ = INITIALIZED;
807 return true;
808}
809
810
811void Isolate::Enter() {
812 Isolate* current_isolate = NULL;
813 PerIsolateThreadData* current_data = CurrentPerIsolateThreadData();
814 if (current_data != NULL) {
815 current_isolate = current_data->isolate_;
816 ASSERT(current_isolate != NULL);
817 if (current_isolate == this) {
818 ASSERT(Current() == this);
819 ASSERT(entry_stack_ != NULL);
820 ASSERT(entry_stack_->previous_thread_data == NULL ||
821 entry_stack_->previous_thread_data->thread_id() ==
822 Thread::GetThreadLocalInt(thread_id_key_));
823 // Same thread re-enters the isolate, no need to re-init anything.
824 entry_stack_->entry_count++;
825 return;
826 }
827 }
828
829 // Threads can have default isolate set into TLS as Current but not yet have
830 // PerIsolateThreadData for it, as it requires more advanced phase of the
831 // initialization. For example, a thread might be the one that system used for
832 // static initializers - in this case the default isolate is set in TLS but
833 // the thread did not yet Enter the isolate. If PerisolateThreadData is not
834 // there, use the isolate set in TLS.
835 if (current_isolate == NULL) {
836 current_isolate = Isolate::UncheckedCurrent();
837 }
838
839 PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread();
840 ASSERT(data != NULL);
841 ASSERT(data->isolate_ == this);
842
843 EntryStackItem* item = new EntryStackItem(current_data,
844 current_isolate,
845 entry_stack_);
846 entry_stack_ = item;
847
848 SetIsolateThreadLocals(this, data);
849
850 CHECK(PreInit());
851
852 // In case it's the first time some thread enters the isolate.
853 set_thread_id(data->thread_id());
854}
855
856
857void Isolate::Exit() {
858 ASSERT(entry_stack_ != NULL);
859 ASSERT(entry_stack_->previous_thread_data == NULL ||
860 entry_stack_->previous_thread_data->thread_id() ==
861 Thread::GetThreadLocalInt(thread_id_key_));
862
863 if (--entry_stack_->entry_count > 0) return;
864
865 ASSERT(CurrentPerIsolateThreadData() != NULL);
866 ASSERT(CurrentPerIsolateThreadData()->isolate_ == this);
867
868 // Pop the stack.
869 EntryStackItem* item = entry_stack_;
870 entry_stack_ = item->previous_item;
871
872 PerIsolateThreadData* previous_thread_data = item->previous_thread_data;
873 Isolate* previous_isolate = item->previous_isolate;
874
875 delete item;
876
877 // Reinit the current thread for the isolate it was running before this one.
878 SetIsolateThreadLocals(previous_isolate, previous_thread_data);
879}
880
881
882void Isolate::ResetEagerOptimizingData() {
883 compilation_cache_->ResetEagerOptimizingData();
884}
885
886
887#ifdef DEBUG
888#define ISOLATE_FIELD_OFFSET(type, name, ignored) \
889const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_);
890ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
891ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
892#undef ISOLATE_FIELD_OFFSET
893#endif
894
895} } // namespace v8::internal