blob: 8b4e12bc0d38aea0acf9498e49258c7c0964995e [file] [log] [blame]
rossberg@chromium.orgfab14982012-01-05 15:02:15 +00001// Copyright 2012 the V8 project authors. All rights reserved.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002// 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"
svenpanne@chromium.org4efbdb12012-03-12 08:18:42 +000039#include "date.h"
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000040#include "global-handles.h"
41#include "handles.h"
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000042#include "hashmap.h"
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000043#include "heap.h"
44#include "regexp-stack.h"
45#include "runtime-profiler.h"
46#include "runtime.h"
47#include "zone.h"
48
49namespace v8 {
50namespace internal {
51
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000052class Bootstrapper;
53class CodeGenerator;
54class CodeRange;
55class CompilationCache;
56class ContextSlotCache;
57class ContextSwitcher;
58class Counters;
59class CpuFeatures;
60class CpuProfiler;
61class DeoptimizerData;
62class Deserializer;
63class EmptyStatement;
64class ExternalReferenceTable;
65class Factory;
66class FunctionInfoListener;
67class HandleScopeImplementer;
68class HeapProfiler;
69class InlineRuntimeFunctionsTable;
70class NoAllocationStringAllocator;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000071class InnerPointerToCodeCache;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000072class PreallocatedMemoryThread;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000073class RegExpStack;
74class SaveContext;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000075class UnicodeCache;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000076class StringInputBuffer;
77class StringTracker;
78class StubCache;
79class ThreadManager;
80class ThreadState;
81class ThreadVisitor; // Defined in v8threads.h
82class VMState;
83
84// 'void function pointer', used to roundtrip the
85// ExternalReference::ExternalReferenceRedirector since we can not include
86// assembler.h, where it is defined, here.
87typedef void* ExternalReferenceRedirectorPointer();
88
89
90#ifdef ENABLE_DEBUGGER_SUPPORT
91class Debug;
92class Debugger;
93class DebuggerAgent;
94#endif
95
lrn@chromium.org7516f052011-03-30 08:52:27 +000096#if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
97 !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000098class Redirection;
99class Simulator;
100#endif
101
lrn@chromium.org7516f052011-03-30 08:52:27 +0000102
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000103// Static indirection table for handles to constants. If a frame
104// element represents a constant, the data contains an index into
105// this table of handles to the actual constants.
106// Static indirection table for handles to constants. If a Result
107// represents a constant, the data contains an index into this table
108// of handles to the actual constants.
109typedef ZoneList<Handle<Object> > ZoneObjectList;
110
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000111#define RETURN_IF_SCHEDULED_EXCEPTION(isolate) \
112 do { \
113 Isolate* __isolate__ = (isolate); \
114 if (__isolate__->has_scheduled_exception()) { \
115 return __isolate__->PromoteScheduledException(); \
116 } \
117 } while (false)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000118
119#define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value) \
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000120 do { \
121 if ((call).is_null()) { \
122 ASSERT((isolate)->has_pending_exception()); \
123 return (value); \
124 } \
125 } while (false)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000126
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000127#define CHECK_NOT_EMPTY_HANDLE(isolate, call) \
128 do { \
129 ASSERT(!(isolate)->has_pending_exception()); \
130 CHECK(!(call).is_null()); \
131 CHECK(!(isolate)->has_pending_exception()); \
132 } while (false)
133
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000134#define RETURN_IF_EMPTY_HANDLE(isolate, call) \
135 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, Failure::Exception())
136
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000137#define FOR_EACH_ISOLATE_ADDRESS_NAME(C) \
138 C(Handler, handler) \
139 C(CEntryFP, c_entry_fp) \
140 C(Context, context) \
141 C(PendingException, pending_exception) \
142 C(ExternalCaughtException, external_caught_exception) \
143 C(JSEntrySP, js_entry_sp)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000144
145
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000146// Platform-independent, reliable thread identifier.
147class ThreadId {
148 public:
149 // Creates an invalid ThreadId.
150 ThreadId() : id_(kInvalidId) {}
151
152 // Returns ThreadId for current thread.
153 static ThreadId Current() { return ThreadId(GetCurrentThreadId()); }
154
155 // Returns invalid ThreadId (guaranteed not to be equal to any thread).
156 static ThreadId Invalid() { return ThreadId(kInvalidId); }
157
158 // Compares ThreadIds for equality.
159 INLINE(bool Equals(const ThreadId& other) const) {
160 return id_ == other.id_;
161 }
162
163 // Checks whether this ThreadId refers to any thread.
164 INLINE(bool IsValid() const) {
165 return id_ != kInvalidId;
166 }
167
168 // Converts ThreadId to an integer representation
169 // (required for public API: V8::V8::GetCurrentThreadId).
170 int ToInteger() const { return id_; }
171
172 // Converts ThreadId to an integer representation
173 // (required for public API: V8::V8::TerminateExecution).
174 static ThreadId FromInteger(int id) { return ThreadId(id); }
175
176 private:
177 static const int kInvalidId = -1;
178
179 explicit ThreadId(int id) : id_(id) {}
180
181 static int AllocateThreadId();
182
183 static int GetCurrentThreadId();
184
185 int id_;
186
187 static Atomic32 highest_thread_id_;
188
189 friend class Isolate;
190};
191
192
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000193class ThreadLocalTop BASE_EMBEDDED {
194 public:
vitalyr@chromium.org5523ec32011-04-15 21:42:52 +0000195 // Does early low-level initialization that does not depend on the
196 // isolate being present.
197 ThreadLocalTop();
198
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000199 // Initialize the thread data.
200 void Initialize();
201
202 // Get the top C++ try catch handler or NULL if none are registered.
203 //
204 // This method is not guarenteed to return an address that can be
205 // used for comparison with addresses into the JS stack. If such an
206 // address is needed, use try_catch_handler_address.
207 v8::TryCatch* TryCatchHandler();
208
209 // Get the address of the top C++ try catch handler or NULL if
210 // none are registered.
211 //
212 // This method always returns an address that can be compared to
213 // pointers into the JavaScript stack. When running on actual
214 // hardware, try_catch_handler_address and TryCatchHandler return
215 // the same pointer. When running on a simulator with a separate JS
216 // stack, try_catch_handler_address returns a JS stack address that
217 // corresponds to the place on the JS stack where the C++ handler
218 // would have been if the stack were not separate.
219 inline Address try_catch_handler_address() {
220 return try_catch_handler_address_;
221 }
222
223 // Set the address of the top C++ try catch handler.
224 inline void set_try_catch_handler_address(Address address) {
225 try_catch_handler_address_ = address;
226 }
227
228 void Free() {
229 ASSERT(!has_pending_message_);
230 ASSERT(!external_caught_exception_);
231 ASSERT(try_catch_handler_address_ == NULL);
232 }
233
lrn@chromium.org1c092762011-05-09 09:42:16 +0000234 Isolate* isolate_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000235 // The context where the current execution method is created and for variable
236 // lookups.
237 Context* context_;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000238 ThreadId thread_id_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000239 MaybeObject* pending_exception_;
240 bool has_pending_message_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000241 Object* pending_message_obj_;
242 Script* pending_message_script_;
243 int pending_message_start_pos_;
244 int pending_message_end_pos_;
245 // Use a separate value for scheduled exceptions to preserve the
246 // invariants that hold about pending_exception. We may want to
247 // unify them later.
248 MaybeObject* scheduled_exception_;
249 bool external_caught_exception_;
250 SaveContext* save_context_;
251 v8::TryCatch* catcher_;
252
253 // Stack.
254 Address c_entry_fp_; // the frame pointer of the top c entry frame
255 Address handler_; // try-blocks are chained through the stack
256
257#ifdef USE_SIMULATOR
lrn@chromium.org7516f052011-03-30 08:52:27 +0000258#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000259 Simulator* simulator_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000260#endif
261#endif // USE_SIMULATOR
262
ulan@chromium.org2efb9002012-01-19 15:36:35 +0000263 Address js_entry_sp_; // the stack pointer of the bottom JS entry frame
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000264 Address external_callback_; // the external callback we're currently in
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000265 StateTag current_vm_state_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000266
267 // Generated code scratch locations.
268 int32_t formal_count_;
269
270 // Call back function to report unsafe JS accesses.
271 v8::FailedAccessCheckCallback failed_access_check_callback_;
272
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000273 // Head of the list of live LookupResults.
274 LookupResult* top_lookup_result_;
275
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000276 // Whether out of memory exceptions should be ignored.
277 bool ignore_out_of_memory_;
278
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000279 private:
vitalyr@chromium.org5523ec32011-04-15 21:42:52 +0000280 void InitializeInternal();
281
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000282 Address try_catch_handler_address_;
283};
284
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000285
286#ifdef ENABLE_DEBUGGER_SUPPORT
287
288#define ISOLATE_DEBUGGER_INIT_LIST(V) \
289 V(v8::Debug::EventCallback, debug_event_callback, NULL) \
290 V(DebuggerAgent*, debugger_agent_instance, NULL)
291#else
292
293#define ISOLATE_DEBUGGER_INIT_LIST(V)
294
295#endif
296
297#ifdef DEBUG
298
299#define ISOLATE_INIT_DEBUG_ARRAY_LIST(V) \
300 V(CommentStatistic, paged_space_comments_statistics, \
301 CommentStatistic::kMaxComments + 1)
302#else
303
304#define ISOLATE_INIT_DEBUG_ARRAY_LIST(V)
305
306#endif
307
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000308#define ISOLATE_INIT_ARRAY_LIST(V) \
309 /* SerializerDeserializer state. */ \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000310 V(int, jsregexp_static_offsets_vector, kJSRegexpStaticOffsetsVectorSize) \
311 V(int, bad_char_shift_table, kUC16AlphabetSize) \
312 V(int, good_suffix_shift_table, (kBMMaxShift + 1)) \
313 V(int, suffix_table, (kBMMaxShift + 1)) \
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000314 V(uint32_t, private_random_seed, 2) \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000315 ISOLATE_INIT_DEBUG_ARRAY_LIST(V)
316
rossberg@chromium.org400388e2012-06-06 09:29:22 +0000317typedef List<HeapObject*, PreallocatedStorageAllocationPolicy> DebugObjectCache;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000318
319#define ISOLATE_INIT_LIST(V) \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000320 /* SerializerDeserializer state. */ \
321 V(int, serialize_partial_snapshot_cache_length, 0) \
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000322 V(int, serialize_partial_snapshot_cache_capacity, 0) \
323 V(Object**, serialize_partial_snapshot_cache, NULL) \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000324 /* Assembler state. */ \
325 /* A previously allocated buffer of kMinimalBufferSize bytes, or NULL. */ \
326 V(byte*, assembler_spare_buffer, NULL) \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000327 V(FatalErrorCallback, exception_behavior, NULL) \
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +0000328 V(AllowCodeGenerationFromStringsCallback, allow_code_gen_callback, NULL) \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000329 V(v8::Debug::MessageHandler, message_handler, NULL) \
330 /* To distinguish the function templates, so that we can find them in the */ \
331 /* function cache of the global context. */ \
332 V(int, next_serial_number, 0) \
333 V(ExternalReferenceRedirectorPointer*, external_reference_redirector, NULL) \
334 V(bool, always_allow_natives_syntax, false) \
335 /* Part of the state of liveedit. */ \
336 V(FunctionInfoListener*, active_function_info_listener, NULL) \
337 /* State for Relocatable. */ \
338 V(Relocatable*, relocatable_top, NULL) \
339 /* State for CodeEntry in profile-generator. */ \
340 V(CodeGenerator*, current_code_generator, NULL) \
341 V(bool, jump_target_compiling_deferred_code, false) \
342 V(DebugObjectCache*, string_stream_debug_object_cache, NULL) \
343 V(Object*, string_stream_current_security_token, NULL) \
344 /* TODO(isolates): Release this on destruction? */ \
345 V(int*, irregexp_interpreter_backtrack_stack_cache, NULL) \
346 /* Serializer state. */ \
347 V(ExternalReferenceTable*, external_reference_table, NULL) \
348 /* AstNode state. */ \
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +0000349 V(int, ast_node_id, 0) \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000350 V(unsigned, ast_node_count, 0) \
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000351 /* SafeStackFrameIterator activations count. */ \
352 V(int, safe_stack_iterator_counter, 0) \
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000353 V(uint64_t, enabled_cpu_features, 0) \
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000354 V(CpuProfiler*, cpu_profiler, NULL) \
355 V(HeapProfiler*, heap_profiler, NULL) \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000356 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
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000366 // 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),
lrn@chromium.org7516f052011-03-30 08:52:27 +0000376#if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
377 !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000378 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
lrn@chromium.org7516f052011-03-30 08:52:27 +0000389#if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
390 !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000391 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 {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000398 return isolate_ == isolate && thread_id_.Equals(thread_id);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000399 }
400
401 private:
402 Isolate* isolate_;
403 ThreadId thread_id_;
404 uintptr_t stack_limit_;
405 ThreadState* thread_state_;
406
lrn@chromium.org7516f052011-03-30 08:52:27 +0000407#if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
408 !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000409 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 {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000424#define DECLARE_ENUM(CamelName, hacker_name) k##CamelName##Address,
425 FOR_EACH_ISOLATE_ADDRESS_NAME(DECLARE_ENUM)
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000426#undef DECLARE_ENUM
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000427 kIsolateAddressCount
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000428 };
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*>(
danno@chromium.org8c0a43f2012-04-03 08:37:53 +0000434 Thread::GetThreadLocal(per_isolate_thread_data_key_));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000435 }
436
437 // Returns the isolate inside which the current thread is running.
438 INLINE(static Isolate* Current()) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000439 Isolate* isolate = reinterpret_cast<Isolate*>(
danno@chromium.org8c0a43f2012-04-03 08:37:53 +0000440 Thread::GetExistingThreadLocal(isolate_key_));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000441 ASSERT(isolate != NULL);
442 return isolate;
443 }
444
445 INLINE(static Isolate* UncheckedCurrent()) {
danno@chromium.org8c0a43f2012-04-03 08:37:53 +0000446 return reinterpret_cast<Isolate*>(Thread::GetThreadLocal(isolate_key_));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000447 }
448
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000449 // Usually called by Init(), but can be called early e.g. to allow
450 // testing components that require logging but not the whole
451 // isolate.
452 //
453 // Safe to call more than once.
454 void InitializeLoggingAndCounters();
455
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000456 bool Init(Deserializer* des);
457
458 bool IsInitialized() { return state_ == INITIALIZED; }
459
460 // True if at least one thread Enter'ed this isolate.
461 bool IsInUse() { return entry_stack_ != NULL; }
462
463 // Destroys the non-default isolates.
464 // Sets default isolate into "has_been_disposed" state rather then destroying,
465 // for legacy API reasons.
466 void TearDown();
467
danno@chromium.org8c0a43f2012-04-03 08:37:53 +0000468 bool IsDefaultIsolate() const { return this == default_isolate_; }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000469
470 // Ensures that process-wide resources and the default isolate have been
ulan@chromium.org2efb9002012-01-19 15:36:35 +0000471 // allocated. It is only necessary to call this method in rare cases, for
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000472 // example if you are using V8 from within the body of a static initializer.
473 // Safe to call multiple times.
474 static void EnsureDefaultIsolate();
475
lrn@chromium.org1c092762011-05-09 09:42:16 +0000476 // Find the PerThread for this particular (isolate, thread) combination
477 // If one does not yet exist, return null.
478 PerIsolateThreadData* FindPerThreadDataForThisThread();
479
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000480#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000481 // Get the debugger from the default isolate. Preinitializes the
482 // default isolate if needed.
483 static Debugger* GetDefaultIsolateDebugger();
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000484#endif
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000485
486 // Get the stack guard from the default isolate. Preinitializes the
487 // default isolate if needed.
488 static StackGuard* GetDefaultIsolateStackGuard();
489
490 // Returns the key used to store the pointer to the current isolate.
491 // Used internally for V8 threads that do not execute JavaScript but still
492 // are part of the domain of an isolate (like the context switcher).
danno@chromium.org8c0a43f2012-04-03 08:37:53 +0000493 static Thread::LocalStorageKey isolate_key() {
494 return isolate_key_;
495 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000496
497 // Returns the key used to store process-wide thread IDs.
danno@chromium.org8c0a43f2012-04-03 08:37:53 +0000498 static Thread::LocalStorageKey thread_id_key() {
499 return thread_id_key_;
500 }
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000501
502 static Thread::LocalStorageKey per_isolate_thread_data_key();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000503
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000504 // If a client attempts to create a Locker without specifying an isolate,
505 // we assume that the client is using legacy behavior. Set up the current
506 // thread to be inside the implicit isolate (or fail a check if we have
507 // switched to non-legacy behavior).
508 static void EnterDefaultIsolate();
509
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000510 // Mutex for serializing access to break control structures.
511 Mutex* break_access() { return break_access_; }
512
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000513 // Mutex for serializing access to debugger.
514 Mutex* debugger_access() { return debugger_access_; }
515
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000516 Address get_address_from_id(AddressId id);
517
518 // Access to top context (where the current function object was created).
519 Context* context() { return thread_local_top_.context_; }
520 void set_context(Context* context) {
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000521 ASSERT(context == NULL || context->IsContext());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000522 thread_local_top_.context_ = context;
523 }
524 Context** context_address() { return &thread_local_top_.context_; }
525
526 SaveContext* save_context() {return thread_local_top_.save_context_; }
527 void set_save_context(SaveContext* save) {
528 thread_local_top_.save_context_ = save;
529 }
530
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000531 // Access to the map of "new Object()".
532 Map* empty_object_map() {
533 return context()->global_context()->object_function()->map();
534 }
535
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000536 // Access to current thread id.
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000537 ThreadId thread_id() { return thread_local_top_.thread_id_; }
538 void set_thread_id(ThreadId id) { thread_local_top_.thread_id_ = id; }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000539
540 // Interface to pending exception.
541 MaybeObject* pending_exception() {
542 ASSERT(has_pending_exception());
543 return thread_local_top_.pending_exception_;
544 }
545 bool external_caught_exception() {
546 return thread_local_top_.external_caught_exception_;
547 }
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000548 void set_external_caught_exception(bool value) {
549 thread_local_top_.external_caught_exception_ = value;
550 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000551 void set_pending_exception(MaybeObject* exception) {
552 thread_local_top_.pending_exception_ = exception;
553 }
554 void clear_pending_exception() {
555 thread_local_top_.pending_exception_ = heap_.the_hole_value();
556 }
557 MaybeObject** pending_exception_address() {
558 return &thread_local_top_.pending_exception_;
559 }
560 bool has_pending_exception() {
561 return !thread_local_top_.pending_exception_->IsTheHole();
562 }
563 void clear_pending_message() {
564 thread_local_top_.has_pending_message_ = false;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000565 thread_local_top_.pending_message_obj_ = heap_.the_hole_value();
566 thread_local_top_.pending_message_script_ = NULL;
567 }
568 v8::TryCatch* try_catch_handler() {
569 return thread_local_top_.TryCatchHandler();
570 }
571 Address try_catch_handler_address() {
572 return thread_local_top_.try_catch_handler_address();
573 }
574 bool* external_caught_exception_address() {
575 return &thread_local_top_.external_caught_exception_;
576 }
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000577 v8::TryCatch* catcher() {
578 return thread_local_top_.catcher_;
579 }
580 void set_catcher(v8::TryCatch* catcher) {
581 thread_local_top_.catcher_ = catcher;
582 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000583
584 MaybeObject** scheduled_exception_address() {
585 return &thread_local_top_.scheduled_exception_;
586 }
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000587
588 Address pending_message_obj_address() {
589 return reinterpret_cast<Address>(&thread_local_top_.pending_message_obj_);
590 }
591
592 Address has_pending_message_address() {
593 return reinterpret_cast<Address>(&thread_local_top_.has_pending_message_);
594 }
595
596 Address pending_message_script_address() {
597 return reinterpret_cast<Address>(
598 &thread_local_top_.pending_message_script_);
599 }
600
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000601 MaybeObject* scheduled_exception() {
602 ASSERT(has_scheduled_exception());
603 return thread_local_top_.scheduled_exception_;
604 }
605 bool has_scheduled_exception() {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000606 return thread_local_top_.scheduled_exception_ != heap_.the_hole_value();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000607 }
608 void clear_scheduled_exception() {
609 thread_local_top_.scheduled_exception_ = heap_.the_hole_value();
610 }
611
612 bool IsExternallyCaught();
613
614 bool is_catchable_by_javascript(MaybeObject* exception) {
615 return (exception != Failure::OutOfMemoryException()) &&
616 (exception != heap()->termination_exception());
617 }
618
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000619 // Serializer.
620 void PushToPartialSnapshotCache(Object* obj);
621
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000622 // JS execution stack (see frames.h).
623 static Address c_entry_fp(ThreadLocalTop* thread) {
624 return thread->c_entry_fp_;
625 }
626 static Address handler(ThreadLocalTop* thread) { return thread->handler_; }
627
628 inline Address* c_entry_fp_address() {
629 return &thread_local_top_.c_entry_fp_;
630 }
631 inline Address* handler_address() { return &thread_local_top_.handler_; }
632
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000633 // Bottom JS entry (see StackTracer::Trace in log.cc).
634 static Address js_entry_sp(ThreadLocalTop* thread) {
635 return thread->js_entry_sp_;
636 }
637 inline Address* js_entry_sp_address() {
638 return &thread_local_top_.js_entry_sp_;
639 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000640
641 // Generated code scratch locations.
642 void* formal_count_address() { return &thread_local_top_.formal_count_; }
643
644 // Returns the global object of the current context. It could be
ulan@chromium.org2efb9002012-01-19 15:36:35 +0000645 // a builtin object, or a JS global object.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000646 Handle<GlobalObject> global() {
647 return Handle<GlobalObject>(context()->global());
648 }
649
650 // Returns the global proxy object of the current context.
651 Object* global_proxy() {
652 return context()->global_proxy();
653 }
654
655 Handle<JSBuiltinsObject> js_builtins_object() {
656 return Handle<JSBuiltinsObject>(thread_local_top_.context_->builtins());
657 }
658
659 static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); }
660 void FreeThreadResources() { thread_local_top_.Free(); }
661
662 // This method is called by the api after operations that may throw
663 // exceptions. If an exception was thrown and not handled by an external
664 // handler the exception is scheduled to be rethrown when we return to running
665 // JavaScript code. If an exception is scheduled true is returned.
666 bool OptionalRescheduleException(bool is_bottom_call);
667
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000668 class ExceptionScope {
669 public:
670 explicit ExceptionScope(Isolate* isolate) :
671 // Scope currently can only be used for regular exceptions, not
672 // failures like OOM or termination exception.
673 isolate_(isolate),
674 pending_exception_(isolate_->pending_exception()->ToObjectUnchecked()),
675 catcher_(isolate_->catcher())
676 { }
677
678 ~ExceptionScope() {
679 isolate_->set_catcher(catcher_);
680 isolate_->set_pending_exception(*pending_exception_);
681 }
682
683 private:
684 Isolate* isolate_;
685 Handle<Object> pending_exception_;
686 v8::TryCatch* catcher_;
687 };
688
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000689 void SetCaptureStackTraceForUncaughtExceptions(
690 bool capture,
691 int frame_limit,
692 StackTrace::StackTraceOptions options);
693
694 // Tells whether the current context has experienced an out of memory
695 // exception.
696 bool is_out_of_memory();
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000697 bool ignore_out_of_memory() {
698 return thread_local_top_.ignore_out_of_memory_;
699 }
700 void set_ignore_out_of_memory(bool value) {
701 thread_local_top_.ignore_out_of_memory_ = value;
702 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000703
704 void PrintCurrentStackTrace(FILE* out);
705 void PrintStackTrace(FILE* out, char* thread_data);
706 void PrintStack(StringStream* accumulator);
707 void PrintStack();
708 Handle<String> StackTraceString();
709 Handle<JSArray> CaptureCurrentStackTrace(
710 int frame_limit,
711 StackTrace::StackTraceOptions options);
712
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +0000713 void CaptureAndSetCurrentStackTraceFor(Handle<JSObject> error_object);
714
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000715 // Returns if the top context may access the given global object. If
716 // the result is false, the pending exception is guaranteed to be
717 // set.
718 bool MayNamedAccess(JSObject* receiver,
719 Object* key,
720 v8::AccessType type);
721 bool MayIndexedAccess(JSObject* receiver,
722 uint32_t index,
723 v8::AccessType type);
724
725 void SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback);
726 void ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type);
727
728 // Exception throwing support. The caller should use the result
729 // of Throw() as its return value.
730 Failure* Throw(Object* exception, MessageLocation* location = NULL);
731 // Re-throw an exception. This involves no error reporting since
732 // error reporting was handled when the exception was thrown
733 // originally.
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000734 Failure* ReThrow(MaybeObject* exception);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000735 void ScheduleThrow(Object* exception);
736 void ReportPendingMessages();
737 Failure* ThrowIllegalOperation();
738
739 // Promote a scheduled exception to pending. Asserts has_scheduled_exception.
740 Failure* PromoteScheduledException();
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +0000741 void DoThrow(Object* exception, MessageLocation* location);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000742 // Checks if exception should be reported and finds out if it's
743 // caught externally.
744 bool ShouldReportException(bool* can_be_caught_externally,
745 bool catchable_by_javascript);
746
747 // Attempts to compute the current source location, storing the
748 // result in the target out parameter.
749 void ComputeLocation(MessageLocation* target);
750
751 // Override command line flag.
752 void TraceException(bool flag);
753
754 // Out of resource exception helpers.
755 Failure* StackOverflow();
756 Failure* TerminateExecution();
757
758 // Administration
759 void Iterate(ObjectVisitor* v);
760 void Iterate(ObjectVisitor* v, ThreadLocalTop* t);
761 char* Iterate(ObjectVisitor* v, char* t);
762 void IterateThread(ThreadVisitor* v);
763 void IterateThread(ThreadVisitor* v, char* t);
764
765
766 // Returns the current global context.
767 Handle<Context> global_context();
768
769 // Returns the global context of the calling JavaScript code. That
770 // is, the global context of the top-most JavaScript frame.
771 Handle<Context> GetCallingGlobalContext();
772
773 void RegisterTryCatchHandler(v8::TryCatch* that);
774 void UnregisterTryCatchHandler(v8::TryCatch* that);
775
776 char* ArchiveThread(char* to);
777 char* RestoreThread(char* from);
778
779 static const char* const kStackOverflowMessage;
780
781 static const int kUC16AlphabetSize = 256; // See StringSearchBase.
782 static const int kBMMaxShift = 250; // See StringSearchBase.
783
784 // Accessors.
785#define GLOBAL_ACCESSOR(type, name, initialvalue) \
786 inline type name() const { \
787 ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_); \
788 return name##_; \
789 } \
790 inline void set_##name(type value) { \
791 ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_); \
792 name##_ = value; \
793 }
794 ISOLATE_INIT_LIST(GLOBAL_ACCESSOR)
795#undef GLOBAL_ACCESSOR
796
797#define GLOBAL_ARRAY_ACCESSOR(type, name, length) \
798 inline type* name() { \
799 ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_); \
800 return &(name##_)[0]; \
801 }
802 ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_ACCESSOR)
803#undef GLOBAL_ARRAY_ACCESSOR
804
805#define GLOBAL_CONTEXT_FIELD_ACCESSOR(index, type, name) \
806 Handle<type> name() { \
807 return Handle<type>(context()->global_context()->name()); \
808 }
809 GLOBAL_CONTEXT_FIELDS(GLOBAL_CONTEXT_FIELD_ACCESSOR)
810#undef GLOBAL_CONTEXT_FIELD_ACCESSOR
811
812 Bootstrapper* bootstrapper() { return bootstrapper_; }
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000813 Counters* counters() {
814 // Call InitializeLoggingAndCounters() if logging is needed before
815 // the isolate is fully initialized.
816 ASSERT(counters_ != NULL);
817 return counters_;
818 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000819 CodeRange* code_range() { return code_range_; }
820 RuntimeProfiler* runtime_profiler() { return runtime_profiler_; }
821 CompilationCache* compilation_cache() { return compilation_cache_; }
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000822 Logger* logger() {
823 // Call InitializeLoggingAndCounters() if logging is needed before
824 // the isolate is fully initialized.
825 ASSERT(logger_ != NULL);
826 return logger_;
827 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000828 StackGuard* stack_guard() { return &stack_guard_; }
829 Heap* heap() { return &heap_; }
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000830 StatsTable* stats_table();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000831 StubCache* stub_cache() { return stub_cache_; }
832 DeoptimizerData* deoptimizer_data() { return deoptimizer_data_; }
833 ThreadLocalTop* thread_local_top() { return &thread_local_top_; }
834
835 TranscendentalCache* transcendental_cache() const {
836 return transcendental_cache_;
837 }
838
839 MemoryAllocator* memory_allocator() {
840 return memory_allocator_;
841 }
842
843 KeyedLookupCache* keyed_lookup_cache() {
844 return keyed_lookup_cache_;
845 }
846
847 ContextSlotCache* context_slot_cache() {
848 return context_slot_cache_;
849 }
850
851 DescriptorLookupCache* descriptor_lookup_cache() {
852 return descriptor_lookup_cache_;
853 }
854
855 v8::ImplementationUtilities::HandleScopeData* handle_scope_data() {
856 return &handle_scope_data_;
857 }
858 HandleScopeImplementer* handle_scope_implementer() {
859 ASSERT(handle_scope_implementer_);
860 return handle_scope_implementer_;
861 }
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000862 Zone* runtime_zone() { return &runtime_zone_; }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000863
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000864 UnicodeCache* unicode_cache() {
865 return unicode_cache_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000866 }
867
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000868 InnerPointerToCodeCache* inner_pointer_to_code_cache() {
869 return inner_pointer_to_code_cache_;
870 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000871
872 StringInputBuffer* write_input_buffer() { return write_input_buffer_; }
873
874 GlobalHandles* global_handles() { return global_handles_; }
875
876 ThreadManager* thread_manager() { return thread_manager_; }
877
878 ContextSwitcher* context_switcher() { return context_switcher_; }
879
880 void set_context_switcher(ContextSwitcher* switcher) {
881 context_switcher_ = switcher;
882 }
883
884 StringTracker* string_tracker() { return string_tracker_; }
885
886 unibrow::Mapping<unibrow::Ecma262UnCanonicalize>* jsregexp_uncanonicalize() {
887 return &jsregexp_uncanonicalize_;
888 }
889
890 unibrow::Mapping<unibrow::CanonicalizationRange>* jsregexp_canonrange() {
891 return &jsregexp_canonrange_;
892 }
893
894 StringInputBuffer* objects_string_compare_buffer_a() {
895 return &objects_string_compare_buffer_a_;
896 }
897
898 StringInputBuffer* objects_string_compare_buffer_b() {
899 return &objects_string_compare_buffer_b_;
900 }
901
902 StaticResource<StringInputBuffer>* objects_string_input_buffer() {
903 return &objects_string_input_buffer_;
904 }
905
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000906 RuntimeState* runtime_state() { return &runtime_state_; }
907
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000908 void set_fp_stubs_generated(bool value) {
909 fp_stubs_generated_ = value;
910 }
911
912 bool fp_stubs_generated() { return fp_stubs_generated_; }
913
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000914 StaticResource<SafeStringInputBuffer>* compiler_safe_string_input_buffer() {
915 return &compiler_safe_string_input_buffer_;
916 }
917
918 Builtins* builtins() { return &builtins_; }
919
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000920 void NotifyExtensionInstalled() {
921 has_installed_extensions_ = true;
922 }
923
924 bool has_installed_extensions() { return has_installed_extensions_; }
925
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000926 unibrow::Mapping<unibrow::Ecma262Canonicalize>*
927 regexp_macro_assembler_canonicalize() {
928 return &regexp_macro_assembler_canonicalize_;
929 }
930
931 RegExpStack* regexp_stack() { return regexp_stack_; }
932
933 unibrow::Mapping<unibrow::Ecma262Canonicalize>*
934 interp_canonicalize_mapping() {
935 return &interp_canonicalize_mapping_;
936 }
937
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000938 void* PreallocatedStorageNew(size_t size);
939 void PreallocatedStorageDelete(void* p);
940 void PreallocatedStorageInit(size_t size);
941
942#ifdef ENABLE_DEBUGGER_SUPPORT
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000943 Debugger* debugger() {
944 if (!NoBarrier_Load(&debugger_initialized_)) InitializeDebugger();
945 return debugger_;
946 }
947 Debug* debug() {
948 if (!NoBarrier_Load(&debugger_initialized_)) InitializeDebugger();
949 return debug_;
950 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000951#endif
952
danno@chromium.org88aa0582012-03-23 15:11:57 +0000953 inline bool IsDebuggerActive();
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000954 inline bool DebuggerHasBreakPoints();
955
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000956#ifdef DEBUG
957 HistogramInfo* heap_histograms() { return heap_histograms_; }
958
959 JSObject::SpillInformation* js_spill_information() {
960 return &js_spill_information_;
961 }
962
963 int* code_kind_statistics() { return code_kind_statistics_; }
964#endif
965
lrn@chromium.org7516f052011-03-30 08:52:27 +0000966#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
967 defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000968 bool simulator_initialized() { return simulator_initialized_; }
969 void set_simulator_initialized(bool initialized) {
970 simulator_initialized_ = initialized;
971 }
972
973 HashMap* simulator_i_cache() { return simulator_i_cache_; }
974 void set_simulator_i_cache(HashMap* hash_map) {
975 simulator_i_cache_ = hash_map;
976 }
977
978 Redirection* simulator_redirection() {
979 return simulator_redirection_;
980 }
981 void set_simulator_redirection(Redirection* redirection) {
982 simulator_redirection_ = redirection;
983 }
984#endif
985
986 Factory* factory() { return reinterpret_cast<Factory*>(this); }
987
988 // SerializerDeserializer state.
989 static const int kPartialSnapshotCacheCapacity = 1400;
990
mstarzinger@chromium.org15613d02012-05-23 12:04:37 +0000991 static const int kJSRegexpStaticOffsetsVectorSize = 128;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000992
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000993 Address external_callback() {
994 return thread_local_top_.external_callback_;
995 }
996 void set_external_callback(Address callback) {
997 thread_local_top_.external_callback_ = callback;
998 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000999
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001000 StateTag current_vm_state() {
1001 return thread_local_top_.current_vm_state_;
1002 }
1003
1004 void SetCurrentVMState(StateTag state) {
1005 if (RuntimeProfiler::IsEnabled()) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001006 // Make sure thread local top is initialized.
1007 ASSERT(thread_local_top_.isolate_ == this);
vitalyr@chromium.orgb803dc22011-04-07 21:57:01 +00001008 StateTag current_state = thread_local_top_.current_vm_state_;
1009 if (current_state != JS && state == JS) {
1010 // Non-JS -> JS transition.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001011 RuntimeProfiler::IsolateEnteredJS(this);
vitalyr@chromium.orgb803dc22011-04-07 21:57:01 +00001012 } else if (current_state == JS && state != JS) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001013 // JS -> non-JS transition.
1014 ASSERT(RuntimeProfiler::IsSomeIsolateInJS());
1015 RuntimeProfiler::IsolateExitedJS(this);
vitalyr@chromium.orgb803dc22011-04-07 21:57:01 +00001016 } else {
1017 // Other types of state transitions are not interesting to the
1018 // runtime profiler, because they don't affect whether we're
1019 // in JS or not.
1020 ASSERT((current_state == JS) == (state == JS));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001021 }
1022 }
1023 thread_local_top_.current_vm_state_ = state;
1024 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001025
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001026 void SetData(void* data) { embedder_data_ = data; }
1027 void* GetData() { return embedder_data_; }
1028
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001029 LookupResult* top_lookup_result() {
1030 return thread_local_top_.top_lookup_result_;
1031 }
1032 void SetTopLookupResult(LookupResult* top) {
1033 thread_local_top_.top_lookup_result_ = top;
1034 }
1035
ulan@chromium.org2efb9002012-01-19 15:36:35 +00001036 bool context_exit_happened() {
1037 return context_exit_happened_;
1038 }
1039 void set_context_exit_happened(bool context_exit_happened) {
1040 context_exit_happened_ = context_exit_happened;
1041 }
1042
rossberg@chromium.org994edf62012-02-06 10:12:55 +00001043 double time_millis_since_init() {
1044 return OS::TimeCurrentMillis() - time_millis_at_init_;
1045 }
1046
svenpanne@chromium.org4efbdb12012-03-12 08:18:42 +00001047 DateCache* date_cache() {
1048 return date_cache_;
1049 }
1050
1051 void set_date_cache(DateCache* date_cache) {
1052 if (date_cache != date_cache_) {
1053 delete date_cache_;
1054 }
1055 date_cache_ = date_cache;
1056 }
1057
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001058 private:
1059 Isolate();
1060
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001061 friend struct GlobalState;
1062 friend struct InitializeGlobalState;
1063
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +00001064 enum State {
1065 UNINITIALIZED, // Some components may not have been allocated.
1066 INITIALIZED // All components are fully initialized.
1067 };
1068
1069 // These fields are accessed through the API, offsets must be kept in sync
1070 // with v8::internal::Internals (in include/v8.h) constants. This is also
1071 // verified in Isolate::Init() using runtime checks.
1072 State state_; // Will be padded to kApiPointerSize.
1073 void* embedder_data_;
1074 Heap heap_;
1075
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001076 // The per-process lock should be acquired before the ThreadDataTable is
1077 // modified.
1078 class ThreadDataTable {
1079 public:
1080 ThreadDataTable();
1081 ~ThreadDataTable();
1082
1083 PerIsolateThreadData* Lookup(Isolate* isolate, ThreadId thread_id);
1084 void Insert(PerIsolateThreadData* data);
1085 void Remove(Isolate* isolate, ThreadId thread_id);
1086 void Remove(PerIsolateThreadData* data);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +00001087 void RemoveAllThreads(Isolate* isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001088
1089 private:
1090 PerIsolateThreadData* list_;
1091 };
1092
1093 // These items form a stack synchronously with threads Enter'ing and Exit'ing
1094 // the Isolate. The top of the stack points to a thread which is currently
1095 // running the Isolate. When the stack is empty, the Isolate is considered
1096 // not entered by any thread and can be Disposed.
1097 // If the same thread enters the Isolate more then once, the entry_count_
1098 // is incremented rather then a new item pushed to the stack.
1099 class EntryStackItem {
1100 public:
1101 EntryStackItem(PerIsolateThreadData* previous_thread_data,
1102 Isolate* previous_isolate,
1103 EntryStackItem* previous_item)
1104 : entry_count(1),
1105 previous_thread_data(previous_thread_data),
1106 previous_isolate(previous_isolate),
1107 previous_item(previous_item) { }
1108
1109 int entry_count;
1110 PerIsolateThreadData* previous_thread_data;
1111 Isolate* previous_isolate;
1112 EntryStackItem* previous_item;
1113
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001114 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001115 DISALLOW_COPY_AND_ASSIGN(EntryStackItem);
1116 };
1117
danno@chromium.org8c0a43f2012-04-03 08:37:53 +00001118 // This mutex protects highest_thread_id_, thread_data_table_ and
1119 // default_isolate_.
1120 static Mutex* process_wide_mutex_;
1121
1122 static Thread::LocalStorageKey per_isolate_thread_data_key_;
1123 static Thread::LocalStorageKey isolate_key_;
1124 static Thread::LocalStorageKey thread_id_key_;
1125 static Isolate* default_isolate_;
1126 static ThreadDataTable* thread_data_table_;
1127
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001128 void Deinit();
1129
1130 static void SetIsolateThreadLocals(Isolate* isolate,
1131 PerIsolateThreadData* data);
1132
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001133 // Allocate and insert PerIsolateThreadData into the ThreadDataTable
1134 // (regardless of whether such data already exists).
1135 PerIsolateThreadData* AllocatePerIsolateThreadData(ThreadId thread_id);
1136
1137 // Find the PerThread for this particular (isolate, thread) combination.
1138 // If one does not yet exist, allocate a new one.
1139 PerIsolateThreadData* FindOrAllocatePerThreadDataForThisThread();
1140
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001141 // PreInits and returns a default isolate. Needed when a new thread tries
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001142 // to create a Locker for the first time (the lock itself is in the isolate).
1143 static Isolate* GetDefaultIsolateForLocking();
1144
1145 // Initializes the current thread to run this Isolate.
1146 // Not thread-safe. Multiple threads should not Enter/Exit the same isolate
1147 // at the same time, this should be prevented using external locking.
1148 void Enter();
1149
1150 // Exits the current thread. The previosuly entered Isolate is restored
1151 // for the thread.
1152 // Not thread-safe. Multiple threads should not Enter/Exit the same isolate
1153 // at the same time, this should be prevented using external locking.
1154 void Exit();
1155
1156 void PreallocatedMemoryThreadStart();
1157 void PreallocatedMemoryThreadStop();
1158 void InitializeThreadLocal();
1159
1160 void PrintStackTrace(FILE* out, ThreadLocalTop* thread);
1161 void MarkCompactPrologue(bool is_compacting,
1162 ThreadLocalTop* archived_thread_data);
1163 void MarkCompactEpilogue(bool is_compacting,
1164 ThreadLocalTop* archived_thread_data);
1165
1166 void FillCache();
1167
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001168 void PropagatePendingExceptionToExternalTryCatch();
1169
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00001170 void InitializeDebugger();
1171
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +00001172 // Traverse prototype chain to find out whether the object is derived from
1173 // the Error object.
1174 bool IsErrorObject(Handle<Object> obj);
1175
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +00001176 EntryStackItem* entry_stack_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001177 int stack_trace_nesting_level_;
1178 StringStream* incomplete_message_;
1179 // The preallocated memory thread singleton.
1180 PreallocatedMemoryThread* preallocated_memory_thread_;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001181 Address isolate_addresses_[kIsolateAddressCount + 1]; // NOLINT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001182 NoAllocationStringAllocator* preallocated_message_space_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001183 Bootstrapper* bootstrapper_;
1184 RuntimeProfiler* runtime_profiler_;
1185 CompilationCache* compilation_cache_;
1186 Counters* counters_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001187 CodeRange* code_range_;
1188 Mutex* break_access_;
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00001189 Atomic32 debugger_initialized_;
1190 Mutex* debugger_access_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001191 Logger* logger_;
1192 StackGuard stack_guard_;
1193 StatsTable* stats_table_;
1194 StubCache* stub_cache_;
1195 DeoptimizerData* deoptimizer_data_;
1196 ThreadLocalTop thread_local_top_;
1197 bool capture_stack_trace_for_uncaught_exceptions_;
1198 int stack_trace_for_uncaught_exceptions_frame_limit_;
1199 StackTrace::StackTraceOptions stack_trace_for_uncaught_exceptions_options_;
1200 TranscendentalCache* transcendental_cache_;
1201 MemoryAllocator* memory_allocator_;
1202 KeyedLookupCache* keyed_lookup_cache_;
1203 ContextSlotCache* context_slot_cache_;
1204 DescriptorLookupCache* descriptor_lookup_cache_;
1205 v8::ImplementationUtilities::HandleScopeData handle_scope_data_;
1206 HandleScopeImplementer* handle_scope_implementer_;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +00001207 UnicodeCache* unicode_cache_;
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001208 Zone runtime_zone_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001209 PreallocatedStorage in_use_list_;
1210 PreallocatedStorage free_list_;
1211 bool preallocated_storage_preallocated_;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001212 InnerPointerToCodeCache* inner_pointer_to_code_cache_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001213 StringInputBuffer* write_input_buffer_;
1214 GlobalHandles* global_handles_;
1215 ContextSwitcher* context_switcher_;
1216 ThreadManager* thread_manager_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001217 RuntimeState runtime_state_;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001218 bool fp_stubs_generated_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001219 StaticResource<SafeStringInputBuffer> compiler_safe_string_input_buffer_;
1220 Builtins builtins_;
ricow@chromium.org27bf2882011-11-17 08:34:43 +00001221 bool has_installed_extensions_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001222 StringTracker* string_tracker_;
1223 unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize_;
1224 unibrow::Mapping<unibrow::CanonicalizationRange> jsregexp_canonrange_;
1225 StringInputBuffer objects_string_compare_buffer_a_;
1226 StringInputBuffer objects_string_compare_buffer_b_;
1227 StaticResource<StringInputBuffer> objects_string_input_buffer_;
1228 unibrow::Mapping<unibrow::Ecma262Canonicalize>
1229 regexp_macro_assembler_canonicalize_;
1230 RegExpStack* regexp_stack_;
svenpanne@chromium.org4efbdb12012-03-12 08:18:42 +00001231 DateCache* date_cache_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001232 unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize_mapping_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001233
ulan@chromium.org2efb9002012-01-19 15:36:35 +00001234 // The garbage collector should be a little more aggressive when it knows
1235 // that a context was recently exited.
1236 bool context_exit_happened_;
1237
rossberg@chromium.org994edf62012-02-06 10:12:55 +00001238 // Time stamp at initialization.
1239 double time_millis_at_init_;
1240
lrn@chromium.org7516f052011-03-30 08:52:27 +00001241#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
1242 defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001243 bool simulator_initialized_;
1244 HashMap* simulator_i_cache_;
1245 Redirection* simulator_redirection_;
1246#endif
1247
1248#ifdef DEBUG
1249 // A static array of histogram info for each type.
1250 HistogramInfo heap_histograms_[LAST_TYPE + 1];
1251 JSObject::SpillInformation js_spill_information_;
1252 int code_kind_statistics_[Code::NUMBER_OF_KINDS];
1253#endif
1254
1255#ifdef ENABLE_DEBUGGER_SUPPORT
1256 Debugger* debugger_;
1257 Debug* debug_;
1258#endif
1259
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001260#define GLOBAL_BACKING_STORE(type, name, initialvalue) \
1261 type name##_;
1262 ISOLATE_INIT_LIST(GLOBAL_BACKING_STORE)
1263#undef GLOBAL_BACKING_STORE
1264
1265#define GLOBAL_ARRAY_BACKING_STORE(type, name, length) \
1266 type name##_[length];
1267 ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_BACKING_STORE)
1268#undef GLOBAL_ARRAY_BACKING_STORE
1269
1270#ifdef DEBUG
1271 // This class is huge and has a number of fields controlled by
1272 // preprocessor defines. Make sure the offsets of these fields agree
1273 // between compilation units.
1274#define ISOLATE_FIELD_OFFSET(type, name, ignored) \
1275 static const intptr_t name##_debug_offset_;
1276 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
1277 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
1278#undef ISOLATE_FIELD_OFFSET
1279#endif
1280
1281 friend class ExecutionAccess;
1282 friend class IsolateInitializer;
lrn@chromium.org1c092762011-05-09 09:42:16 +00001283 friend class ThreadManager;
1284 friend class Simulator;
1285 friend class StackGuard;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +00001286 friend class ThreadId;
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00001287 friend class TestMemoryAllocatorScope;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001288 friend class v8::Isolate;
1289 friend class v8::Locker;
lrn@chromium.org1c092762011-05-09 09:42:16 +00001290 friend class v8::Unlocker;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001291
1292 DISALLOW_COPY_AND_ASSIGN(Isolate);
1293};
1294
1295
1296// If the GCC version is 4.1.x or 4.2.x an additional field is added to the
1297// class as a work around for a bug in the generated code found with these
1298// versions of GCC. See V8 issue 122 for details.
1299class SaveContext BASE_EMBEDDED {
1300 public:
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001301 inline explicit SaveContext(Isolate* isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001302
1303 ~SaveContext() {
1304 if (context_.is_null()) {
1305 Isolate* isolate = Isolate::Current();
1306 isolate->set_context(NULL);
1307 isolate->set_save_context(prev_);
1308 } else {
1309 Isolate* isolate = context_->GetIsolate();
1310 isolate->set_context(*context_);
1311 isolate->set_save_context(prev_);
1312 }
1313 }
1314
1315 Handle<Context> context() { return context_; }
1316 SaveContext* prev() { return prev_; }
1317
1318 // Returns true if this save context is below a given JavaScript frame.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001319 bool IsBelowFrame(JavaScriptFrame* frame) {
1320 return (c_entry_fp_ == 0) || (c_entry_fp_ > frame->sp());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001321 }
1322
1323 private:
1324 Handle<Context> context_;
1325#if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300
1326 Handle<Context> dummy_;
1327#endif
1328 SaveContext* prev_;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001329 Address c_entry_fp_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001330};
1331
1332
1333class AssertNoContextChange BASE_EMBEDDED {
1334#ifdef DEBUG
1335 public:
1336 AssertNoContextChange() :
1337 scope_(Isolate::Current()),
1338 context_(Isolate::Current()->context(), Isolate::Current()) {
1339 }
1340
1341 ~AssertNoContextChange() {
1342 ASSERT(Isolate::Current()->context() == *context_);
1343 }
1344
1345 private:
1346 HandleScope scope_;
1347 Handle<Context> context_;
1348#else
1349 public:
1350 AssertNoContextChange() { }
1351#endif
1352};
1353
1354
1355class ExecutionAccess BASE_EMBEDDED {
1356 public:
1357 explicit ExecutionAccess(Isolate* isolate) : isolate_(isolate) {
1358 Lock(isolate);
1359 }
1360 ~ExecutionAccess() { Unlock(isolate_); }
1361
1362 static void Lock(Isolate* isolate) { isolate->break_access_->Lock(); }
1363 static void Unlock(Isolate* isolate) { isolate->break_access_->Unlock(); }
1364
1365 static bool TryLock(Isolate* isolate) {
1366 return isolate->break_access_->TryLock();
1367 }
1368
1369 private:
1370 Isolate* isolate_;
1371};
1372
1373
1374// Support for checking for stack-overflows in C++ code.
1375class StackLimitCheck BASE_EMBEDDED {
1376 public:
1377 explicit StackLimitCheck(Isolate* isolate) : isolate_(isolate) { }
1378
1379 bool HasOverflowed() const {
1380 StackGuard* stack_guard = isolate_->stack_guard();
1381 // Stack has overflowed in C++ code only if stack pointer exceeds the C++
1382 // stack guard and the limits are not set to interrupt values.
1383 // TODO(214): Stack overflows are ignored if a interrupt is pending. This
1384 // code should probably always use the initial C++ limit.
1385 return (reinterpret_cast<uintptr_t>(this) < stack_guard->climit()) &&
1386 stack_guard->IsStackOverflow();
1387 }
1388 private:
1389 Isolate* isolate_;
1390};
1391
1392
1393// Support for temporarily postponing interrupts. When the outermost
1394// postpone scope is left the interrupts will be re-enabled and any
1395// interrupts that occurred while in the scope will be taken into
1396// account.
1397class PostponeInterruptsScope BASE_EMBEDDED {
1398 public:
1399 explicit PostponeInterruptsScope(Isolate* isolate)
1400 : stack_guard_(isolate->stack_guard()) {
1401 stack_guard_->thread_local_.postpone_interrupts_nesting_++;
1402 stack_guard_->DisableInterrupts();
1403 }
1404
1405 ~PostponeInterruptsScope() {
1406 if (--stack_guard_->thread_local_.postpone_interrupts_nesting_ == 0) {
1407 stack_guard_->EnableInterrupts();
1408 }
1409 }
1410 private:
1411 StackGuard* stack_guard_;
1412};
1413
1414
1415// Temporary macros for accessing current isolate and its subobjects.
1416// They provide better readability, especially when used a lot in the code.
1417#define HEAP (v8::internal::Isolate::Current()->heap())
1418#define FACTORY (v8::internal::Isolate::Current()->factory())
1419#define ISOLATE (v8::internal::Isolate::Current())
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001420#define LOGGER (v8::internal::Isolate::Current()->logger())
1421
1422
1423// Tells whether the global context is marked with out of memory.
1424inline bool Context::has_out_of_memory() {
1425 return global_context()->out_of_memory()->IsTrue();
1426}
1427
1428
1429// Mark the global context with out of memory.
1430inline void Context::mark_out_of_memory() {
1431 global_context()->set_out_of_memory(HEAP->true_value());
1432}
1433
1434
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001435} } // namespace v8::internal
1436
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001437#endif // V8_ISOLATE_H_