diff options
Diffstat (limited to 'deps/v8/src/debug/debug.cc')
-rw-r--r-- | deps/v8/src/debug/debug.cc | 94 |
1 files changed, 69 insertions, 25 deletions
diff --git a/deps/v8/src/debug/debug.cc b/deps/v8/src/debug/debug.cc index 3a3a48b699..8a5a9b6eb0 100644 --- a/deps/v8/src/debug/debug.cc +++ b/deps/v8/src/debug/debug.cc @@ -29,6 +29,7 @@ #include "src/isolate-inl.h" #include "src/log.h" #include "src/messages.h" +#include "src/objects/api-callbacks-inl.h" #include "src/objects/debug-objects-inl.h" #include "src/objects/js-generator-inl.h" #include "src/objects/js-promise-inl.h" @@ -42,7 +43,7 @@ namespace internal { class Debug::TemporaryObjectsTracker : public HeapObjectAllocationTracker { public: TemporaryObjectsTracker() = default; - ~TemporaryObjectsTracker() = default; + ~TemporaryObjectsTracker() override = default; void AllocationEvent(Address addr, int) override { objects_.insert(addr); } @@ -417,9 +418,6 @@ void Debug::Break(JavaScriptFrame* frame, Handle<JSFunction> break_target) { // Enter the debugger. DebugScope debug_scope(this); - - // Postpone interrupt during breakpoint processing. - PostponeInterruptsScope postpone(isolate_); DisableBreak no_recursive_break(this); // Return if we fail to retrieve debug info. @@ -1142,7 +1140,7 @@ class RedirectActiveFunctions : public ThreadVisitor { DCHECK(shared->HasBytecodeArray()); } - void VisitThread(Isolate* isolate, ThreadLocalTop* top) { + void VisitThread(Isolate* isolate, ThreadLocalTop* top) override { for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { JavaScriptFrame* frame = it.frame(); JSFunction* function = frame->function(); @@ -1165,9 +1163,9 @@ void Debug::DeoptimizeFunction(Handle<SharedFunctionInfo> shared) { // inlining. isolate_->AbortConcurrentOptimization(BlockingBehavior::kBlock); - // Make sure we abort incremental marking. - isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask, - GarbageCollectionReason::kDebugger); + // TODO(mlippautz): Try to remove this call. + isolate_->heap()->PreciseCollectAllGarbage( + Heap::kNoGCFlags, GarbageCollectionReason::kDebugger); bool found_something = false; Code::OptimizedCodeIterator iterator(isolate_); @@ -1542,7 +1540,7 @@ void Debug::FindDebugInfo(Handle<DebugInfo> debug_info, UNREACHABLE(); } -void Debug::ClearAllDebugInfos(DebugInfoClearFunction clear_function) { +void Debug::ClearAllDebugInfos(const DebugInfoClearFunction& clear_function) { DebugInfoListNode* prev = nullptr; DebugInfoListNode* current = debug_info_list_; while (current != nullptr) { @@ -1625,7 +1623,7 @@ void Debug::ScheduleFrameRestart(StackFrame* frame) { } Handle<FixedArray> Debug::GetLoadedScripts() { - isolate_->heap()->CollectAllGarbage(Heap::kFinalizeIncrementalMarkingMask, + isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, GarbageCollectionReason::kDebugger); Factory* factory = isolate_->factory(); if (!factory->script_list()->IsWeakArrayList()) { @@ -1655,7 +1653,10 @@ void Debug::OnThrow(Handle<Object> exception) { scheduled_exception = handle(isolate_->scheduled_exception(), isolate_); isolate_->clear_scheduled_exception(); } - OnException(exception, isolate_->GetPromiseOnStackOnThrow()); + Handle<Object> maybe_promise = isolate_->GetPromiseOnStackOnThrow(); + OnException(exception, maybe_promise, + maybe_promise->IsJSPromise() ? v8::debug::kPromiseRejection + : v8::debug::kException); if (!scheduled_exception.is_null()) { isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception; } @@ -1670,7 +1671,7 @@ void Debug::OnPromiseReject(Handle<Object> promise, Handle<Object> value) { if (!promise->IsJSObject() || JSReceiver::GetDataProperty(Handle<JSObject>::cast(promise), key) ->IsUndefined(isolate_)) { - OnException(value, promise); + OnException(value, promise, v8::debug::kPromiseRejection); } } @@ -1695,7 +1696,8 @@ bool Debug::IsFrameBlackboxed(JavaScriptFrame* frame) { return true; } -void Debug::OnException(Handle<Object> exception, Handle<Object> promise) { +void Debug::OnException(Handle<Object> exception, Handle<Object> promise, + v8::debug::ExceptionType exception_type) { // TODO(kozyatinskiy): regress-662674.js test fails on arm without this. if (!AllowJavascriptExecution::IsAllowed(isolate_)) return; @@ -1741,9 +1743,9 @@ void Debug::OnException(Handle<Object> exception, Handle<Object> promise) { DisableBreak no_recursive_break(this); Handle<Context> native_context(isolate_->native_context()); - debug_delegate_->ExceptionThrown(v8::Utils::ToLocal(native_context), - v8::Utils::ToLocal(exception), - v8::Utils::ToLocal(promise), uncaught); + debug_delegate_->ExceptionThrown( + v8::Utils::ToLocal(native_context), v8::Utils::ToLocal(exception), + v8::Utils::ToLocal(promise), uncaught, exception_type); } void Debug::OnDebugBreak(Handle<FixedArray> break_points_hit) { @@ -1758,8 +1760,8 @@ void Debug::OnDebugBreak(Handle<FixedArray> break_points_hit) { #endif // DEBUG if (!debug_delegate_) return; + DCHECK(in_debug_scope()); HandleScope scope(isolate_); - PostponeInterruptsScope no_interrupts(isolate_); DisableBreak no_recursive_break(this); std::vector<int> inspector_break_points_hit; @@ -2182,16 +2184,55 @@ Handle<Object> Debug::return_value_handle() { return handle(thread_local_.return_value_, isolate_); } -bool Debug::PerformSideEffectCheckForCallback(Handle<Object> callback_info) { +bool Debug::PerformSideEffectCheckForCallback( + Handle<Object> callback_info, Handle<Object> receiver, + Debug::AccessorKind accessor_kind) { + DCHECK_EQ(!receiver.is_null(), callback_info->IsAccessorInfo()); DCHECK_EQ(isolate_->debug_execution_mode(), DebugInfo::kSideEffects); if (!callback_info.is_null() && callback_info->IsCallHandlerInfo() && i::CallHandlerInfo::cast(*callback_info)->NextCallHasNoSideEffect()) { return true; } // TODO(7515): always pass a valid callback info object. - if (!callback_info.is_null() && - DebugEvaluate::CallbackHasNoSideEffect(*callback_info)) { - return true; + if (!callback_info.is_null()) { + if (callback_info->IsAccessorInfo()) { + // List of whitelisted internal accessors can be found in accessors.h. + AccessorInfo* info = AccessorInfo::cast(*callback_info); + DCHECK_NE(kNotAccessor, accessor_kind); + switch (accessor_kind == kSetter ? info->setter_side_effect_type() + : info->getter_side_effect_type()) { + case SideEffectType::kHasNoSideEffect: + // We do not support setter accessors with no side effects, since + // calling set accessors go through a store bytecode. Store bytecodes + // are considered to cause side effects (to non-temporary objects). + DCHECK_NE(kSetter, accessor_kind); + return true; + case SideEffectType::kHasSideEffectToReceiver: + DCHECK(!receiver.is_null()); + if (PerformSideEffectCheckForObject(receiver)) return true; + isolate_->OptionalRescheduleException(false); + return false; + case SideEffectType::kHasSideEffect: + break; + } + if (FLAG_trace_side_effect_free_debug_evaluate) { + PrintF("[debug-evaluate] API Callback '"); + info->name()->ShortPrint(); + PrintF("' may cause side effect.\n"); + } + } else if (callback_info->IsInterceptorInfo()) { + InterceptorInfo* info = InterceptorInfo::cast(*callback_info); + if (info->has_no_side_effect()) return true; + if (FLAG_trace_side_effect_free_debug_evaluate) { + PrintF("[debug-evaluate] API Interceptor may cause side effect.\n"); + } + } else if (callback_info->IsCallHandlerInfo()) { + CallHandlerInfo* info = CallHandlerInfo::cast(*callback_info); + if (info->IsSideEffectFreeCallHandlerInfo()) return true; + if (FLAG_trace_side_effect_free_debug_evaluate) { + PrintF("[debug-evaluate] API CallHandlerInfo may cause side effect.\n"); + } + } } side_effect_check_failed_ = true; // Throw an uncatchable termination exception. @@ -2228,11 +2269,14 @@ bool Debug::PerformSideEffectCheckAtBytecode(InterpretedFrame* frame) { bool Debug::PerformSideEffectCheckForObject(Handle<Object> object) { DCHECK_EQ(isolate_->debug_execution_mode(), DebugInfo::kSideEffects); - if (object->IsHeapObject()) { - if (temporary_objects_->HasObject(Handle<HeapObject>::cast(object))) { - return true; - } + // We expect no side-effects for primitives. + if (object->IsNumber()) return true; + if (object->IsName()) return true; + + if (temporary_objects_->HasObject(Handle<HeapObject>::cast(object))) { + return true; } + if (FLAG_trace_side_effect_free_debug_evaluate) { PrintF("[debug-evaluate] failed runtime side effect check.\n"); } |