| Index: src/isolate.h
|
| ===================================================================
|
| --- src/isolate.h (revision 4906)
|
| +++ src/isolate.h (working copy)
|
| @@ -31,8 +31,12 @@
|
| // #define V8_USE_TLS_FOR_GLOBAL_ISOLATE
|
|
|
| #include "apiutils.h"
|
| +#include "contexts.h"
|
| +#include "execution.h"
|
| +#include "frames-inl.h"
|
| +#include "frames.h"
|
| +#include "handles.h"
|
| #include "heap.h"
|
| -#include "execution.h"
|
| #include "zone.h"
|
|
|
| namespace v8 {
|
| @@ -44,10 +48,32 @@
|
| class CpuFeatures;
|
| class Deserializer;
|
| class HandleScopeImplementer;
|
| +class NoAllocationStringAllocator;
|
| +class PreallocatedMemoryThread;
|
| class SaveContext;
|
| class StubCache;
|
| class ScannerCharacterClasses;
|
| +class ThreadVisitor; // Defined in v8threads.h
|
|
|
| +#define RETURN_IF_SCHEDULED_EXCEPTION() \
|
| + if (Isolate::Current()->has_scheduled_exception()) \
|
| + return Isolate::Current()->PromoteScheduledException()
|
| +
|
| +#define ISOLATE_ADDRESS_LIST(C) \
|
| + C(handler_address) \
|
| + C(c_entry_fp_address) \
|
| + C(context_address) \
|
| + C(pending_exception_address) \
|
| + C(external_caught_exception_address)
|
| +
|
| +#ifdef ENABLE_LOGGING_AND_PROFILING
|
| +#define ISOLATE_ADDRESS_LIST_PROF(C) \
|
| + C(js_entry_sp_address)
|
| +#else
|
| +#define ISOLATE_ADDRESS_LIST_PROF(C)
|
| +#endif
|
| +
|
| +
|
| class ThreadLocalTop BASE_EMBEDDED {
|
| public:
|
| // Initialize the thread data.
|
| @@ -154,6 +180,14 @@
|
| public:
|
| ~Isolate();
|
|
|
| + enum AddressId {
|
| +#define C(name) k_##name,
|
| + ISOLATE_ADDRESS_LIST(C)
|
| + ISOLATE_ADDRESS_LIST_PROF(C)
|
| +#undef C
|
| + k_isolate_address_count
|
| + };
|
| +
|
| // Returns the single global isolate.
|
| static Isolate* Current() {
|
| #ifdef V8_USE_TLS_FOR_GLOBAL_ISOLATE
|
| @@ -174,10 +208,231 @@
|
| static Isolate* InitThreadForGlobalIsolate();
|
| #endif
|
|
|
| + // Destroy the global isolate and create a new one in its place.
|
| + static void TearDownAndRecreateGlobalIsolate();
|
| +
|
| // Creates a new isolate (perhaps using a deserializer). Returns null
|
| // on failure.
|
| static Isolate* Create(Deserializer* des);
|
|
|
| + // Debug.
|
| + // Mutex for serializing access to break control structures.
|
| + Mutex* break_access() { return break_access_; }
|
| +
|
| + Address get_address_from_id(AddressId id);
|
| +
|
| + // Access to top context (where the current function object was created).
|
| + Context* context() { return thread_local_top_.context_; }
|
| + void set_context(Context* context) {
|
| + thread_local_top_.context_ = context;
|
| + }
|
| + Context** context_address() { return &thread_local_top_.context_; }
|
| +
|
| + SaveContext* save_context() {return thread_local_top_.save_context_; }
|
| + void set_save_context(SaveContext* save) {
|
| + thread_local_top_.save_context_ = save;
|
| + }
|
| +
|
| + // Access to current thread id.
|
| + int thread_id() { return thread_local_top_.thread_id_; }
|
| + void set_thread_id(int id) { thread_local_top_.thread_id_ = id; }
|
| +
|
| + // Interface to pending exception.
|
| + Object* pending_exception() {
|
| + ASSERT(has_pending_exception());
|
| + return thread_local_top_.pending_exception_;
|
| + }
|
| + bool external_caught_exception() {
|
| + return thread_local_top_.external_caught_exception_;
|
| + }
|
| + void set_pending_exception(Object* exception) {
|
| + thread_local_top_.pending_exception_ = exception;
|
| + }
|
| + void clear_pending_exception() {
|
| + thread_local_top_.pending_exception_ = heap_.the_hole_value();
|
| + }
|
| + Object** pending_exception_address() {
|
| + return &thread_local_top_.pending_exception_;
|
| + }
|
| + bool has_pending_exception() {
|
| + return !thread_local_top_.pending_exception_->IsTheHole();
|
| + }
|
| + void clear_pending_message() {
|
| + thread_local_top_.has_pending_message_ = false;
|
| + thread_local_top_.pending_message_ = NULL;
|
| + thread_local_top_.pending_message_obj_ = heap_.the_hole_value();
|
| + thread_local_top_.pending_message_script_ = NULL;
|
| + }
|
| + v8::TryCatch* try_catch_handler() {
|
| + return thread_local_top_.TryCatchHandler();
|
| + }
|
| + Address try_catch_handler_address() {
|
| + return thread_local_top_.try_catch_handler_address();
|
| + }
|
| + bool* external_caught_exception_address() {
|
| + return &thread_local_top_.external_caught_exception_;
|
| + }
|
| +
|
| + Object** scheduled_exception_address() {
|
| + return &thread_local_top_.scheduled_exception_;
|
| + }
|
| + Object* scheduled_exception() {
|
| + ASSERT(has_scheduled_exception());
|
| + return thread_local_top_.scheduled_exception_;
|
| + }
|
| + bool has_scheduled_exception() {
|
| + return !thread_local_top_.scheduled_exception_->IsTheHole();
|
| + }
|
| + void clear_scheduled_exception() {
|
| + thread_local_top_.scheduled_exception_ = heap_.the_hole_value();
|
| + }
|
| +
|
| + void setup_external_caught() {
|
| + thread_local_top_.external_caught_exception_ =
|
| + has_pending_exception() &&
|
| + (thread_local_top_.catcher_ != NULL) &&
|
| + (try_catch_handler() == thread_local_top_.catcher_);
|
| + }
|
| +
|
| + // JS execution stack (see frames.h).
|
| + static Address c_entry_fp(ThreadLocalTop* thread) {
|
| + return thread->c_entry_fp_;
|
| + }
|
| + static Address handler(ThreadLocalTop* thread) { return thread->handler_; }
|
| +
|
| + inline Address* c_entry_fp_address() {
|
| + return &thread_local_top_.c_entry_fp_;
|
| + }
|
| + inline Address* handler_address() { return &thread_local_top_.handler_; }
|
| +
|
| +#ifdef ENABLE_LOGGING_AND_PROFILING
|
| + // Bottom JS entry (see StackTracer::Trace in log.cc).
|
| + static Address js_entry_sp(ThreadLocalTop* thread) {
|
| + return thread->js_entry_sp_;
|
| + }
|
| + inline Address* js_entry_sp_address() {
|
| + return &thread_local_top_.js_entry_sp_;
|
| + }
|
| +#endif
|
| +
|
| + // Generated code scratch locations.
|
| + void* formal_count_address() { return &thread_local_top_.formal_count_; }
|
| +
|
| + // Returns the global object of the current context. It could be
|
| + // a builtin object, or a js global object.
|
| + Handle<GlobalObject> global() {
|
| + return Handle<GlobalObject>(context()->global());
|
| + }
|
| +
|
| + // Returns the global proxy object of the current context.
|
| + Object* global_proxy() {
|
| + return context()->global_proxy();
|
| + }
|
| +
|
| + Handle<JSBuiltinsObject> builtins() {
|
| + return Handle<JSBuiltinsObject>(thread_local_top_.context_->builtins());
|
| + }
|
| +
|
| + static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); }
|
| + void FreeThreadResources() { thread_local_top_.Free(); }
|
| +
|
| + // This method is called by the api after operations that may throw
|
| + // exceptions. If an exception was thrown and not handled by an external
|
| + // handler the exception is scheduled to be rethrown when we return to running
|
| + // JavaScript code. If an exception is scheduled true is returned.
|
| + bool OptionalRescheduleException(bool is_bottom_call);
|
| +
|
| +
|
| + // Tells whether the current context has experienced an out of memory
|
| + // exception.
|
| + bool is_out_of_memory();
|
| +
|
| +
|
| + void MarkCompactPrologue(bool is_compacting);
|
| + void MarkCompactEpilogue(bool is_compacting);
|
| + void MarkCompactPrologue(bool is_compacting,
|
| + char* archived_thread_data);
|
| + void MarkCompactEpilogue(bool is_compacting,
|
| + char* archived_thread_data);
|
| + void PrintCurrentStackTrace(FILE* out);
|
| + void PrintStackTrace(FILE* out, char* thread_data);
|
| + void PrintStack(StringStream* accumulator);
|
| + void PrintStack();
|
| + Handle<String> StackTraceString();
|
| + Local<StackTrace> CaptureCurrentStackTrace(
|
| + int frame_limit,
|
| + StackTrace::StackTraceOptions options);
|
| +
|
| + // Returns if the top context may access the given global object. If
|
| + // the result is false, the pending exception is guaranteed to be
|
| + // set.
|
| + bool MayNamedAccess(JSObject* receiver,
|
| + Object* key,
|
| + v8::AccessType type);
|
| + bool MayIndexedAccess(JSObject* receiver,
|
| + uint32_t index,
|
| + v8::AccessType type);
|
| +
|
| + void SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback);
|
| + void ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type);
|
| +
|
| + // Exception throwing support. The caller should use the result
|
| + // of Throw() as its return value.
|
| + Failure* Throw(Object* exception, MessageLocation* location = NULL);
|
| + // Re-throw an exception. This involves no error reporting since
|
| + // error reporting was handled when the exception was thrown
|
| + // originally.
|
| + Failure* ReThrow(Object* exception, MessageLocation* location = NULL);
|
| + void ScheduleThrow(Object* exception);
|
| + void ReportPendingMessages();
|
| + Failure* ThrowIllegalOperation();
|
| +
|
| + // Promote a scheduled exception to pending. Asserts has_scheduled_exception.
|
| + Object* PromoteScheduledException();
|
| + void DoThrow(Object* exception,
|
| + MessageLocation* location,
|
| + const char* message);
|
| + bool ShouldReturnException(bool* is_caught_externally,
|
| + bool catchable_by_javascript);
|
| + void ReportUncaughtException(Handle<Object> exception,
|
| + MessageLocation* location,
|
| + Handle<String> stack_trace);
|
| +
|
| + // Attempts to compute the current source location, storing the
|
| + // result in the target out parameter.
|
| + void ComputeLocation(MessageLocation* target);
|
| +
|
| + // Override command line flag.
|
| + void TraceException(bool flag);
|
| +
|
| + // Out of resource exception helpers.
|
| + Failure* StackOverflow();
|
| + Failure* TerminateExecution();
|
| +
|
| + // Administration
|
| + void Iterate(ObjectVisitor* v);
|
| + void Iterate(ObjectVisitor* v, ThreadLocalTop* t);
|
| + char* Iterate(ObjectVisitor* v, char* t);
|
| + void IterateThread(ThreadVisitor* v);
|
| + void IterateThread(ThreadVisitor* v, char* t);
|
| +
|
| +
|
| + // Returns the current global context.
|
| + Handle<Context> global_context();
|
| +
|
| + // Returns the global context of the calling JavaScript code. That
|
| + // is, the global context of the top-most JavaScript frame.
|
| + Handle<Context> GetCallingGlobalContext();
|
| +
|
| + void RegisterTryCatchHandler(v8::TryCatch* that);
|
| + void UnregisterTryCatchHandler(v8::TryCatch* that);
|
| +
|
| + char* ArchiveThread(char* to);
|
| + char* RestoreThread(char* from);
|
| +
|
| + static const char* kStackOverflowMessage;
|
| +
|
| + // Accessors.
|
| #define GLOBAL_ACCESSOR(type, name, initialvalue) \
|
| type name() const { return name##_; } \
|
| void set_##name(type value) { name##_ = value; }
|
| @@ -189,11 +444,13 @@
|
| ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_ACCESSOR)
|
| #undef GLOBAL_ARRAY_ACCESSOR
|
|
|
| - // Debug.
|
| - // Mutex for serializing access to break control structures.
|
| - Mutex* break_access() { return break_access_; }
|
| +#define GLOBAL_CONTEXT_FIELD_ACCESSOR(index, type, name) \
|
| + Handle<type> name() { \
|
| + return Handle<type>(context()->global_context()->name()); \
|
| + }
|
| + GLOBAL_CONTEXT_FIELDS(GLOBAL_CONTEXT_FIELD_ACCESSOR)
|
| +#undef GLOBAL_CONTEXT_FIELD_ACCESSOR
|
|
|
| - // Accessors.
|
| Bootstrapper* bootstrapper() { return bootstrapper_; }
|
| CpuFeatures* cpu_features() { return cpu_features_; }
|
| CompilationCache* compilation_cache() { return compilation_cache_; }
|
| @@ -262,6 +519,25 @@
|
|
|
| State state_;
|
|
|
| + void PreallocatedMemoryThreadStart();
|
| + void PreallocatedMemoryThreadStop();
|
| + void InitializeThreadLocal();
|
| +
|
| + void PrintStackTrace(FILE* out, ThreadLocalTop* thread);
|
| + void MarkCompactPrologue(bool is_compacting,
|
| + ThreadLocalTop* archived_thread_data);
|
| + void MarkCompactEpilogue(bool is_compacting,
|
| + ThreadLocalTop* archived_thread_data);
|
| +
|
| + void FillCache();
|
| +
|
| + int stack_trace_nesting_level_;
|
| + StringStream* incomplete_message_;
|
| + // The preallocated memory thread singleton.
|
| + PreallocatedMemoryThread* preallocated_memory_thread_;
|
| + Address isolate_addresses_[k_isolate_address_count + 1];
|
| + NoAllocationStringAllocator* preallocated_message_space_;
|
| +
|
| Bootstrapper* bootstrapper_;
|
| CompilationCache* compilation_cache_;
|
| CpuFeatures* cpu_features_;
|
| @@ -295,6 +571,75 @@
|
| };
|
|
|
|
|
| +// If the GCC version is 4.1.x or 4.2.x an additional field is added to the
|
| +// class as a work around for a bug in the generated code found with these
|
| +// versions of GCC. See V8 issue 122 for details.
|
| +class SaveContext BASE_EMBEDDED {
|
| + public:
|
| + SaveContext()
|
| + : context_(Isolate::Current()->context()),
|
| +#if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300
|
| + dummy_(Isolate::Current()->context()),
|
| +#endif
|
| + prev_(Isolate::Current()->save_context()) {
|
| + Isolate::Current()->set_save_context(this);
|
| +
|
| + // If there is no JS frame under the current C frame, use the value 0.
|
| + JavaScriptFrameIterator it;
|
| + js_sp_ = it.done() ? 0 : it.frame()->sp();
|
| + }
|
| +
|
| + ~SaveContext() {
|
| + Isolate::Current()->set_context(*context_);
|
| + Isolate::Current()->set_save_context(prev_);
|
| + }
|
| +
|
| + Handle<Context> context() { return context_; }
|
| + SaveContext* prev() { return prev_; }
|
| +
|
| + // Returns true if this save context is below a given JavaScript frame.
|
| + bool below(JavaScriptFrame* frame) {
|
| + return (js_sp_ == 0) || (frame->sp() < js_sp_);
|
| + }
|
| +
|
| + private:
|
| + Handle<Context> context_;
|
| +#if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300
|
| + Handle<Context> dummy_;
|
| +#endif
|
| + SaveContext* prev_;
|
| + Address js_sp_; // The top JS frame's sp when saving context.
|
| +};
|
| +
|
| +
|
| +class AssertNoContextChange BASE_EMBEDDED {
|
| +#ifdef DEBUG
|
| + public:
|
| + AssertNoContextChange() :
|
| + context_(Isolate::Current()->context()) {
|
| + }
|
| +
|
| + ~AssertNoContextChange() {
|
| + ASSERT(Isolate::Current()->context() == *context_);
|
| + }
|
| +
|
| + private:
|
| + HandleScope scope_;
|
| + Handle<Context> context_;
|
| +#else
|
| + public:
|
| + AssertNoContextChange() { }
|
| +#endif
|
| +};
|
| +
|
| +
|
| +class ExecutionAccess BASE_EMBEDDED {
|
| + public:
|
| + ExecutionAccess();
|
| + ~ExecutionAccess();
|
| +};
|
| +
|
| +
|
| // Support for checking for stack-overflows in C++ code.
|
| class StackLimitCheck BASE_EMBEDDED {
|
| public:
|
| @@ -336,7 +681,16 @@
|
| #define HEAP (v8::internal::Isolate::Current()->heap())
|
| #define ZONE (v8::internal::Isolate::Current()->zone())
|
|
|
| +// Tells whether the global context is marked with out of memory.
|
| +inline bool Context::has_out_of_memory() {
|
| + return global_context()->out_of_memory() == HEAP->true_value();
|
| +}
|
|
|
| +// Mark the global context with out of memory.
|
| +inline void Context::mark_out_of_memory() {
|
| + global_context()->set_out_of_memory(HEAP->true_value());
|
| +}
|
| +
|
| // Temporary macro to be used to flag definitions that are indeed static
|
| // and not per-isolate. (It would be great to be able to grep for [static]!)
|
| #define RLYSTC static
|
| @@ -353,4 +707,5 @@
|
|
|
| } } // namespace v8::internal
|
|
|
| +
|
| #endif // V8_ISOLATE_H_
|
|
|