1 // Copyright 2011 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 #ifndef V8_ISOLATE_H_
29 #define V8_ISOLATE_H_
30
31 #include "../include/v8-debug.h"
32 #include "allocation.h"
33 #include "apiutils.h"
34 #include "atomicops.h"
35 #include "builtins.h"
36 #include "contexts.h"
37 #include "execution.h"
38 #include "frames.h"
39 #include "global-handles.h"
40 #include "handles.h"
41 #include "heap.h"
42 #include "regexp-stack.h"
43 #include "runtime-profiler.h"
44 #include "runtime.h"
45 #include "zone.h"
46
47 namespace v8 {
48 namespace internal {
49
50 class AstSentinels;
51 class Bootstrapper;
52 class CodeGenerator;
53 class CodeRange;
54 class CompilationCache;
55 class ContextSlotCache;
56 class ContextSwitcher;
57 class Counters;
58 class CpuFeatures;
59 class CpuProfiler;
60 class DeoptimizerData;
61 class Deserializer;
62 class EmptyStatement;
63 class ExternalReferenceTable;
64 class Factory;
65 class FunctionInfoListener;
66 class HandleScopeImplementer;
67 class HeapProfiler;
68 class InlineRuntimeFunctionsTable;
69 class NoAllocationStringAllocator;
70 class PcToCodeCache;
71 class PreallocatedMemoryThread;
72 class ProducerHeapProfile;
73 class RegExpStack;
74 class SaveContext;
75 class UnicodeCache;
76 class StringInputBuffer;
77 class StringTracker;
78 class StubCache;
79 class ThreadManager;
80 class ThreadState;
81 class ThreadVisitor; // Defined in v8threads.h
82 class VMState;
83
84 // 'void function pointer', used to roundtrip the
85 // ExternalReference::ExternalReferenceRedirector since we can not include
86 // assembler.h, where it is defined, here.
87 typedef void* ExternalReferenceRedirectorPointer();
88
89
90 #ifdef ENABLE_DEBUGGER_SUPPORT
91 class Debug;
92 class Debugger;
93 class DebuggerAgent;
94 #endif
95
96 #if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
97 !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
98 class Redirection;
99 class Simulator;
100 #endif
101
102
103 // Static indirection table for handles to constants. If a frame
104 // element represents a constant, the data contains an index into
105 // this table of handles to the actual constants.
106 // Static indirection table for handles to constants. If a Result
107 // represents a constant, the data contains an index into this table
108 // of handles to the actual constants.
109 typedef ZoneList<Handle<Object> > ZoneObjectList;
110
111 #define RETURN_IF_SCHEDULED_EXCEPTION(isolate) \
112 if (isolate->has_scheduled_exception()) \
113 return isolate->PromoteScheduledException()
114
115 #define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value) \
116 if (call.is_null()) { \
117 ASSERT(isolate->has_pending_exception()); \
118 return value; \
119 }
120
121 #define RETURN_IF_EMPTY_HANDLE(isolate, call) \
122 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, Failure::Exception())
123
124 #define ISOLATE_ADDRESS_LIST(C) \
125 C(handler_address) \
126 C(c_entry_fp_address) \
127 C(context_address) \
128 C(pending_exception_address) \
129 C(external_caught_exception_address)
130
131 #ifdef ENABLE_LOGGING_AND_PROFILING
132 #define ISOLATE_ADDRESS_LIST_PROF(C) \
133 C(js_entry_sp_address)
134 #else
135 #define ISOLATE_ADDRESS_LIST_PROF(C)
136 #endif
137
138
139 // Platform-independent, reliable thread identifier.
140 class ThreadId {
141 public:
142 // Creates an invalid ThreadId.
ThreadId()143 ThreadId() : id_(kInvalidId) {}
144
145 // Returns ThreadId for current thread.
Current()146 static ThreadId Current() { return ThreadId(GetCurrentThreadId()); }
147
148 // Returns invalid ThreadId (guaranteed not to be equal to any thread).
Invalid()149 static ThreadId Invalid() { return ThreadId(kInvalidId); }
150
151 // Compares ThreadIds for equality.
INLINE(bool Equals (const ThreadId & other)const)152 INLINE(bool Equals(const ThreadId& other) const) {
153 return id_ == other.id_;
154 }
155
156 // Checks whether this ThreadId refers to any thread.
INLINE(bool IsValid ()const)157 INLINE(bool IsValid() const) {
158 return id_ != kInvalidId;
159 }
160
161 // Converts ThreadId to an integer representation
162 // (required for public API: V8::V8::GetCurrentThreadId).
ToInteger()163 int ToInteger() const { return id_; }
164
165 // Converts ThreadId to an integer representation
166 // (required for public API: V8::V8::TerminateExecution).
FromInteger(int id)167 static ThreadId FromInteger(int id) { return ThreadId(id); }
168
169 private:
170 static const int kInvalidId = -1;
171
ThreadId(int id)172 explicit ThreadId(int id) : id_(id) {}
173
174 static int AllocateThreadId();
175
176 static int GetCurrentThreadId();
177
178 int id_;
179
180 static Atomic32 highest_thread_id_;
181
182 friend class Isolate;
183 };
184
185
186 class ThreadLocalTop BASE_EMBEDDED {
187 public:
188 // Does early low-level initialization that does not depend on the
189 // isolate being present.
190 ThreadLocalTop();
191
192 // Initialize the thread data.
193 void Initialize();
194
195 // Get the top C++ try catch handler or NULL if none are registered.
196 //
197 // This method is not guarenteed to return an address that can be
198 // used for comparison with addresses into the JS stack. If such an
199 // address is needed, use try_catch_handler_address.
200 v8::TryCatch* TryCatchHandler();
201
202 // Get the address of the top C++ try catch handler or NULL if
203 // none are registered.
204 //
205 // This method always returns an address that can be compared to
206 // pointers into the JavaScript stack. When running on actual
207 // hardware, try_catch_handler_address and TryCatchHandler return
208 // the same pointer. When running on a simulator with a separate JS
209 // stack, try_catch_handler_address returns a JS stack address that
210 // corresponds to the place on the JS stack where the C++ handler
211 // would have been if the stack were not separate.
try_catch_handler_address()212 inline Address try_catch_handler_address() {
213 return try_catch_handler_address_;
214 }
215
216 // Set the address of the top C++ try catch handler.
set_try_catch_handler_address(Address address)217 inline void set_try_catch_handler_address(Address address) {
218 try_catch_handler_address_ = address;
219 }
220
Free()221 void Free() {
222 ASSERT(!has_pending_message_);
223 ASSERT(!external_caught_exception_);
224 ASSERT(try_catch_handler_address_ == NULL);
225 }
226
227 // The context where the current execution method is created and for variable
228 // lookups.
229 Context* context_;
230 ThreadId thread_id_;
231 MaybeObject* pending_exception_;
232 bool has_pending_message_;
233 Object* pending_message_obj_;
234 Script* pending_message_script_;
235 int pending_message_start_pos_;
236 int pending_message_end_pos_;
237 // Use a separate value for scheduled exceptions to preserve the
238 // invariants that hold about pending_exception. We may want to
239 // unify them later.
240 MaybeObject* scheduled_exception_;
241 bool external_caught_exception_;
242 SaveContext* save_context_;
243 v8::TryCatch* catcher_;
244
245 // Stack.
246 Address c_entry_fp_; // the frame pointer of the top c entry frame
247 Address handler_; // try-blocks are chained through the stack
248
249 #ifdef USE_SIMULATOR
250 #if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
251 Simulator* simulator_;
252 #endif
253 #endif // USE_SIMULATOR
254
255 #ifdef ENABLE_LOGGING_AND_PROFILING
256 Address js_entry_sp_; // the stack pointer of the bottom js entry frame
257 Address external_callback_; // the external callback we're currently in
258 #endif
259
260 #ifdef ENABLE_VMSTATE_TRACKING
261 StateTag current_vm_state_;
262 #endif
263
264 // Generated code scratch locations.
265 int32_t formal_count_;
266
267 // Call back function to report unsafe JS accesses.
268 v8::FailedAccessCheckCallback failed_access_check_callback_;
269
270 // Whether out of memory exceptions should be ignored.
271 bool ignore_out_of_memory_;
272
273 private:
274 void InitializeInternal();
275
276 Address try_catch_handler_address_;
277 };
278
279 #if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
280
281 #define ISOLATE_PLATFORM_INIT_LIST(V) \
282 /* VirtualFrame::SpilledScope state */ \
283 V(bool, is_virtual_frame_in_spilled_scope, false) \
284 /* CodeGenerator::EmitNamedStore state */ \
285 V(int, inlined_write_barrier_size, -1)
286
287 #if !defined(__arm__) && !defined(__mips__)
288 class HashMap;
289 #endif
290
291 #else
292
293 #define ISOLATE_PLATFORM_INIT_LIST(V)
294
295 #endif
296
297 #ifdef ENABLE_DEBUGGER_SUPPORT
298
299 #define ISOLATE_DEBUGGER_INIT_LIST(V) \
300 V(uint64_t, enabled_cpu_features, 0) \
301 V(v8::Debug::EventCallback, debug_event_callback, NULL) \
302 V(DebuggerAgent*, debugger_agent_instance, NULL)
303 #else
304
305 #define ISOLATE_DEBUGGER_INIT_LIST(V)
306
307 #endif
308
309 #ifdef DEBUG
310
311 #define ISOLATE_INIT_DEBUG_ARRAY_LIST(V) \
312 V(CommentStatistic, paged_space_comments_statistics, \
313 CommentStatistic::kMaxComments + 1)
314 #else
315
316 #define ISOLATE_INIT_DEBUG_ARRAY_LIST(V)
317
318 #endif
319
320 #ifdef ENABLE_LOGGING_AND_PROFILING
321
322 #define ISOLATE_LOGGING_INIT_LIST(V) \
323 V(CpuProfiler*, cpu_profiler, NULL) \
324 V(HeapProfiler*, heap_profiler, NULL)
325
326 #else
327
328 #define ISOLATE_LOGGING_INIT_LIST(V)
329
330 #endif
331
332 #define ISOLATE_INIT_ARRAY_LIST(V) \
333 /* SerializerDeserializer state. */ \
334 V(Object*, serialize_partial_snapshot_cache, kPartialSnapshotCacheCapacity) \
335 V(int, jsregexp_static_offsets_vector, kJSRegexpStaticOffsetsVectorSize) \
336 V(int, bad_char_shift_table, kUC16AlphabetSize) \
337 V(int, good_suffix_shift_table, (kBMMaxShift + 1)) \
338 V(int, suffix_table, (kBMMaxShift + 1)) \
339 ISOLATE_INIT_DEBUG_ARRAY_LIST(V)
340
341 typedef List<HeapObject*, PreallocatedStorage> DebugObjectCache;
342
343 #define ISOLATE_INIT_LIST(V) \
344 /* AssertNoZoneAllocation state. */ \
345 V(bool, zone_allow_allocation, true) \
346 /* SerializerDeserializer state. */ \
347 V(int, serialize_partial_snapshot_cache_length, 0) \
348 /* Assembler state. */ \
349 /* A previously allocated buffer of kMinimalBufferSize bytes, or NULL. */ \
350 V(byte*, assembler_spare_buffer, NULL) \
351 V(FatalErrorCallback, exception_behavior, NULL) \
352 V(v8::Debug::MessageHandler, message_handler, NULL) \
353 /* To distinguish the function templates, so that we can find them in the */ \
354 /* function cache of the global context. */ \
355 V(int, next_serial_number, 0) \
356 V(ExternalReferenceRedirectorPointer*, external_reference_redirector, NULL) \
357 V(bool, always_allow_natives_syntax, false) \
358 /* Part of the state of liveedit. */ \
359 V(FunctionInfoListener*, active_function_info_listener, NULL) \
360 /* State for Relocatable. */ \
361 V(Relocatable*, relocatable_top, NULL) \
362 /* State for CodeEntry in profile-generator. */ \
363 V(CodeGenerator*, current_code_generator, NULL) \
364 V(bool, jump_target_compiling_deferred_code, false) \
365 V(DebugObjectCache*, string_stream_debug_object_cache, NULL) \
366 V(Object*, string_stream_current_security_token, NULL) \
367 /* TODO(isolates): Release this on destruction? */ \
368 V(int*, irregexp_interpreter_backtrack_stack_cache, NULL) \
369 /* Serializer state. */ \
370 V(ExternalReferenceTable*, external_reference_table, NULL) \
371 /* AstNode state. */ \
372 V(unsigned, ast_node_id, 0) \
373 V(unsigned, ast_node_count, 0) \
374 /* SafeStackFrameIterator activations count. */ \
375 V(int, safe_stack_iterator_counter, 0) \
376 ISOLATE_PLATFORM_INIT_LIST(V) \
377 ISOLATE_LOGGING_INIT_LIST(V) \
378 ISOLATE_DEBUGGER_INIT_LIST(V)
379
380 class Isolate {
381 // These forward declarations are required to make the friend declarations in
382 // PerIsolateThreadData work on some older versions of gcc.
383 class ThreadDataTable;
384 class EntryStackItem;
385 public:
386 ~Isolate();
387
388 // A thread has a PerIsolateThreadData instance for each isolate that it has
389 // entered. That instance is allocated when the isolate is initially entered
390 // and reused on subsequent entries.
391 class PerIsolateThreadData {
392 public:
PerIsolateThreadData(Isolate * isolate,ThreadId thread_id)393 PerIsolateThreadData(Isolate* isolate, ThreadId thread_id)
394 : isolate_(isolate),
395 thread_id_(thread_id),
396 stack_limit_(0),
397 thread_state_(NULL),
398 #if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
399 !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
400 simulator_(NULL),
401 #endif
402 next_(NULL),
403 prev_(NULL) { }
isolate()404 Isolate* isolate() const { return isolate_; }
thread_id()405 ThreadId thread_id() const { return thread_id_; }
set_stack_limit(uintptr_t value)406 void set_stack_limit(uintptr_t value) { stack_limit_ = value; }
stack_limit()407 uintptr_t stack_limit() const { return stack_limit_; }
thread_state()408 ThreadState* thread_state() const { return thread_state_; }
set_thread_state(ThreadState * value)409 void set_thread_state(ThreadState* value) { thread_state_ = value; }
410
411 #if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
412 !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
simulator()413 Simulator* simulator() const { return simulator_; }
set_simulator(Simulator * simulator)414 void set_simulator(Simulator* simulator) {
415 simulator_ = simulator;
416 }
417 #endif
418
Matches(Isolate * isolate,ThreadId thread_id)419 bool Matches(Isolate* isolate, ThreadId thread_id) const {
420 return isolate_ == isolate && thread_id_.Equals(thread_id);
421 }
422
423 private:
424 Isolate* isolate_;
425 ThreadId thread_id_;
426 uintptr_t stack_limit_;
427 ThreadState* thread_state_;
428
429 #if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
430 !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
431 Simulator* simulator_;
432 #endif
433
434 PerIsolateThreadData* next_;
435 PerIsolateThreadData* prev_;
436
437 friend class Isolate;
438 friend class ThreadDataTable;
439 friend class EntryStackItem;
440
441 DISALLOW_COPY_AND_ASSIGN(PerIsolateThreadData);
442 };
443
444
445 enum AddressId {
446 #define C(name) k_##name,
447 ISOLATE_ADDRESS_LIST(C)
448 ISOLATE_ADDRESS_LIST_PROF(C)
449 #undef C
450 k_isolate_address_count
451 };
452
453 // Returns the PerIsolateThreadData for the current thread (or NULL if one is
454 // not currently set).
CurrentPerIsolateThreadData()455 static PerIsolateThreadData* CurrentPerIsolateThreadData() {
456 return reinterpret_cast<PerIsolateThreadData*>(
457 Thread::GetThreadLocal(per_isolate_thread_data_key_));
458 }
459
460 // Returns the isolate inside which the current thread is running.
INLINE(static Isolate * Current ())461 INLINE(static Isolate* Current()) {
462 Isolate* isolate = reinterpret_cast<Isolate*>(
463 Thread::GetExistingThreadLocal(isolate_key_));
464 ASSERT(isolate != NULL);
465 return isolate;
466 }
467
INLINE(static Isolate * UncheckedCurrent ())468 INLINE(static Isolate* UncheckedCurrent()) {
469 return reinterpret_cast<Isolate*>(Thread::GetThreadLocal(isolate_key_));
470 }
471
472 // Usually called by Init(), but can be called early e.g. to allow
473 // testing components that require logging but not the whole
474 // isolate.
475 //
476 // Safe to call more than once.
477 void InitializeLoggingAndCounters();
478
479 bool Init(Deserializer* des);
480
IsInitialized()481 bool IsInitialized() { return state_ == INITIALIZED; }
482
483 // True if at least one thread Enter'ed this isolate.
IsInUse()484 bool IsInUse() { return entry_stack_ != NULL; }
485
486 // Destroys the non-default isolates.
487 // Sets default isolate into "has_been_disposed" state rather then destroying,
488 // for legacy API reasons.
489 void TearDown();
490
IsDefaultIsolate()491 bool IsDefaultIsolate() const { return this == default_isolate_; }
492
493 // Ensures that process-wide resources and the default isolate have been
494 // allocated. It is only necessary to call this method in rare casses, for
495 // example if you are using V8 from within the body of a static initializer.
496 // Safe to call multiple times.
497 static void EnsureDefaultIsolate();
498
499 // Get the debugger from the default isolate. Preinitializes the
500 // default isolate if needed.
501 static Debugger* GetDefaultIsolateDebugger();
502
503 // Get the stack guard from the default isolate. Preinitializes the
504 // default isolate if needed.
505 static StackGuard* GetDefaultIsolateStackGuard();
506
507 // Returns the key used to store the pointer to the current isolate.
508 // Used internally for V8 threads that do not execute JavaScript but still
509 // are part of the domain of an isolate (like the context switcher).
isolate_key()510 static Thread::LocalStorageKey isolate_key() {
511 return isolate_key_;
512 }
513
514 // Returns the key used to store process-wide thread IDs.
thread_id_key()515 static Thread::LocalStorageKey thread_id_key() {
516 return thread_id_key_;
517 }
518
519 // If a client attempts to create a Locker without specifying an isolate,
520 // we assume that the client is using legacy behavior. Set up the current
521 // thread to be inside the implicit isolate (or fail a check if we have
522 // switched to non-legacy behavior).
523 static void EnterDefaultIsolate();
524
525 // Mutex for serializing access to break control structures.
break_access()526 Mutex* break_access() { return break_access_; }
527
528 // Mutex for serializing access to debugger.
debugger_access()529 Mutex* debugger_access() { return debugger_access_; }
530
531 Address get_address_from_id(AddressId id);
532
533 // Access to top context (where the current function object was created).
context()534 Context* context() { return thread_local_top_.context_; }
set_context(Context * context)535 void set_context(Context* context) {
536 thread_local_top_.context_ = context;
537 }
context_address()538 Context** context_address() { return &thread_local_top_.context_; }
539
save_context()540 SaveContext* save_context() {return thread_local_top_.save_context_; }
set_save_context(SaveContext * save)541 void set_save_context(SaveContext* save) {
542 thread_local_top_.save_context_ = save;
543 }
544
545 // Access to current thread id.
thread_id()546 ThreadId thread_id() { return thread_local_top_.thread_id_; }
set_thread_id(ThreadId id)547 void set_thread_id(ThreadId id) { thread_local_top_.thread_id_ = id; }
548
549 // Interface to pending exception.
pending_exception()550 MaybeObject* pending_exception() {
551 ASSERT(has_pending_exception());
552 return thread_local_top_.pending_exception_;
553 }
external_caught_exception()554 bool external_caught_exception() {
555 return thread_local_top_.external_caught_exception_;
556 }
set_external_caught_exception(bool value)557 void set_external_caught_exception(bool value) {
558 thread_local_top_.external_caught_exception_ = value;
559 }
set_pending_exception(MaybeObject * exception)560 void set_pending_exception(MaybeObject* exception) {
561 thread_local_top_.pending_exception_ = exception;
562 }
clear_pending_exception()563 void clear_pending_exception() {
564 thread_local_top_.pending_exception_ = heap_.the_hole_value();
565 }
pending_exception_address()566 MaybeObject** pending_exception_address() {
567 return &thread_local_top_.pending_exception_;
568 }
has_pending_exception()569 bool has_pending_exception() {
570 return !thread_local_top_.pending_exception_->IsTheHole();
571 }
clear_pending_message()572 void clear_pending_message() {
573 thread_local_top_.has_pending_message_ = false;
574 thread_local_top_.pending_message_obj_ = heap_.the_hole_value();
575 thread_local_top_.pending_message_script_ = NULL;
576 }
try_catch_handler()577 v8::TryCatch* try_catch_handler() {
578 return thread_local_top_.TryCatchHandler();
579 }
try_catch_handler_address()580 Address try_catch_handler_address() {
581 return thread_local_top_.try_catch_handler_address();
582 }
external_caught_exception_address()583 bool* external_caught_exception_address() {
584 return &thread_local_top_.external_caught_exception_;
585 }
catcher()586 v8::TryCatch* catcher() {
587 return thread_local_top_.catcher_;
588 }
set_catcher(v8::TryCatch * catcher)589 void set_catcher(v8::TryCatch* catcher) {
590 thread_local_top_.catcher_ = catcher;
591 }
592
scheduled_exception_address()593 MaybeObject** scheduled_exception_address() {
594 return &thread_local_top_.scheduled_exception_;
595 }
scheduled_exception()596 MaybeObject* scheduled_exception() {
597 ASSERT(has_scheduled_exception());
598 return thread_local_top_.scheduled_exception_;
599 }
has_scheduled_exception()600 bool has_scheduled_exception() {
601 return !thread_local_top_.scheduled_exception_->IsTheHole();
602 }
clear_scheduled_exception()603 void clear_scheduled_exception() {
604 thread_local_top_.scheduled_exception_ = heap_.the_hole_value();
605 }
606
607 bool IsExternallyCaught();
608
is_catchable_by_javascript(MaybeObject * exception)609 bool is_catchable_by_javascript(MaybeObject* exception) {
610 return (exception != Failure::OutOfMemoryException()) &&
611 (exception != heap()->termination_exception());
612 }
613
614 // JS execution stack (see frames.h).
c_entry_fp(ThreadLocalTop * thread)615 static Address c_entry_fp(ThreadLocalTop* thread) {
616 return thread->c_entry_fp_;
617 }
handler(ThreadLocalTop * thread)618 static Address handler(ThreadLocalTop* thread) { return thread->handler_; }
619
c_entry_fp_address()620 inline Address* c_entry_fp_address() {
621 return &thread_local_top_.c_entry_fp_;
622 }
handler_address()623 inline Address* handler_address() { return &thread_local_top_.handler_; }
624
625 #ifdef ENABLE_LOGGING_AND_PROFILING
626 // Bottom JS entry (see StackTracer::Trace in log.cc).
js_entry_sp(ThreadLocalTop * thread)627 static Address js_entry_sp(ThreadLocalTop* thread) {
628 return thread->js_entry_sp_;
629 }
js_entry_sp_address()630 inline Address* js_entry_sp_address() {
631 return &thread_local_top_.js_entry_sp_;
632 }
633 #endif
634
635 // Generated code scratch locations.
formal_count_address()636 void* formal_count_address() { return &thread_local_top_.formal_count_; }
637
638 // Returns the global object of the current context. It could be
639 // a builtin object, or a js global object.
global()640 Handle<GlobalObject> global() {
641 return Handle<GlobalObject>(context()->global());
642 }
643
644 // Returns the global proxy object of the current context.
global_proxy()645 Object* global_proxy() {
646 return context()->global_proxy();
647 }
648
js_builtins_object()649 Handle<JSBuiltinsObject> js_builtins_object() {
650 return Handle<JSBuiltinsObject>(thread_local_top_.context_->builtins());
651 }
652
ArchiveSpacePerThread()653 static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); }
FreeThreadResources()654 void FreeThreadResources() { thread_local_top_.Free(); }
655
656 // This method is called by the api after operations that may throw
657 // exceptions. If an exception was thrown and not handled by an external
658 // handler the exception is scheduled to be rethrown when we return to running
659 // JavaScript code. If an exception is scheduled true is returned.
660 bool OptionalRescheduleException(bool is_bottom_call);
661
662 class ExceptionScope {
663 public:
ExceptionScope(Isolate * isolate)664 explicit ExceptionScope(Isolate* isolate) :
665 // Scope currently can only be used for regular exceptions, not
666 // failures like OOM or termination exception.
667 isolate_(isolate),
668 pending_exception_(isolate_->pending_exception()->ToObjectUnchecked()),
669 catcher_(isolate_->catcher())
670 { }
671
~ExceptionScope()672 ~ExceptionScope() {
673 isolate_->set_catcher(catcher_);
674 isolate_->set_pending_exception(*pending_exception_);
675 }
676
677 private:
678 Isolate* isolate_;
679 Handle<Object> pending_exception_;
680 v8::TryCatch* catcher_;
681 };
682
683 void SetCaptureStackTraceForUncaughtExceptions(
684 bool capture,
685 int frame_limit,
686 StackTrace::StackTraceOptions options);
687
688 // Tells whether the current context has experienced an out of memory
689 // exception.
690 bool is_out_of_memory();
ignore_out_of_memory()691 bool ignore_out_of_memory() {
692 return thread_local_top_.ignore_out_of_memory_;
693 }
set_ignore_out_of_memory(bool value)694 void set_ignore_out_of_memory(bool value) {
695 thread_local_top_.ignore_out_of_memory_ = value;
696 }
697
698 void PrintCurrentStackTrace(FILE* out);
699 void PrintStackTrace(FILE* out, char* thread_data);
700 void PrintStack(StringStream* accumulator);
701 void PrintStack();
702 Handle<String> StackTraceString();
703 Handle<JSArray> CaptureCurrentStackTrace(
704 int frame_limit,
705 StackTrace::StackTraceOptions options);
706
707 // Returns if the top context may access the given global object. If
708 // the result is false, the pending exception is guaranteed to be
709 // set.
710 bool MayNamedAccess(JSObject* receiver,
711 Object* key,
712 v8::AccessType type);
713 bool MayIndexedAccess(JSObject* receiver,
714 uint32_t index,
715 v8::AccessType type);
716
717 void SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback);
718 void ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type);
719
720 // Exception throwing support. The caller should use the result
721 // of Throw() as its return value.
722 Failure* Throw(Object* exception, MessageLocation* location = NULL);
723 // Re-throw an exception. This involves no error reporting since
724 // error reporting was handled when the exception was thrown
725 // originally.
726 Failure* ReThrow(MaybeObject* exception, MessageLocation* location = NULL);
727 void ScheduleThrow(Object* exception);
728 void ReportPendingMessages();
729 Failure* ThrowIllegalOperation();
730
731 // Promote a scheduled exception to pending. Asserts has_scheduled_exception.
732 Failure* PromoteScheduledException();
733 void DoThrow(MaybeObject* exception, MessageLocation* location);
734 // Checks if exception should be reported and finds out if it's
735 // caught externally.
736 bool ShouldReportException(bool* can_be_caught_externally,
737 bool catchable_by_javascript);
738
739 // Attempts to compute the current source location, storing the
740 // result in the target out parameter.
741 void ComputeLocation(MessageLocation* target);
742
743 // Override command line flag.
744 void TraceException(bool flag);
745
746 // Out of resource exception helpers.
747 Failure* StackOverflow();
748 Failure* TerminateExecution();
749
750 // Administration
751 void Iterate(ObjectVisitor* v);
752 void Iterate(ObjectVisitor* v, ThreadLocalTop* t);
753 char* Iterate(ObjectVisitor* v, char* t);
754 void IterateThread(ThreadVisitor* v);
755 void IterateThread(ThreadVisitor* v, char* t);
756
757
758 // Returns the current global context.
759 Handle<Context> global_context();
760
761 // Returns the global context of the calling JavaScript code. That
762 // is, the global context of the top-most JavaScript frame.
763 Handle<Context> GetCallingGlobalContext();
764
765 void RegisterTryCatchHandler(v8::TryCatch* that);
766 void UnregisterTryCatchHandler(v8::TryCatch* that);
767
768 char* ArchiveThread(char* to);
769 char* RestoreThread(char* from);
770
771 static const char* const kStackOverflowMessage;
772
773 static const int kUC16AlphabetSize = 256; // See StringSearchBase.
774 static const int kBMMaxShift = 250; // See StringSearchBase.
775
776 // Accessors.
777 #define GLOBAL_ACCESSOR(type, name, initialvalue) \
778 inline type name() const { \
779 ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_); \
780 return name##_; \
781 } \
782 inline void set_##name(type value) { \
783 ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_); \
784 name##_ = value; \
785 }
786 ISOLATE_INIT_LIST(GLOBAL_ACCESSOR)
787 #undef GLOBAL_ACCESSOR
788
789 #define GLOBAL_ARRAY_ACCESSOR(type, name, length) \
790 inline type* name() { \
791 ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_); \
792 return &(name##_)[0]; \
793 }
ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_ACCESSOR)794 ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_ACCESSOR)
795 #undef GLOBAL_ARRAY_ACCESSOR
796
797 #define GLOBAL_CONTEXT_FIELD_ACCESSOR(index, type, name) \
798 Handle<type> name() { \
799 return Handle<type>(context()->global_context()->name()); \
800 }
801 GLOBAL_CONTEXT_FIELDS(GLOBAL_CONTEXT_FIELD_ACCESSOR)
802 #undef GLOBAL_CONTEXT_FIELD_ACCESSOR
803
804 Bootstrapper* bootstrapper() { return bootstrapper_; }
counters()805 Counters* counters() {
806 // Call InitializeLoggingAndCounters() if logging is needed before
807 // the isolate is fully initialized.
808 ASSERT(counters_ != NULL);
809 return counters_;
810 }
code_range()811 CodeRange* code_range() { return code_range_; }
runtime_profiler()812 RuntimeProfiler* runtime_profiler() { return runtime_profiler_; }
compilation_cache()813 CompilationCache* compilation_cache() { return compilation_cache_; }
logger()814 Logger* logger() {
815 // Call InitializeLoggingAndCounters() if logging is needed before
816 // the isolate is fully initialized.
817 ASSERT(logger_ != NULL);
818 return logger_;
819 }
stack_guard()820 StackGuard* stack_guard() { return &stack_guard_; }
heap()821 Heap* heap() { return &heap_; }
822 StatsTable* stats_table();
stub_cache()823 StubCache* stub_cache() { return stub_cache_; }
deoptimizer_data()824 DeoptimizerData* deoptimizer_data() { return deoptimizer_data_; }
thread_local_top()825 ThreadLocalTop* thread_local_top() { return &thread_local_top_; }
826
transcendental_cache()827 TranscendentalCache* transcendental_cache() const {
828 return transcendental_cache_;
829 }
830
memory_allocator()831 MemoryAllocator* memory_allocator() {
832 return memory_allocator_;
833 }
834
keyed_lookup_cache()835 KeyedLookupCache* keyed_lookup_cache() {
836 return keyed_lookup_cache_;
837 }
838
context_slot_cache()839 ContextSlotCache* context_slot_cache() {
840 return context_slot_cache_;
841 }
842
descriptor_lookup_cache()843 DescriptorLookupCache* descriptor_lookup_cache() {
844 return descriptor_lookup_cache_;
845 }
846
handle_scope_data()847 v8::ImplementationUtilities::HandleScopeData* handle_scope_data() {
848 return &handle_scope_data_;
849 }
handle_scope_implementer()850 HandleScopeImplementer* handle_scope_implementer() {
851 ASSERT(handle_scope_implementer_);
852 return handle_scope_implementer_;
853 }
zone()854 Zone* zone() { return &zone_; }
855
unicode_cache()856 UnicodeCache* unicode_cache() {
857 return unicode_cache_;
858 }
859
pc_to_code_cache()860 PcToCodeCache* pc_to_code_cache() { return pc_to_code_cache_; }
861
write_input_buffer()862 StringInputBuffer* write_input_buffer() { return write_input_buffer_; }
863
global_handles()864 GlobalHandles* global_handles() { return global_handles_; }
865
thread_manager()866 ThreadManager* thread_manager() { return thread_manager_; }
867
context_switcher()868 ContextSwitcher* context_switcher() { return context_switcher_; }
869
set_context_switcher(ContextSwitcher * switcher)870 void set_context_switcher(ContextSwitcher* switcher) {
871 context_switcher_ = switcher;
872 }
873
string_tracker()874 StringTracker* string_tracker() { return string_tracker_; }
875
jsregexp_uncanonicalize()876 unibrow::Mapping<unibrow::Ecma262UnCanonicalize>* jsregexp_uncanonicalize() {
877 return &jsregexp_uncanonicalize_;
878 }
879
jsregexp_canonrange()880 unibrow::Mapping<unibrow::CanonicalizationRange>* jsregexp_canonrange() {
881 return &jsregexp_canonrange_;
882 }
883
objects_string_compare_buffer_a()884 StringInputBuffer* objects_string_compare_buffer_a() {
885 return &objects_string_compare_buffer_a_;
886 }
887
objects_string_compare_buffer_b()888 StringInputBuffer* objects_string_compare_buffer_b() {
889 return &objects_string_compare_buffer_b_;
890 }
891
objects_string_input_buffer()892 StaticResource<StringInputBuffer>* objects_string_input_buffer() {
893 return &objects_string_input_buffer_;
894 }
895
ast_sentinels()896 AstSentinels* ast_sentinels() { return ast_sentinels_; }
897
runtime_state()898 RuntimeState* runtime_state() { return &runtime_state_; }
899
liveedit_compare_substrings_buf1()900 StringInputBuffer* liveedit_compare_substrings_buf1() {
901 return &liveedit_compare_substrings_buf1_;
902 }
903
liveedit_compare_substrings_buf2()904 StringInputBuffer* liveedit_compare_substrings_buf2() {
905 return &liveedit_compare_substrings_buf2_;
906 }
907
compiler_safe_string_input_buffer()908 StaticResource<SafeStringInputBuffer>* compiler_safe_string_input_buffer() {
909 return &compiler_safe_string_input_buffer_;
910 }
911
builtins()912 Builtins* builtins() { return &builtins_; }
913
914 unibrow::Mapping<unibrow::Ecma262Canonicalize>*
regexp_macro_assembler_canonicalize()915 regexp_macro_assembler_canonicalize() {
916 return ®exp_macro_assembler_canonicalize_;
917 }
918
regexp_stack()919 RegExpStack* regexp_stack() { return regexp_stack_; }
920
921 unibrow::Mapping<unibrow::Ecma262Canonicalize>*
interp_canonicalize_mapping()922 interp_canonicalize_mapping() {
923 return &interp_canonicalize_mapping_;
924 }
925
frame_element_constant_list()926 ZoneObjectList* frame_element_constant_list() {
927 return &frame_element_constant_list_;
928 }
929
result_constant_list()930 ZoneObjectList* result_constant_list() {
931 return &result_constant_list_;
932 }
933
934 void* PreallocatedStorageNew(size_t size);
935 void PreallocatedStorageDelete(void* p);
936 void PreallocatedStorageInit(size_t size);
937
938 #ifdef ENABLE_DEBUGGER_SUPPORT
debugger()939 Debugger* debugger() {
940 if (!NoBarrier_Load(&debugger_initialized_)) InitializeDebugger();
941 return debugger_;
942 }
debug()943 Debug* debug() {
944 if (!NoBarrier_Load(&debugger_initialized_)) InitializeDebugger();
945 return debug_;
946 }
947 #endif
948
949 #ifdef ENABLE_LOGGING_AND_PROFILING
producer_heap_profile()950 ProducerHeapProfile* producer_heap_profile() {
951 return producer_heap_profile_;
952 }
953 #endif
954
955 #ifdef DEBUG
heap_histograms()956 HistogramInfo* heap_histograms() { return heap_histograms_; }
957
js_spill_information()958 JSObject::SpillInformation* js_spill_information() {
959 return &js_spill_information_;
960 }
961
code_kind_statistics()962 int* code_kind_statistics() { return code_kind_statistics_; }
963 #endif
964
965 #if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
966 defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
simulator_initialized()967 bool simulator_initialized() { return simulator_initialized_; }
set_simulator_initialized(bool initialized)968 void set_simulator_initialized(bool initialized) {
969 simulator_initialized_ = initialized;
970 }
971
simulator_i_cache()972 HashMap* simulator_i_cache() { return simulator_i_cache_; }
set_simulator_i_cache(HashMap * hash_map)973 void set_simulator_i_cache(HashMap* hash_map) {
974 simulator_i_cache_ = hash_map;
975 }
976
simulator_redirection()977 Redirection* simulator_redirection() {
978 return simulator_redirection_;
979 }
set_simulator_redirection(Redirection * redirection)980 void set_simulator_redirection(Redirection* redirection) {
981 simulator_redirection_ = redirection;
982 }
983 #endif
984
factory()985 Factory* factory() { return reinterpret_cast<Factory*>(this); }
986
987 // SerializerDeserializer state.
988 static const int kPartialSnapshotCacheCapacity = 1400;
989
990 static const int kJSRegexpStaticOffsetsVectorSize = 50;
991
992 #ifdef ENABLE_LOGGING_AND_PROFILING
external_callback()993 Address external_callback() {
994 return thread_local_top_.external_callback_;
995 }
set_external_callback(Address callback)996 void set_external_callback(Address callback) {
997 thread_local_top_.external_callback_ = callback;
998 }
999 #endif
1000
1001 #ifdef ENABLE_VMSTATE_TRACKING
current_vm_state()1002 StateTag current_vm_state() {
1003 return thread_local_top_.current_vm_state_;
1004 }
1005
SetCurrentVMState(StateTag state)1006 void SetCurrentVMState(StateTag state) {
1007 if (RuntimeProfiler::IsEnabled()) {
1008 StateTag current_state = thread_local_top_.current_vm_state_;
1009 if (current_state != JS && state == JS) {
1010 // Non-JS -> JS transition.
1011 RuntimeProfiler::IsolateEnteredJS(this);
1012 } else if (current_state == JS && state != JS) {
1013 // JS -> non-JS transition.
1014 ASSERT(RuntimeProfiler::IsSomeIsolateInJS());
1015 RuntimeProfiler::IsolateExitedJS(this);
1016 } else {
1017 // Other types of state transitions are not interesting to the
1018 // runtime profiler, because they don't affect whether we're
1019 // in JS or not.
1020 ASSERT((current_state == JS) == (state == JS));
1021 }
1022 }
1023 thread_local_top_.current_vm_state_ = state;
1024 }
1025 #endif
1026
1027 void ResetEagerOptimizingData();
1028
1029 private:
1030 Isolate();
1031
1032 // The per-process lock should be acquired before the ThreadDataTable is
1033 // modified.
1034 class ThreadDataTable {
1035 public:
1036 ThreadDataTable();
1037 ~ThreadDataTable();
1038
1039 PerIsolateThreadData* Lookup(Isolate* isolate, ThreadId thread_id);
1040 void Insert(PerIsolateThreadData* data);
1041 void Remove(Isolate* isolate, ThreadId thread_id);
1042 void Remove(PerIsolateThreadData* data);
1043
1044 private:
1045 PerIsolateThreadData* list_;
1046 };
1047
1048 // These items form a stack synchronously with threads Enter'ing and Exit'ing
1049 // the Isolate. The top of the stack points to a thread which is currently
1050 // running the Isolate. When the stack is empty, the Isolate is considered
1051 // not entered by any thread and can be Disposed.
1052 // If the same thread enters the Isolate more then once, the entry_count_
1053 // is incremented rather then a new item pushed to the stack.
1054 class EntryStackItem {
1055 public:
EntryStackItem(PerIsolateThreadData * previous_thread_data,Isolate * previous_isolate,EntryStackItem * previous_item)1056 EntryStackItem(PerIsolateThreadData* previous_thread_data,
1057 Isolate* previous_isolate,
1058 EntryStackItem* previous_item)
1059 : entry_count(1),
1060 previous_thread_data(previous_thread_data),
1061 previous_isolate(previous_isolate),
1062 previous_item(previous_item) { }
1063
1064 int entry_count;
1065 PerIsolateThreadData* previous_thread_data;
1066 Isolate* previous_isolate;
1067 EntryStackItem* previous_item;
1068
1069 DISALLOW_COPY_AND_ASSIGN(EntryStackItem);
1070 };
1071
1072 // This mutex protects highest_thread_id_, thread_data_table_ and
1073 // default_isolate_.
1074 static Mutex* process_wide_mutex_;
1075
1076 static Thread::LocalStorageKey per_isolate_thread_data_key_;
1077 static Thread::LocalStorageKey isolate_key_;
1078 static Thread::LocalStorageKey thread_id_key_;
1079 static Isolate* default_isolate_;
1080 static ThreadDataTable* thread_data_table_;
1081
1082 void Deinit();
1083
1084 static void SetIsolateThreadLocals(Isolate* isolate,
1085 PerIsolateThreadData* data);
1086
1087 enum State {
1088 UNINITIALIZED, // Some components may not have been allocated.
1089 INITIALIZED // All components are fully initialized.
1090 };
1091
1092 State state_;
1093 EntryStackItem* entry_stack_;
1094
1095 // Allocate and insert PerIsolateThreadData into the ThreadDataTable
1096 // (regardless of whether such data already exists).
1097 PerIsolateThreadData* AllocatePerIsolateThreadData(ThreadId thread_id);
1098
1099 // Find the PerThread for this particular (isolate, thread) combination.
1100 // If one does not yet exist, allocate a new one.
1101 PerIsolateThreadData* FindOrAllocatePerThreadDataForThisThread();
1102
1103 // PreInits and returns a default isolate. Needed when a new thread tries
1104 // to create a Locker for the first time (the lock itself is in the isolate).
1105 static Isolate* GetDefaultIsolateForLocking();
1106
1107 // Initializes the current thread to run this Isolate.
1108 // Not thread-safe. Multiple threads should not Enter/Exit the same isolate
1109 // at the same time, this should be prevented using external locking.
1110 void Enter();
1111
1112 // Exits the current thread. The previosuly entered Isolate is restored
1113 // for the thread.
1114 // Not thread-safe. Multiple threads should not Enter/Exit the same isolate
1115 // at the same time, this should be prevented using external locking.
1116 void Exit();
1117
1118 void PreallocatedMemoryThreadStart();
1119 void PreallocatedMemoryThreadStop();
1120 void InitializeThreadLocal();
1121
1122 void PrintStackTrace(FILE* out, ThreadLocalTop* thread);
1123 void MarkCompactPrologue(bool is_compacting,
1124 ThreadLocalTop* archived_thread_data);
1125 void MarkCompactEpilogue(bool is_compacting,
1126 ThreadLocalTop* archived_thread_data);
1127
1128 void FillCache();
1129
1130 void PropagatePendingExceptionToExternalTryCatch();
1131
1132 void InitializeDebugger();
1133
1134 int stack_trace_nesting_level_;
1135 StringStream* incomplete_message_;
1136 // The preallocated memory thread singleton.
1137 PreallocatedMemoryThread* preallocated_memory_thread_;
1138 Address isolate_addresses_[k_isolate_address_count + 1]; // NOLINT
1139 NoAllocationStringAllocator* preallocated_message_space_;
1140
1141 Bootstrapper* bootstrapper_;
1142 RuntimeProfiler* runtime_profiler_;
1143 CompilationCache* compilation_cache_;
1144 Counters* counters_;
1145 CodeRange* code_range_;
1146 Mutex* break_access_;
1147 Atomic32 debugger_initialized_;
1148 Mutex* debugger_access_;
1149 Heap heap_;
1150 Logger* logger_;
1151 StackGuard stack_guard_;
1152 StatsTable* stats_table_;
1153 StubCache* stub_cache_;
1154 DeoptimizerData* deoptimizer_data_;
1155 ThreadLocalTop thread_local_top_;
1156 bool capture_stack_trace_for_uncaught_exceptions_;
1157 int stack_trace_for_uncaught_exceptions_frame_limit_;
1158 StackTrace::StackTraceOptions stack_trace_for_uncaught_exceptions_options_;
1159 TranscendentalCache* transcendental_cache_;
1160 MemoryAllocator* memory_allocator_;
1161 KeyedLookupCache* keyed_lookup_cache_;
1162 ContextSlotCache* context_slot_cache_;
1163 DescriptorLookupCache* descriptor_lookup_cache_;
1164 v8::ImplementationUtilities::HandleScopeData handle_scope_data_;
1165 HandleScopeImplementer* handle_scope_implementer_;
1166 UnicodeCache* unicode_cache_;
1167 Zone zone_;
1168 PreallocatedStorage in_use_list_;
1169 PreallocatedStorage free_list_;
1170 bool preallocated_storage_preallocated_;
1171 PcToCodeCache* pc_to_code_cache_;
1172 StringInputBuffer* write_input_buffer_;
1173 GlobalHandles* global_handles_;
1174 ContextSwitcher* context_switcher_;
1175 ThreadManager* thread_manager_;
1176 AstSentinels* ast_sentinels_;
1177 RuntimeState runtime_state_;
1178 StringInputBuffer liveedit_compare_substrings_buf1_;
1179 StringInputBuffer liveedit_compare_substrings_buf2_;
1180 StaticResource<SafeStringInputBuffer> compiler_safe_string_input_buffer_;
1181 Builtins builtins_;
1182 StringTracker* string_tracker_;
1183 unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize_;
1184 unibrow::Mapping<unibrow::CanonicalizationRange> jsregexp_canonrange_;
1185 StringInputBuffer objects_string_compare_buffer_a_;
1186 StringInputBuffer objects_string_compare_buffer_b_;
1187 StaticResource<StringInputBuffer> objects_string_input_buffer_;
1188 unibrow::Mapping<unibrow::Ecma262Canonicalize>
1189 regexp_macro_assembler_canonicalize_;
1190 RegExpStack* regexp_stack_;
1191 unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize_mapping_;
1192 ZoneObjectList frame_element_constant_list_;
1193 ZoneObjectList result_constant_list_;
1194
1195 #if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
1196 defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
1197 bool simulator_initialized_;
1198 HashMap* simulator_i_cache_;
1199 Redirection* simulator_redirection_;
1200 #endif
1201
1202 #ifdef DEBUG
1203 // A static array of histogram info for each type.
1204 HistogramInfo heap_histograms_[LAST_TYPE + 1];
1205 JSObject::SpillInformation js_spill_information_;
1206 int code_kind_statistics_[Code::NUMBER_OF_KINDS];
1207 #endif
1208
1209 #ifdef ENABLE_DEBUGGER_SUPPORT
1210 Debugger* debugger_;
1211 Debug* debug_;
1212 #endif
1213
1214 #ifdef ENABLE_LOGGING_AND_PROFILING
1215 ProducerHeapProfile* producer_heap_profile_;
1216 #endif
1217
1218 #define GLOBAL_BACKING_STORE(type, name, initialvalue) \
1219 type name##_;
1220 ISOLATE_INIT_LIST(GLOBAL_BACKING_STORE)
1221 #undef GLOBAL_BACKING_STORE
1222
1223 #define GLOBAL_ARRAY_BACKING_STORE(type, name, length) \
1224 type name##_[length];
1225 ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_BACKING_STORE)
1226 #undef GLOBAL_ARRAY_BACKING_STORE
1227
1228 #ifdef DEBUG
1229 // This class is huge and has a number of fields controlled by
1230 // preprocessor defines. Make sure the offsets of these fields agree
1231 // between compilation units.
1232 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \
1233 static const intptr_t name##_debug_offset_;
1234 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
1235 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
1236 #undef ISOLATE_FIELD_OFFSET
1237 #endif
1238
1239 friend class ExecutionAccess;
1240 friend class IsolateInitializer;
1241 friend class ThreadId;
1242 friend class TestMemoryAllocatorScope;
1243 friend class v8::Isolate;
1244 friend class v8::Locker;
1245
1246 DISALLOW_COPY_AND_ASSIGN(Isolate);
1247 };
1248
1249
1250 // If the GCC version is 4.1.x or 4.2.x an additional field is added to the
1251 // class as a work around for a bug in the generated code found with these
1252 // versions of GCC. See V8 issue 122 for details.
1253 class SaveContext BASE_EMBEDDED {
1254 public:
SaveContext(Isolate * isolate)1255 explicit SaveContext(Isolate* isolate) : prev_(isolate->save_context()) {
1256 if (isolate->context() != NULL) {
1257 context_ = Handle<Context>(isolate->context());
1258 #if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300
1259 dummy_ = Handle<Context>(isolate->context());
1260 #endif
1261 }
1262 isolate->set_save_context(this);
1263
1264 // If there is no JS frame under the current C frame, use the value 0.
1265 JavaScriptFrameIterator it(isolate);
1266 js_sp_ = it.done() ? 0 : it.frame()->sp();
1267 }
1268
~SaveContext()1269 ~SaveContext() {
1270 if (context_.is_null()) {
1271 Isolate* isolate = Isolate::Current();
1272 isolate->set_context(NULL);
1273 isolate->set_save_context(prev_);
1274 } else {
1275 Isolate* isolate = context_->GetIsolate();
1276 isolate->set_context(*context_);
1277 isolate->set_save_context(prev_);
1278 }
1279 }
1280
context()1281 Handle<Context> context() { return context_; }
prev()1282 SaveContext* prev() { return prev_; }
1283
1284 // Returns true if this save context is below a given JavaScript frame.
below(JavaScriptFrame * frame)1285 bool below(JavaScriptFrame* frame) {
1286 return (js_sp_ == 0) || (frame->sp() < js_sp_);
1287 }
1288
1289 private:
1290 Handle<Context> context_;
1291 #if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300
1292 Handle<Context> dummy_;
1293 #endif
1294 SaveContext* prev_;
1295 Address js_sp_; // The top JS frame's sp when saving context.
1296 };
1297
1298
1299 class AssertNoContextChange BASE_EMBEDDED {
1300 #ifdef DEBUG
1301 public:
AssertNoContextChange()1302 AssertNoContextChange() :
1303 scope_(Isolate::Current()),
1304 context_(Isolate::Current()->context(), Isolate::Current()) {
1305 }
1306
~AssertNoContextChange()1307 ~AssertNoContextChange() {
1308 ASSERT(Isolate::Current()->context() == *context_);
1309 }
1310
1311 private:
1312 HandleScope scope_;
1313 Handle<Context> context_;
1314 #else
1315 public:
1316 AssertNoContextChange() { }
1317 #endif
1318 };
1319
1320
1321 class ExecutionAccess BASE_EMBEDDED {
1322 public:
ExecutionAccess(Isolate * isolate)1323 explicit ExecutionAccess(Isolate* isolate) : isolate_(isolate) {
1324 Lock(isolate);
1325 }
~ExecutionAccess()1326 ~ExecutionAccess() { Unlock(isolate_); }
1327
Lock(Isolate * isolate)1328 static void Lock(Isolate* isolate) { isolate->break_access_->Lock(); }
Unlock(Isolate * isolate)1329 static void Unlock(Isolate* isolate) { isolate->break_access_->Unlock(); }
1330
TryLock(Isolate * isolate)1331 static bool TryLock(Isolate* isolate) {
1332 return isolate->break_access_->TryLock();
1333 }
1334
1335 private:
1336 Isolate* isolate_;
1337 };
1338
1339
1340 // Support for checking for stack-overflows in C++ code.
1341 class StackLimitCheck BASE_EMBEDDED {
1342 public:
StackLimitCheck(Isolate * isolate)1343 explicit StackLimitCheck(Isolate* isolate) : isolate_(isolate) { }
1344
HasOverflowed()1345 bool HasOverflowed() const {
1346 StackGuard* stack_guard = isolate_->stack_guard();
1347 // Stack has overflowed in C++ code only if stack pointer exceeds the C++
1348 // stack guard and the limits are not set to interrupt values.
1349 // TODO(214): Stack overflows are ignored if a interrupt is pending. This
1350 // code should probably always use the initial C++ limit.
1351 return (reinterpret_cast<uintptr_t>(this) < stack_guard->climit()) &&
1352 stack_guard->IsStackOverflow();
1353 }
1354 private:
1355 Isolate* isolate_;
1356 };
1357
1358
1359 // Support for temporarily postponing interrupts. When the outermost
1360 // postpone scope is left the interrupts will be re-enabled and any
1361 // interrupts that occurred while in the scope will be taken into
1362 // account.
1363 class PostponeInterruptsScope BASE_EMBEDDED {
1364 public:
PostponeInterruptsScope(Isolate * isolate)1365 explicit PostponeInterruptsScope(Isolate* isolate)
1366 : stack_guard_(isolate->stack_guard()) {
1367 stack_guard_->thread_local_.postpone_interrupts_nesting_++;
1368 stack_guard_->DisableInterrupts();
1369 }
1370
~PostponeInterruptsScope()1371 ~PostponeInterruptsScope() {
1372 if (--stack_guard_->thread_local_.postpone_interrupts_nesting_ == 0) {
1373 stack_guard_->EnableInterrupts();
1374 }
1375 }
1376 private:
1377 StackGuard* stack_guard_;
1378 };
1379
1380
1381 // Temporary macros for accessing current isolate and its subobjects.
1382 // They provide better readability, especially when used a lot in the code.
1383 #define HEAP (v8::internal::Isolate::Current()->heap())
1384 #define FACTORY (v8::internal::Isolate::Current()->factory())
1385 #define ISOLATE (v8::internal::Isolate::Current())
1386 #define ZONE (v8::internal::Isolate::Current()->zone())
1387 #define LOGGER (v8::internal::Isolate::Current()->logger())
1388
1389
1390 // Tells whether the global context is marked with out of memory.
has_out_of_memory()1391 inline bool Context::has_out_of_memory() {
1392 return global_context()->out_of_memory()->IsTrue();
1393 }
1394
1395
1396 // Mark the global context with out of memory.
mark_out_of_memory()1397 inline void Context::mark_out_of_memory() {
1398 global_context()->set_out_of_memory(HEAP->true_value());
1399 }
1400
1401
1402 // Temporary macro to be used to flag definitions that are indeed static
1403 // and not per-isolate. (It would be great to be able to grep for [static]!)
1404 #define RLYSTC static
1405
1406
1407 // Temporary macro to be used to flag classes that should be static.
1408 #define STATIC_CLASS class
1409
1410
1411 // Temporary macro to be used to flag classes that are completely converted
1412 // to be isolate-friendly. Their mix of static/nonstatic methods/fields is
1413 // correct.
1414 #define ISOLATED_CLASS class
1415
1416 } } // namespace v8::internal
1417
1418 // TODO(isolates): Get rid of these -inl.h includes and place them only where
1419 // they're needed.
1420 #include "allocation-inl.h"
1421 #include "zone-inl.h"
1422 #include "frames-inl.h"
1423
1424 #endif // V8_ISOLATE_H_
1425