Chromium Code Reviews| Index: src/api.cc |
| diff --git a/src/api.cc b/src/api.cc |
| index caa7d002f5fa43b2b4c3649febafbe64db704394..8f92929c959d826e35414fb81880d98c76a2ec03 100644 |
| --- a/src/api.cc |
| +++ b/src/api.cc |
| @@ -75,17 +75,18 @@ namespace v8 { |
| #define ENTER_V8(isolate) i::VMState<v8::OTHER> __state__((isolate)) |
| -#define PREPARE_FOR_EXECUTION_GENERIC(isolate, context, function_name, \ |
| - bailout_value, HandleScopeClass, \ |
| - do_callback) \ |
| - if (IsExecutionTerminatingCheck(isolate)) { \ |
| - return bailout_value; \ |
| - } \ |
| - TRACE_EVENT_SCOPED_CONTEXT("v8", "Isolate", isolate); \ |
| - HandleScopeClass handle_scope(isolate); \ |
| - CallDepthScope call_depth_scope(isolate, context, do_callback); \ |
| - LOG_API(isolate, function_name); \ |
| - ENTER_V8(isolate); \ |
| +#define PREPARE_FOR_EXECUTION_GENERIC(isolate, context, function_name, \ |
| + bailout_value, HandleScopeClass, \ |
| + do_callback) \ |
| + if (IsExecutionTerminatingCheck(isolate)) { \ |
| + return bailout_value; \ |
| + } \ |
| + TRACE_EVENT_SCOPED_CONTEXT("v8", "Isolate", isolate); \ |
| + HandleScopeClass handle_scope(isolate); \ |
| + isolate->IncrementJsCallsFromApiCounter(); \ |
| + CallDepthScope call_depth_scope(isolate, context, do_callback, false);\ |
| + LOG_API(isolate, function_name); \ |
| + ENTER_V8(isolate); \ |
| bool has_pending_exception = false |
| @@ -157,41 +158,92 @@ class InternalEscapableScope : public v8::EscapableHandleScope { |
| }; |
| +inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) { |
| + if (isolate->has_scheduled_exception()) { |
| + return isolate->scheduled_exception() == |
| + isolate->heap()->termination_exception(); |
| + } |
| + return false; |
| +} |
| + |
| + |
| class CallDepthScope { |
| public: |
| - explicit CallDepthScope(i::Isolate* isolate, Local<Context> context, |
| - bool do_callback) |
| + CallDepthScope(i::Isolate* isolate, |
| + Local<Context> context, |
| + bool do_callback_and_microtasks, |
| + bool is_external) |
| : isolate_(isolate), |
| context_(context), |
| - escaped_(false), |
| - do_callback_(do_callback) { |
| - // TODO(dcarney): remove this when blink stops crashing. |
| - DCHECK(!isolate_->external_caught_exception()); |
| - isolate_->IncrementJsCallsFromApiCounter(); |
| - isolate_->handle_scope_implementer()->IncrementCallDepth(); |
| + handle_exception_(!is_external), |
| + do_callback_(do_callback_and_microtasks && !is_external) { |
| + bool affects_microtasks = is_external || |
| + isolate_->handle_scope_implementer()->microtasks_policy() == |
| + i::kAutoMicrotasksInvocation; |
| + run_microtasks_ = affects_microtasks && do_callback_and_microtasks; |
| +#ifdef V8_ENABLE_CHECKS |
| + debug_microtasks_ = affects_microtasks && !do_callback_and_microtasks; |
| +#endif |
| + auto handle_scope_implementer = isolate_->handle_scope_implementer(); |
| + if (handle_exception_) { |
| + // TODO(dcarney): remove this when blink stops crashing. |
| + DCHECK(!isolate_->external_caught_exception()); |
| + handle_scope_implementer->IncrementInternalCallDepth(); |
| + } |
| + if (run_microtasks_) handle_scope_implementer->IncrementCallDepth(); |
| +#ifdef V8_ENABLE_CHECKS |
| + if (debug_microtasks_) handle_scope_implementer->IncrementDebugCallDepth(); |
| +#endif |
| if (!context_.IsEmpty()) context_->Enter(); |
| if (do_callback_) isolate_->FireBeforeCallEnteredCallback(); |
| } |
| + |
| ~CallDepthScope() { |
| if (!context_.IsEmpty()) context_->Exit(); |
| - if (!escaped_) isolate_->handle_scope_implementer()->DecrementCallDepth(); |
| + auto handle_scope_implementer = isolate_->handle_scope_implementer(); |
| + if (handle_exception_) |
| + handle_scope_implementer->DecrementInternalCallDepth(); |
| if (do_callback_) isolate_->FireCallCompletedCallback(); |
| +#ifdef V8_ENABLE_CHECKS |
| + bool scoped_policy = handle_scope_implementer->microtasks_policy() == |
| + i::kScopedMicrotasksInvocation; |
| + DCHECK(!(scoped_policy && do_callback_ |
| + && !handle_scope_implementer->GetCallDepth() |
| + && !handle_scope_implementer->GetDebugCallDepth())); |
| +#endif |
| + if (run_microtasks_) { |
| + handle_scope_implementer->DecrementCallDepth(); |
| + PerformCheckpoint(isolate_); |
| + } |
| +#ifdef V8_ENABLE_CHECKS |
| + if (debug_microtasks_) handle_scope_implementer->DecrementDebugCallDepth(); |
| +#endif |
| } |
| void Escape() { |
| - DCHECK(!escaped_); |
| - escaped_ = true; |
| + DCHECK(handle_exception_); |
| + handle_exception_ = false; |
| auto handle_scope_implementer = isolate_->handle_scope_implementer(); |
| - handle_scope_implementer->DecrementCallDepth(); |
| - bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero(); |
| + handle_scope_implementer->DecrementInternalCallDepth(); |
| + bool call_depth_is_zero = !handle_scope_implementer->GetInternalCallDepth(); |
| isolate_->OptionalRescheduleException(call_depth_is_zero); |
| } |
| + static void PerformCheckpoint(i::Isolate* isolate) { |
| + if (IsExecutionTerminatingCheck(isolate)) return; |
| + if (!isolate->handle_scope_implementer()->GetCallDepth() && |
| + !isolate->handle_scope_implementer()->GetMicrotasksSuppression()) { |
| + isolate->RunMicrotasks(); |
| + } |
| + } |
| + |
| private: |
| i::Isolate* const isolate_; |
| Local<Context> context_; |
| - bool escaped_; |
| + bool handle_exception_; |
| bool do_callback_; |
| + bool run_microtasks_; |
| + bool debug_microtasks_; |
| }; |
| } // namespace |
| @@ -310,15 +362,6 @@ void Utils::ReportApiFailure(const char* location, const char* message) { |
| } |
| -static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) { |
| - if (isolate->has_scheduled_exception()) { |
| - return isolate->scheduled_exception() == |
| - isolate->heap()->termination_exception(); |
| - } |
| - return false; |
| -} |
| - |
| - |
| void V8::SetNativesDataBlob(StartupData* natives_blob) { |
| i::V8::SetNativesBlob(natives_blob); |
| } |
| @@ -7290,12 +7333,12 @@ Isolate::AllowJavascriptExecutionScope::~AllowJavascriptExecutionScope() { |
| Isolate::SuppressMicrotaskExecutionScope::SuppressMicrotaskExecutionScope( |
| Isolate* isolate) |
| : isolate_(reinterpret_cast<i::Isolate*>(isolate)) { |
| - isolate_->handle_scope_implementer()->IncrementCallDepth(); |
| + isolate_->handle_scope_implementer()->IncrementMicrotasksSuppression(); |
| } |
| Isolate::SuppressMicrotaskExecutionScope::~SuppressMicrotaskExecutionScope() { |
| - isolate_->handle_scope_implementer()->DecrementCallDepth(); |
| + isolate_->handle_scope_implementer()->DecrementMicrotasksSuppression(); |
| } |
| @@ -7436,6 +7479,7 @@ void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) { |
| void Isolate::RunMicrotasks() { |
| + DCHECK_EQ(Isolate::kExplicitMicrotasksInvocation, GetMicrotasksPolicy()); |
| reinterpret_cast<i::Isolate*>(this)->RunMicrotasks(); |
| } |
| @@ -7459,12 +7503,25 @@ void Isolate::EnqueueMicrotask(MicrotaskCallback microtask, void* data) { |
| void Isolate::SetAutorunMicrotasks(bool autorun) { |
| - reinterpret_cast<i::Isolate*>(this)->set_autorun_microtasks(autorun); |
| + SetMicrotasksPolicy(kAutoMicrotasksInvocation); |
| } |
| bool Isolate::WillAutorunMicrotasks() const { |
| - return reinterpret_cast<const i::Isolate*>(this)->autorun_microtasks(); |
| + return GetMicrotasksPolicy() == kAutoMicrotasksInvocation; |
| +} |
| + |
| + |
| +void Isolate::SetMicrotasksPolicy(MicrotasksPolicy policy) { |
| + reinterpret_cast<i::Isolate*>(this)->handle_scope_implementer()-> |
| + set_microtasks_policy(static_cast<i::MicrotasksPolicy>(policy)); |
| +} |
| + |
| + |
| +Isolate::MicrotasksPolicy Isolate::GetMicrotasksPolicy() const { |
| + return static_cast<MicrotasksPolicy>( |
| + reinterpret_cast<i::Isolate*>(const_cast<Isolate*>(this))-> |
| + handle_scope_implementer()->microtasks_policy()); |
| } |
| @@ -7703,6 +7760,33 @@ void Isolate::VisitWeakHandles(PersistentHandleVisitor* visitor) { |
| } |
| +MicrotasksScope::MicrotasksScope(Isolate* isolate, MicrotasksScope::Type type) { |
| + DCHECK_EQ(Isolate::kScopedMicrotasksInvocation, |
| + isolate->GetMicrotasksPolicy()); |
| + internal_ = reinterpret_cast<void*>(new CallDepthScope( |
|
adamk
2016/03/01 19:10:34
I'm a little bit worried about the added heap allo
dgozman
2016/03/03 01:22:06
I think this patch would be easier to understand w
|
| + reinterpret_cast<i::Isolate*>(isolate), |
| + Local<Context>(), |
| + type == MicrotasksScope::kRunMicrotasks, |
| + true)); |
| +} |
| + |
| + |
| +MicrotasksScope::~MicrotasksScope() { |
| + delete reinterpret_cast<CallDepthScope*>(internal_); |
| +} |
| + |
| + |
| +void MicrotasksScope::PerformCheckpoint(Isolate* isolate) { |
| + CallDepthScope::PerformCheckpoint(reinterpret_cast<i::Isolate*>(isolate)); |
| +} |
| + |
| + |
| +int MicrotasksScope::GetRecursionLevel(Isolate* isolate) { |
| + return reinterpret_cast<i::Isolate*>(isolate)->handle_scope_implementer()-> |
| + GetCallDepth(); |
| +} |
| + |
| + |
| String::Utf8Value::Utf8Value(v8::Local<v8::Value> obj) |
| : str_(NULL), length_(0) { |
| if (obj.IsEmpty()) return; |