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