Merge V8 at r7668: Initial merge by Git.
Change-Id: I1703c8b4f5c63052451a22cf3fb878abc9a0ec75
diff --git a/src/isolate.h b/src/isolate.h
index 03a4866..35ffcb4 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -72,7 +72,7 @@
class ProducerHeapProfile;
class RegExpStack;
class SaveContext;
-class ScannerConstants;
+class UnicodeCache;
class StringInputBuffer;
class StringTracker;
class StubCache;
@@ -136,8 +136,59 @@
#endif
+// Platform-independent, reliable thread identifier.
+class ThreadId {
+ public:
+ // Creates an invalid ThreadId.
+ ThreadId() : id_(kInvalidId) {}
+
+ // Returns ThreadId for current thread.
+ static ThreadId Current() { return ThreadId(GetCurrentThreadId()); }
+
+ // Returns invalid ThreadId (guaranteed not to be equal to any thread).
+ static ThreadId Invalid() { return ThreadId(kInvalidId); }
+
+ // Compares ThreadIds for equality.
+ INLINE(bool Equals(const ThreadId& other) const) {
+ return id_ == other.id_;
+ }
+
+ // Checks whether this ThreadId refers to any thread.
+ INLINE(bool IsValid() const) {
+ return id_ != kInvalidId;
+ }
+
+ // Converts ThreadId to an integer representation
+ // (required for public API: V8::V8::GetCurrentThreadId).
+ int ToInteger() const { return id_; }
+
+ // Converts ThreadId to an integer representation
+ // (required for public API: V8::V8::TerminateExecution).
+ static ThreadId FromInteger(int id) { return ThreadId(id); }
+
+ private:
+ static const int kInvalidId = -1;
+
+ explicit ThreadId(int id) : id_(id) {}
+
+ static int AllocateThreadId();
+
+ static int GetCurrentThreadId();
+
+ int id_;
+
+ static Atomic32 highest_thread_id_;
+
+ friend class Isolate;
+};
+
+
class ThreadLocalTop BASE_EMBEDDED {
public:
+ // Does early low-level initialization that does not depend on the
+ // isolate being present.
+ ThreadLocalTop();
+
// Initialize the thread data.
void Initialize();
@@ -176,10 +227,9 @@
// The context where the current execution method is created and for variable
// lookups.
Context* context_;
- int thread_id_;
+ ThreadId thread_id_;
MaybeObject* pending_exception_;
bool has_pending_message_;
- const char* pending_message_;
Object* pending_message_obj_;
Script* pending_message_script_;
int pending_message_start_pos_;
@@ -218,6 +268,8 @@
v8::FailedAccessCheckCallback failed_access_check_callback_;
private:
+ void InitializeInternal();
+
Address try_catch_handler_address_;
};
@@ -242,6 +294,7 @@
#ifdef ENABLE_DEBUGGER_SUPPORT
#define ISOLATE_DEBUGGER_INIT_LIST(V) \
+ V(uint64_t, enabled_cpu_features, 0) \
V(v8::Debug::EventCallback, debug_event_callback, NULL) \
V(DebuggerAgent*, debugger_agent_instance, NULL)
#else
@@ -315,6 +368,8 @@
/* AstNode state. */ \
V(unsigned, ast_node_id, 0) \
V(unsigned, ast_node_count, 0) \
+ /* SafeStackFrameIterator activations count. */ \
+ V(int, safe_stack_iterator_counter, 0) \
ISOLATE_PLATFORM_INIT_LIST(V) \
ISOLATE_LOGGING_INIT_LIST(V) \
ISOLATE_DEBUGGER_INIT_LIST(V)
@@ -327,8 +382,6 @@
public:
~Isolate();
- typedef int ThreadId;
-
// A thread has a PerIsolateThreadData instance for each isolate that it has
// entered. That instance is allocated when the isolate is initially entered
// and reused on subsequent entries.
@@ -361,7 +414,7 @@
#endif
bool Matches(Isolate* isolate, ThreadId thread_id) const {
- return isolate_ == isolate && thread_id_ == thread_id;
+ return isolate_ == isolate && thread_id_.Equals(thread_id);
}
private:
@@ -453,9 +506,6 @@
return thread_id_key_;
}
- // Atomically allocates a new thread ID.
- static ThreadId AllocateThreadId();
-
// If a client attempts to create a Locker without specifying an isolate,
// we assume that the client is using legacy behavior. Set up the current
// thread to be inside the implicit isolate (or fail a check if we have
@@ -481,8 +531,8 @@
}
// 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; }
+ ThreadId thread_id() { return thread_local_top_.thread_id_; }
+ void set_thread_id(ThreadId id) { thread_local_top_.thread_id_ = id; }
// Interface to pending exception.
MaybeObject* pending_exception() {
@@ -492,6 +542,9 @@
bool external_caught_exception() {
return thread_local_top_.external_caught_exception_;
}
+ void set_external_caught_exception(bool value) {
+ thread_local_top_.external_caught_exception_ = value;
+ }
void set_pending_exception(MaybeObject* exception) {
thread_local_top_.pending_exception_ = exception;
}
@@ -506,7 +559,6 @@
}
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;
}
@@ -519,6 +571,12 @@
bool* external_caught_exception_address() {
return &thread_local_top_.external_caught_exception_;
}
+ v8::TryCatch* catcher() {
+ return thread_local_top_.catcher_;
+ }
+ void set_catcher(v8::TryCatch* catcher) {
+ thread_local_top_.catcher_ = catcher;
+ }
MaybeObject** scheduled_exception_address() {
return &thread_local_top_.scheduled_exception_;
@@ -589,6 +647,27 @@
// JavaScript code. If an exception is scheduled true is returned.
bool OptionalRescheduleException(bool is_bottom_call);
+ class ExceptionScope {
+ public:
+ explicit ExceptionScope(Isolate* isolate) :
+ // Scope currently can only be used for regular exceptions, not
+ // failures like OOM or termination exception.
+ isolate_(isolate),
+ pending_exception_(isolate_->pending_exception()->ToObjectUnchecked()),
+ catcher_(isolate_->catcher())
+ { }
+
+ ~ExceptionScope() {
+ isolate_->set_catcher(catcher_);
+ isolate_->set_pending_exception(*pending_exception_);
+ }
+
+ private:
+ Isolate* isolate_;
+ Handle<Object> pending_exception_;
+ v8::TryCatch* catcher_;
+ };
+
void SetCaptureStackTraceForUncaughtExceptions(
bool capture,
int frame_limit,
@@ -633,9 +712,7 @@
// Promote a scheduled exception to pending. Asserts has_scheduled_exception.
Failure* PromoteScheduledException();
- void DoThrow(MaybeObject* exception,
- MessageLocation* location,
- const char* message);
+ void DoThrow(MaybeObject* exception, MessageLocation* location);
// Checks if exception should be reported and finds out if it's
// caught externally.
bool ShouldReportException(bool* can_be_caught_externally,
@@ -708,10 +785,6 @@
Bootstrapper* bootstrapper() { return bootstrapper_; }
Counters* counters() { return counters_; }
- // TODO(isolates): Having CPU features per isolate is probably too
- // flexible. We only really need to have the set of currently
- // enabled features for asserts in DEBUG builds.
- CpuFeatures* cpu_features() { return cpu_features_; }
CodeRange* code_range() { return code_range_; }
RuntimeProfiler* runtime_profiler() { return runtime_profiler_; }
CompilationCache* compilation_cache() { return compilation_cache_; }
@@ -752,8 +825,8 @@
}
Zone* zone() { return &zone_; }
- ScannerConstants* scanner_constants() {
- return scanner_constants_;
+ UnicodeCache* unicode_cache() {
+ return unicode_cache_;
}
PcToCodeCache* pc_to_code_cache() { return pc_to_code_cache_; }
@@ -898,13 +971,19 @@
void SetCurrentVMState(StateTag state) {
if (RuntimeProfiler::IsEnabled()) {
- if (state == JS) {
- // JS or non-JS -> JS transition.
+ StateTag current_state = thread_local_top_.current_vm_state_;
+ if (current_state != JS && state == JS) {
+ // Non-JS -> JS transition.
RuntimeProfiler::IsolateEnteredJS(this);
- } else if (thread_local_top_.current_vm_state_ == JS) {
+ } else if (current_state == JS && state != JS) {
// JS -> non-JS transition.
ASSERT(RuntimeProfiler::IsSomeIsolateInJS());
RuntimeProfiler::IsolateExitedJS(this);
+ } else {
+ // Other types of state transitions are not interesting to the
+ // runtime profiler, because they don't affect whether we're
+ // in JS or not.
+ ASSERT((current_state == JS) == (state == JS));
}
}
thread_local_top_.current_vm_state_ = state;
@@ -965,7 +1044,6 @@
static Thread::LocalStorageKey thread_id_key_;
static Isolate* default_isolate_;
static ThreadDataTable* thread_data_table_;
- static ThreadId highest_thread_id_;
bool PreInit();
@@ -1018,6 +1096,8 @@
void FillCache();
+ void PropagatePendingExceptionToExternalTryCatch();
+
int stack_trace_nesting_level_;
StringStream* incomplete_message_;
// The preallocated memory thread singleton.
@@ -1029,7 +1109,6 @@
RuntimeProfiler* runtime_profiler_;
CompilationCache* compilation_cache_;
Counters* counters_;
- CpuFeatures* cpu_features_;
CodeRange* code_range_;
Mutex* break_access_;
Heap heap_;
@@ -1049,7 +1128,7 @@
DescriptorLookupCache* descriptor_lookup_cache_;
v8::ImplementationUtilities::HandleScopeData handle_scope_data_;
HandleScopeImplementer* handle_scope_implementer_;
- ScannerConstants* scanner_constants_;
+ UnicodeCache* unicode_cache_;
Zone zone_;
PreallocatedStorage in_use_list_;
PreallocatedStorage free_list_;
@@ -1124,6 +1203,7 @@
friend class ExecutionAccess;
friend class IsolateInitializer;
+ friend class ThreadId;
friend class v8::Isolate;
friend class v8::Locker;
@@ -1146,7 +1226,7 @@
isolate->set_save_context(this);
// If there is no JS frame under the current C frame, use the value 0.
- JavaScriptFrameIterator it;
+ JavaScriptFrameIterator it(isolate);
js_sp_ = it.done() ? 0 : it.frame()->sp();
}