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