Chromium Code Reviews| Index: src/debug/debug-interface.cc |
| diff --git a/src/debug/debug-interface.cc b/src/debug/debug-interface.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..f83026378aae962bba033c9b642e0a597d7ef1ca |
| --- /dev/null |
| +++ b/src/debug/debug-interface.cc |
| @@ -0,0 +1,149 @@ |
| +// Copyright 2016 the V8 project authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "src/debug/debug-interface.h" |
| + |
| +#include "src/debug/debug.h" |
| +#include "src/factory.h" |
| +#include "src/isolate-inl.h" |
| +#include "src/vm-state-inl.h" |
| + |
| +namespace v8 { |
| + |
| +namespace i = internal; |
| + |
| +static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) { |
| + if (isolate->has_scheduled_exception()) { |
| + return isolate->scheduled_exception() == |
| + isolate->heap()->termination_exception(); |
| + } |
| + return false; |
| +} |
| + |
| +#define ENTER_V8(isolate) i::VMState<v8::OTHER> __state__((isolate)) |
| + |
| +namespace { |
| + |
| +class InternalEscapableScope : public v8::EscapableHandleScope { |
| + public: |
| + explicit inline InternalEscapableScope(i::Isolate* isolate) |
| + : v8::EscapableHandleScope(reinterpret_cast<v8::Isolate*>(isolate)) {} |
| +}; |
| + |
| +class CallDepthScope { |
|
Yang
2016/10/17 09:53:25
This and some other parts are duplicates of what's
kozy
2016/10/17 14:38:06
Done.
|
| + public: |
| + explicit CallDepthScope(i::Isolate* isolate, Local<Context> context) |
| + : isolate_(isolate), context_(context), escaped_(false) { |
| + // TODO(dcarney): remove this when blink stops crashing. |
| + DCHECK(!isolate_->external_caught_exception()); |
| + isolate_->IncrementJsCallsFromApiCounter(); |
| + isolate_->handle_scope_implementer()->IncrementCallDepth(); |
| + if (!context.IsEmpty()) { |
| + i::Handle<i::Context> env = Utils::OpenHandle(*context); |
| + i::HandleScopeImplementer* impl = isolate->handle_scope_implementer(); |
| + if (isolate->context() != nullptr && |
| + isolate->context()->native_context() == env->native_context() && |
| + impl->LastEnteredContextWas(env)) { |
| + context_ = Local<Context>(); |
| + } else { |
| + context_->Enter(); |
| + } |
| + } |
| + } |
| + ~CallDepthScope() { |
| + if (!context_.IsEmpty()) context_->Exit(); |
| + if (!escaped_) isolate_->handle_scope_implementer()->DecrementCallDepth(); |
| + } |
| + |
| + void Escape() { |
| + DCHECK(!escaped_); |
| + escaped_ = true; |
| + auto handle_scope_implementer = isolate_->handle_scope_implementer(); |
| + handle_scope_implementer->DecrementCallDepth(); |
| + bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero(); |
| + isolate_->OptionalRescheduleException(call_depth_is_zero); |
| + } |
| + |
| + private: |
| + i::Isolate* const isolate_; |
| + Local<Context> context_; |
| + bool escaped_; |
| +}; |
| + |
| +} // namespace |
| + |
| +bool DebugInterface::SetDebugEventListener(Isolate* isolate, EventCallback that, |
| + Local<Value> data) { |
| + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| + ENTER_V8(i_isolate); |
| + i::HandleScope scope(i_isolate); |
| + i::Handle<i::Object> foreign = i_isolate->factory()->undefined_value(); |
| + if (that != NULL) { |
| + foreign = i_isolate->factory()->NewForeign(FUNCTION_ADDR(that)); |
| + } |
| + i_isolate->debug()->SetEventListener(foreign, Utils::OpenHandle(*data, true)); |
| + return true; |
| +} |
| + |
| +Local<Context> DebugInterface::GetDebugContext(Isolate* isolate) { |
| + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| + ENTER_V8(i_isolate); |
| + return Utils::ToLocal(i_isolate->debug()->GetDebugContext()); |
| +} |
| + |
| +MaybeLocal<Value> DebugInterface::Call(Local<Context> context, |
| + v8::Local<v8::Function> fun, |
| + v8::Local<v8::Value> data) { |
| + auto isolate = context.IsEmpty() |
| + ? i::Isolate::Current() |
| + : reinterpret_cast<i::Isolate*>(context->GetIsolate()); |
| + if (IsExecutionTerminatingCheck(isolate)) { |
| + return MaybeLocal<Value>(); |
| + } |
| + InternalEscapableScope handle_scope(isolate); |
| + CallDepthScope call_depth_scope(isolate, context); |
| + ENTER_V8(isolate); |
| + bool has_pending_exception = false; |
| + i::Handle<i::Object> data_obj; |
| + if (data.IsEmpty()) { |
| + data_obj = isolate->factory()->undefined_value(); |
| + } else { |
| + data_obj = Utils::OpenHandle(*data); |
| + } |
| + Local<Value> result; |
| + has_pending_exception = !ToLocal<Value>( |
| + isolate->debug()->Call(Utils::OpenHandle(*fun), data_obj), &result); |
| + if (has_pending_exception) { |
| + call_depth_scope.Escape(); |
| + return result; |
| + } |
| + return handle_scope.Escape(result); |
| +} |
| + |
| +void DebugInterface::SetLiveEditEnabled(Isolate* isolate, bool enable) { |
| + i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| + internal_isolate->debug()->set_live_edit_enabled(enable); |
| +} |
| + |
| +void DebugInterface::DebugBreak(Isolate* isolate) { |
| + reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->RequestDebugBreak(); |
| +} |
| + |
| +void DebugInterface::CancelDebugBreak(Isolate* isolate) { |
| + i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| + internal_isolate->stack_guard()->ClearDebugBreak(); |
| +} |
| + |
| +MaybeLocal<Array> DebugInterface::GetInternalProperties(Isolate* v8_isolate, |
| + Local<Value> value) { |
| + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); |
| + ENTER_V8(isolate); |
| + i::Handle<i::Object> val = Utils::OpenHandle(*value); |
| + i::Handle<i::JSArray> result; |
| + if (!i::Runtime::GetInternalProperties(isolate, val).ToHandle(&result)) |
| + return MaybeLocal<Array>(); |
| + return Utils::ToLocal(result); |
| +} |
| + |
| +} // namespace v8 |