summaryrefslogtreecommitdiff
path: root/deps/v8/src/debug/debug.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/debug/debug.cc')
-rw-r--r--deps/v8/src/debug/debug.cc94
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");
}