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