Revision: 23101
Author: [email protected]
Date: Wed Aug 13 11:14:35 2014 UTC
Log: Move Promise tracking from debug to isolate.
This prepares for tracking promise rejections when debugger is off.
[email protected]
Review URL: https://codereview.chromium.org/462413003
http://code.google.com/p/v8/source/detail?r=23101
Modified:
/branches/bleeding_edge/src/debug.cc
/branches/bleeding_edge/src/debug.h
/branches/bleeding_edge/src/isolate.cc
/branches/bleeding_edge/src/isolate.h
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/v8threads.cc
=======================================
--- /branches/bleeding_edge/src/debug.cc Mon Aug 11 07:59:10 2014 UTC
+++ /branches/bleeding_edge/src/debug.cc Wed Aug 13 11:14:35 2014 UTC
@@ -568,7 +568,6 @@
// TODO(isolates): frames_are_dropped_?
thread_local_.current_debug_scope_ = NULL;
thread_local_.restarter_frame_function_pointer_ = NULL;
- thread_local_.promise_on_stack_ = NULL;
}
@@ -855,9 +854,6 @@
ClearAllBreakPoints();
ClearStepping();
- // Match unmatched PopPromise calls.
- while (thread_local_.promise_on_stack_) PopPromise();
-
// Return debugger is not loaded.
if (!is_loaded()) return;
@@ -1270,57 +1266,6 @@
return break_on_exception_;
}
}
-
-
-PromiseOnStack::PromiseOnStack(Isolate* isolate, PromiseOnStack* prev,
- Handle<JSObject> promise)
- : isolate_(isolate), prev_(prev) {
- handler_ = StackHandler::FromAddress(
- Isolate::handler(isolate->thread_local_top()));
- promise_ =
- Handle<JSObject>::cast(isolate->global_handles()->Create(*promise));
-}
-
-
-PromiseOnStack::~PromiseOnStack() {
- isolate_->global_handles()->Destroy(
- Handle<Object>::cast(promise_).location());
-}
-
-
-void Debug::PushPromise(Handle<JSObject> promise) {
- PromiseOnStack* prev = thread_local_.promise_on_stack_;
- thread_local_.promise_on_stack_ = new PromiseOnStack(isolate_, prev,
promise);
-}
-
-
-void Debug::PopPromise() {
- if (thread_local_.promise_on_stack_ == NULL) return;
- PromiseOnStack* prev = thread_local_.promise_on_stack_->prev();
- delete thread_local_.promise_on_stack_;
- thread_local_.promise_on_stack_ = prev;
-}
-
-
-Handle<Object> Debug::GetPromiseOnStackOnThrow() {
- Handle<Object> undefined = isolate_->factory()->undefined_value();
- if (thread_local_.promise_on_stack_ == NULL) return undefined;
- StackHandler* promise_try = thread_local_.promise_on_stack_->handler();
- // Find the top-most try-catch handler.
- StackHandler* handler = StackHandler::FromAddress(
- Isolate::handler(isolate_->thread_local_top()));
- do {
- if (handler == promise_try) {
- // Mark the pushed try-catch handler to prevent a later duplicate
event
- // triggered with the following reject.
- return thread_local_.promise_on_stack_->promise();
- }
- handler = handler->next();
- // Throwing inside a Promise can be intercepted by an inner try-catch,
so
- // we stop at the first try-catch handler.
- } while (handler != NULL && !handler->is_catch());
- return undefined;
-}
bool Debug::PromiseHasRejectHandler(Handle<JSObject> promise) {
@@ -2567,7 +2512,7 @@
void Debug::OnThrow(Handle<Object> exception, bool uncaught) {
if (in_debug_scope() || ignore_events()) return;
HandleScope scope(isolate_);
- OnException(exception, uncaught, GetPromiseOnStackOnThrow());
+ OnException(exception, uncaught, isolate_->GetPromiseOnStackOnThrow());
}
=======================================
--- /branches/bleeding_edge/src/debug.h Wed Aug 6 09:41:52 2014 UTC
+++ /branches/bleeding_edge/src/debug.h Wed Aug 13 11:14:35 2014 UTC
@@ -333,22 +333,6 @@
};
-class PromiseOnStack {
- public:
- PromiseOnStack(Isolate* isolate, PromiseOnStack* prev,
- Handle<JSObject> getter);
- ~PromiseOnStack();
- StackHandler* handler() { return handler_; }
- Handle<JSObject> promise() { return promise_; }
- PromiseOnStack* prev() { return prev_; }
- private:
- Isolate* isolate_;
- StackHandler* handler_;
- Handle<JSObject> promise_;
- PromiseOnStack* prev_;
-};
-
-
// This class contains the debugger support. The main purpose is to handle
// setting break points in the code.
//
@@ -452,11 +436,6 @@
// Check whether this frame is just about to return.
bool IsBreakAtReturn(JavaScriptFrame* frame);
- // Promise handling.
- // Push and pop a promise and the current try-catch handler.
- void PushPromise(Handle<JSObject> promise);
- void PopPromise();
-
// Support for LiveEdit
void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
LiveEdit::FrameDropMode mode,
@@ -551,7 +530,6 @@
void ClearMirrorCache();
// Returns a promise if the pushed try-catch handler matches the current
one.
- Handle<Object> GetPromiseOnStackOnThrow();
bool PromiseHasRejectHandler(Handle<JSObject> promise);
void CallEventCallback(v8::DebugEvent event,
@@ -658,13 +636,6 @@
// of the pointer to function being restarted. Otherwise (most of the
time)
// stores NULL. This pointer is used with 'step in' implementation.
Object** restarter_frame_function_pointer_;
-
- // When a promise is being resolved, we may want to trigger a debug
event
- // if we catch a throw. For this purpose we remember the try-catch
- // handler address that would catch the exception. We also hold onto a
- // closure that returns a promise if the exception is considered
uncaught.
- // Due to the possibility of reentry we use a linked list.
- PromiseOnStack* promise_on_stack_;
};
// Storage location for registers when handling debug break calls
=======================================
--- /branches/bleeding_edge/src/isolate.cc Wed Aug 6 16:56:52 2014 UTC
+++ /branches/bleeding_edge/src/isolate.cc Wed Aug 13 11:14:35 2014 UTC
@@ -79,6 +79,7 @@
save_context_ = NULL;
catcher_ = NULL;
top_lookup_result_ = NULL;
+ promise_on_stack_ = NULL;
// These members are re-initialized later after deserialization
// is complete.
@@ -98,6 +99,12 @@
#endif
thread_id_ = ThreadId::Current();
}
+
+
+void ThreadLocalTop::Free() {
+ // Match unmatched PopPromise calls.
+ while (promise_on_stack_) isolate_->PopPromise();
+}
base::Thread::LocalStorageKey Isolate::isolate_key_;
@@ -1287,6 +1294,48 @@
clear_pending_exception();
return true;
}
+
+
+void Isolate::PushPromise(Handle<JSObject> promise) {
+ ThreadLocalTop* tltop = thread_local_top();
+ PromiseOnStack* prev = tltop->promise_on_stack_;
+ StackHandler* handler =
StackHandler::FromAddress(Isolate::handler(tltop));
+ Handle<JSObject> global_handle =
+ Handle<JSObject>::cast(global_handles()->Create(*promise));
+ tltop->promise_on_stack_ = new PromiseOnStack(handler, global_handle,
prev);
+}
+
+
+void Isolate::PopPromise() {
+ ThreadLocalTop* tltop = thread_local_top();
+ if (tltop->promise_on_stack_ == NULL) return;
+ PromiseOnStack* prev = tltop->promise_on_stack_->prev();
+ Handle<Object> global_handle = tltop->promise_on_stack_->promise();
+ delete tltop->promise_on_stack_;
+ tltop->promise_on_stack_ = prev;
+ global_handles()->Destroy(global_handle.location());
+}
+
+
+Handle<Object> Isolate::GetPromiseOnStackOnThrow() {
+ Handle<Object> undefined = factory()->undefined_value();
+ ThreadLocalTop* tltop = thread_local_top();
+ if (tltop->promise_on_stack_ == NULL) return undefined;
+ StackHandler* promise_try = tltop->promise_on_stack_->handler();
+ // Find the top-most try-catch handler.
+ StackHandler* handler =
StackHandler::FromAddress(Isolate::handler(tltop));
+ do {
+ if (handler == promise_try) {
+ // Mark the pushed try-catch handler to prevent a later duplicate
event
+ // triggered with the following reject.
+ return tltop->promise_on_stack_->promise();
+ }
+ handler = handler->next();
+ // Throwing inside a Promise can be intercepted by an inner try-catch,
so
+ // we stop at the first try-catch handler.
+ } while (handler != NULL && !handler->is_catch());
+ return undefined;
+}
void Isolate::SetCaptureStackTraceForUncaughtExceptions(
@@ -1552,6 +1601,8 @@
debug()->Unload();
+ FreeThreadResources();
+
if (concurrent_recompilation_enabled()) {
optimizing_compiler_thread_->Stop();
delete optimizing_compiler_thread_;
=======================================
--- /branches/bleeding_edge/src/isolate.h Wed Aug 6 16:56:52 2014 UTC
+++ /branches/bleeding_edge/src/isolate.h Wed Aug 13 11:14:35 2014 UTC
@@ -78,6 +78,7 @@
class Debug;
class Debugger;
+class PromiseOnStack;
#if !defined(__arm__) && V8_TARGET_ARCH_ARM || \
!defined(__aarch64__) && V8_TARGET_ARCH_ARM64 || \
@@ -240,11 +241,7 @@
v8::TryCatch::JSStackComparableAddress(try_catch_handler()));
}
- void Free() {
- DCHECK(!has_pending_message_);
- DCHECK(!external_caught_exception_);
- DCHECK(try_catch_handler_ == NULL);
- }
+ void Free();
Isolate* isolate_;
// The context where the current execution method is created and for
variable
@@ -270,6 +267,11 @@
Address c_entry_fp_; // the frame pointer of the top c entry frame
Address handler_; // try-blocks are chained through the stack
+ // Throwing an exception may cause a Promise rejection. For this purpose
+ // we keep track of a stack of nested promises and the corresponding
+ // try-catch handlers.
+ PromiseOnStack* promise_on_stack_;
+
#ifdef USE_SIMULATOR
Simulator* simulator_;
#endif
@@ -676,6 +678,11 @@
// JavaScript code. If an exception is scheduled true is returned.
bool OptionalRescheduleException(bool is_bottom_call);
+ // Push and pop a promise and the current try-catch handler.
+ void PushPromise(Handle<JSObject> promise);
+ void PopPromise();
+ Handle<Object> GetPromiseOnStackOnThrow();
+
class ExceptionScope {
public:
explicit ExceptionScope(Isolate* isolate) :
@@ -1349,6 +1356,22 @@
#undef THREAD_LOCAL_TOP_ACCESSOR
+class PromiseOnStack {
+ public:
+ PromiseOnStack(StackHandler* handler, Handle<JSObject> promise,
+ PromiseOnStack* prev)
+ : handler_(handler), promise_(promise), prev_(prev) {}
+ StackHandler* handler() { return handler_; }
+ Handle<JSObject> promise() { return promise_; }
+ PromiseOnStack* prev() { return prev_; }
+
+ private:
+ StackHandler* handler_;
+ Handle<JSObject> promise_;
+ PromiseOnStack* prev_;
+};
+
+
// 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.
=======================================
--- /branches/bleeding_edge/src/runtime.cc Tue Aug 12 15:28:20 2014 UTC
+++ /branches/bleeding_edge/src/runtime.cc Wed Aug 13 11:14:35 2014 UTC
@@ -5495,7 +5495,7 @@
DCHECK(args.length() == 1);
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
- isolate->debug()->PushPromise(promise);
+ isolate->PushPromise(promise);
return isolate->heap()->undefined_value();
}
@@ -5503,7 +5503,7 @@
RUNTIME_FUNCTION(Runtime_DebugPopPromise) {
DCHECK(args.length() == 0);
SealHandleScope shs(isolate);
- isolate->debug()->PopPromise();
+ isolate->PopPromise();
return isolate->heap()->undefined_value();
}
=======================================
--- /branches/bleeding_edge/src/v8threads.cc Mon Aug 4 11:34:54 2014 UTC
+++ /branches/bleeding_edge/src/v8threads.cc Wed Aug 13 11:14:35 2014 UTC
@@ -307,6 +307,9 @@
void ThreadManager::FreeThreadResources() {
+ DCHECK(!isolate_->has_pending_exception());
+ DCHECK(!isolate_->external_caught_exception());
+ DCHECK(isolate_->try_catch_handler() == NULL);
isolate_->handle_scope_implementer()->FreeThreadResources();
isolate_->FreeThreadResources();
isolate_->debug()->FreeThreadResources();
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.