Some more debugger-related refactorings.

R=ulan@chromium.org

Review URL: https://codereview.chromium.org/297303006

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21607 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
yangguo@chromium.org 2014-06-02 12:51:19 +00:00
parent 77130247ac
commit 19c71f9e47
8 changed files with 217 additions and 312 deletions

View File

@ -80,6 +80,22 @@ BreakLocationIterator::~BreakLocationIterator() {
}
// Check whether a code stub with the specified major key is a possible break
// point location when looking for source break locations.
static bool IsSourceBreakStub(Code* code) {
CodeStub::Major major_key = CodeStub::GetMajorKey(code);
return major_key == CodeStub::CallFunction;
}
// Check whether a code stub with the specified major key is a possible break
// location.
static bool IsBreakStub(Code* code) {
CodeStub::Major major_key = CodeStub::GetMajorKey(code);
return major_key == CodeStub::CallFunction;
}
void BreakLocationIterator::Next() {
DisallowHeapAllocation no_gc;
ASSERT(!RinfoDone());
@ -129,15 +145,14 @@ void BreakLocationIterator::Next() {
if (IsDebuggerStatement()) {
break_point_++;
return;
}
if (type_ == ALL_BREAK_LOCATIONS) {
if (Debug::IsBreakStub(code)) {
} else if (type_ == ALL_BREAK_LOCATIONS) {
if (IsBreakStub(code)) {
break_point_++;
return;
}
} else {
ASSERT(type_ == SOURCE_BREAK_LOCATIONS);
if (Debug::IsSourceBreakStub(code)) {
if (IsSourceBreakStub(code)) {
break_point_++;
return;
}
@ -422,6 +437,53 @@ bool BreakLocationIterator::IsDebugBreak() {
}
// Find the builtin to use for invoking the debug break
static Handle<Code> DebugBreakForIC(Handle<Code> code, RelocInfo::Mode mode) {
Isolate* isolate = code->GetIsolate();
// Find the builtin debug break function matching the calling convention
// used by the call site.
if (code->is_inline_cache_stub()) {
switch (code->kind()) {
case Code::CALL_IC:
return isolate->builtins()->CallICStub_DebugBreak();
case Code::LOAD_IC:
return isolate->builtins()->LoadIC_DebugBreak();
case Code::STORE_IC:
return isolate->builtins()->StoreIC_DebugBreak();
case Code::KEYED_LOAD_IC:
return isolate->builtins()->KeyedLoadIC_DebugBreak();
case Code::KEYED_STORE_IC:
return isolate->builtins()->KeyedStoreIC_DebugBreak();
case Code::COMPARE_NIL_IC:
return isolate->builtins()->CompareNilIC_DebugBreak();
default:
UNREACHABLE();
}
}
if (RelocInfo::IsConstructCall(mode)) {
if (code->has_function_cache()) {
return isolate->builtins()->CallConstructStub_Recording_DebugBreak();
} else {
return isolate->builtins()->CallConstructStub_DebugBreak();
}
}
if (code->kind() == Code::STUB) {
ASSERT(code->major_key() == CodeStub::CallFunction);
return isolate->builtins()->CallFunctionStub_DebugBreak();
}
UNREACHABLE();
return Handle<Code>::null();
}
void BreakLocationIterator::SetDebugBreakAtIC() {
// Patch the original code with the current address as the current address
// might have changed by the inline caching since the code was copied.
@ -434,7 +496,7 @@ void BreakLocationIterator::SetDebugBreakAtIC() {
// Patch the code to invoke the builtin debug break function matching the
// calling convention used by the call site.
Handle<Code> dbgbrk_code(Debug::FindDebugBreak(target_code, mode));
Handle<Code> dbgbrk_code = DebugBreakForIC(target_code, mode);
rinfo()->set_target_address(dbgbrk_code->entry());
}
}
@ -504,7 +566,6 @@ void Debug::ThreadInit() {
thread_local_.step_out_fp_ = 0;
// TODO(isolates): frames_are_dropped_?
thread_local_.debugger_entry_ = NULL;
thread_local_.has_pending_interrupt_ = false;
thread_local_.restarter_frame_function_pointer_ = NULL;
thread_local_.promise_on_stack_ = NULL;
}
@ -530,6 +591,30 @@ int Debug::ArchiveSpacePerThread() {
}
ScriptCache::ScriptCache(Isolate* isolate) : HashMap(HashMap::PointersMatch),
isolate_(isolate),
collected_scripts_(10) {
Heap* heap = isolate_->heap();
HandleScope scope(isolate_);
// Perform two GCs to get rid of all unreferenced scripts. The first GC gets
// rid of all the cached script wrappers and the second gets rid of the
// scripts which are no longer referenced.
heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache");
heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache");
// Scan heap for Script objects.
HeapIterator iterator(heap);
DisallowHeapAllocation no_allocation;
for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
if (obj->IsScript() && Script::cast(obj)->HasValidSource()) {
Add(Handle<Script>(Script::cast(obj)));
}
}
}
void ScriptCache::Add(Handle<Script> script) {
GlobalHandles* global_handles = isolate_->global_handles();
// Create an entry in the hash map for the script.
@ -785,7 +870,10 @@ void Debug::Unload() {
if (!is_loaded()) return;
// Clear the script cache.
DestroyScriptCache();
if (script_cache_ != NULL) {
delete script_cache_;
script_cache_ = NULL;
}
// Clear debugger context global handle.
GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location());
@ -843,7 +931,8 @@ void Debug::Break(Arguments args, JavaScriptFrame* frame) {
// If step out is active skip everything until the frame where we need to step
// out to is reached, unless real breakpoint is hit.
if (StepOutActive() && frame->fp() != step_out_fp() &&
if (StepOutActive() &&
frame->fp() != thread_local_.step_out_fp_ &&
break_points_hit->IsUndefined() ) {
// Step count should always be 0 for StepOut.
ASSERT(thread_local_.step_count_ == 0);
@ -1192,7 +1281,7 @@ bool Debug::IsBreakOnException(ExceptionBreakType type) {
}
Debug::PromiseOnStack::PromiseOnStack(Isolate* isolate,
PromiseOnStack::PromiseOnStack(Isolate* isolate,
PromiseOnStack* prev,
Handle<JSFunction> getter)
: isolate_(isolate), prev_(prev) {
@ -1203,7 +1292,7 @@ Debug::PromiseOnStack::PromiseOnStack(Isolate* isolate,
}
Debug::PromiseOnStack::~PromiseOnStack() {
PromiseOnStack::~PromiseOnStack() {
isolate_->global_handles()->Destroy(Handle<Object>::cast(getter_).location());
}
@ -1530,68 +1619,8 @@ bool Debug::IsDebugBreak(Address addr) {
}
// Check whether a code stub with the specified major key is a possible break
// point location when looking for source break locations.
bool Debug::IsSourceBreakStub(Code* code) {
CodeStub::Major major_key = CodeStub::GetMajorKey(code);
return major_key == CodeStub::CallFunction;
}
// Check whether a code stub with the specified major key is a possible break
// location.
bool Debug::IsBreakStub(Code* code) {
CodeStub::Major major_key = CodeStub::GetMajorKey(code);
return major_key == CodeStub::CallFunction;
}
// Find the builtin to use for invoking the debug break
Handle<Code> Debug::FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode) {
Isolate* isolate = code->GetIsolate();
// Find the builtin debug break function matching the calling convention
// used by the call site.
if (code->is_inline_cache_stub()) {
switch (code->kind()) {
case Code::CALL_IC:
return isolate->builtins()->CallICStub_DebugBreak();
case Code::LOAD_IC:
return isolate->builtins()->LoadIC_DebugBreak();
case Code::STORE_IC:
return isolate->builtins()->StoreIC_DebugBreak();
case Code::KEYED_LOAD_IC:
return isolate->builtins()->KeyedLoadIC_DebugBreak();
case Code::KEYED_STORE_IC:
return isolate->builtins()->KeyedStoreIC_DebugBreak();
case Code::COMPARE_NIL_IC:
return isolate->builtins()->CompareNilIC_DebugBreak();
default:
UNREACHABLE();
}
}
if (RelocInfo::IsConstructCall(mode)) {
if (code->has_function_cache()) {
return isolate->builtins()->CallConstructStub_Recording_DebugBreak();
} else {
return isolate->builtins()->CallConstructStub_DebugBreak();
}
}
if (code->kind() == Code::STUB) {
ASSERT(code->major_key() == CodeStub::CallFunction);
return isolate->builtins()->CallFunctionStub_DebugBreak();
}
UNREACHABLE();
return Handle<Code>::null();
}
// Simple function for returning the source positions for active break points.
Handle<Object> Debug::GetSourceBreakLocations(
@ -1655,7 +1684,7 @@ void Debug::HandleStepIn(Handle<JSFunction> function,
// Flood the function with one-shot break points if it is called from where
// step into was requested.
if (fp == step_in_fp()) {
if (fp == thread_local_.step_into_fp_) {
if (function->shared()->bound()) {
// Handle Function.prototype.bind
Debug::FloodBoundFunctionWithOneShot(function);
@ -1912,7 +1941,7 @@ class ActiveFunctionsRedirector : public ThreadVisitor {
};
void Debug::EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function) {
static void EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function) {
if (function->code()->kind() == Code::FUNCTION &&
function->code()->has_debug_break_slots()) {
// Nothing to do. Function code already had debug break slots.
@ -1931,7 +1960,7 @@ void Debug::EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function) {
}
void Debug::RecompileAndRelocateSuspendedGenerators(
static void RecompileAndRelocateSuspendedGenerators(
const List<Handle<JSGeneratorObject> > &generators) {
for (int i = 0; i < generators.length(); i++) {
Handle<JSFunction> fun(generators[i]->function());
@ -2444,60 +2473,10 @@ void Debug::ClearMirrorCache() {
}
void Debug::CreateScriptCache() {
Heap* heap = isolate_->heap();
HandleScope scope(isolate_);
// Perform two GCs to get rid of all unreferenced scripts. The first GC gets
// rid of all the cached script wrappers and the second gets rid of the
// scripts which are no longer referenced. The second also sweeps precisely,
// which saves us doing yet another GC to make the heap iterable.
heap->CollectAllGarbage(Heap::kNoGCFlags, "Debug::CreateScriptCache");
ASSERT(script_cache_ == NULL);
script_cache_ = new ScriptCache(isolate_);
// Scan heap for Script objects.
int count = 0;
HeapIterator iterator(heap);
for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
if (obj->IsScript() && Script::cast(obj)->HasValidSource()) {
script_cache_->Add(Handle<Script>(Script::cast(obj)));
count++;
}
}
}
void Debug::DestroyScriptCache() {
// Get rid of the script cache if it was created.
if (script_cache_ != NULL) {
delete script_cache_;
script_cache_ = NULL;
}
}
void Debug::AddScriptToScriptCache(Handle<Script> script) {
if (script_cache_ != NULL) {
script_cache_->Add(script);
}
}
Handle<FixedArray> Debug::GetLoadedScripts() {
// Create and fill the script cache when the loaded scripts is requested for
// the first time.
if (script_cache_ == NULL) {
CreateScriptCache();
}
// If the script cache is not active just return an empty array.
ASSERT(script_cache_ != NULL);
if (script_cache_ == NULL) {
isolate_->factory()->NewFixedArray(0);
}
if (script_cache_ == NULL) script_cache_ = new ScriptCache(isolate_);
// Perform GC to get unreferenced scripts evicted from the cache before
// returning the content.
@ -2604,22 +2583,19 @@ MaybeHandle<Object> Debug::MakeScriptCollectedEvent(int id) {
void Debug::OnException(Handle<Object> exception, bool uncaught) {
if (is_entered() || ignore_events()) return;
HandleScope scope(isolate_);
// Bail out based on state or if there is no listener for this event
if (is_entered()) return;
if (!EventActive()) return;
Handle<Object> promise = GetPromiseForUncaughtException();
uncaught |= !promise->IsUndefined();
// Bail out if exception breaks are not active
if (uncaught) {
// Uncaught exceptions are reported by either flags.
if (!(break_on_uncaught_exception() || break_on_exception())) return;
if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
} else {
// Caught exceptions are reported is activated.
if (!break_on_exception()) return;
if (!break_on_exception_) return;
}
// Enter the debugger.
@ -2645,14 +2621,12 @@ void Debug::OnException(Handle<Object> exception, bool uncaught) {
void Debug::OnDebugBreak(Handle<Object> break_points_hit,
bool auto_continue) {
HandleScope scope(isolate_);
// Debugger has already been entered by caller.
ASSERT(isolate_->context() == *debug_context());
// Bail out if there is no listener for this event
if (!EventActive()) return;
if (ignore_events()) return;
HandleScope scope(isolate_);
// Create the event data object.
Handle<Object> event_data;
// Bail out and don't call debugger if exception.
@ -2666,12 +2640,9 @@ void Debug::OnDebugBreak(Handle<Object> break_points_hit,
void Debug::OnBeforeCompile(Handle<Script> script) {
if (is_entered() || ignore_events()) return;
HandleScope scope(isolate_);
// Bail out based on state or if there is no listener for this event
if (is_entered()) return;
if (!EventActive()) return;
// Enter the debugger.
EnterDebugger debugger(isolate_);
if (debugger.FailedToEnter()) return;
@ -2690,15 +2661,14 @@ void Debug::OnBeforeCompile(Handle<Script> script) {
// Handle debugger actions when a new script is compiled.
void Debug::OnAfterCompile(Handle<Script> script,
AfterCompileFlags after_compile_flags) {
HandleScope scope(isolate_);
AfterCompileFlags after_compile_flags) {
// Add the newly compiled script to the script cache.
AddScriptToScriptCache(script);
if (script_cache_ != NULL) script_cache_->Add(script);
// No more to do if not debugging.
if (!EventActive()) return;
if (is_entered() || ignore_events()) return;
HandleScope scope(isolate_);
// Store whether in debugger before entering debugger.
bool in_debugger = is_entered();
@ -2748,12 +2718,9 @@ void Debug::OnAfterCompile(Handle<Script> script,
void Debug::OnScriptCollected(int id) {
if (is_entered() || ignore_events()) return;
HandleScope scope(isolate_);
// No more to do if not debugging.
if (is_entered()) return;
if (!EventActive()) return;
// Enter the debugger.
EnterDebugger debugger(isolate_);
if (debugger.FailedToEnter()) return;
@ -2775,9 +2742,6 @@ void Debug::ProcessDebugEvent(v8::DebugEvent event,
bool auto_continue) {
HandleScope scope(isolate_);
// Clear any pending debug break if this is a real break.
if (!auto_continue) thread_local_.has_pending_interrupt_ = false;
// Create the execution state.
Handle<Object> exec_state;
// Bail out and don't call debugger if exception.
@ -3095,7 +3059,7 @@ MaybeHandle<Object> Debug::Call(Handle<JSFunction> fun, Handle<Object> data) {
}
void Debug::DebugBreakHelper() {
void Debug::HandleDebugBreak() {
// Ignore debug break during bootstrapping.
if (isolate_->bootstrapper()->IsActive()) return;
// Just continue if breaks are disabled.
@ -3161,9 +3125,9 @@ EnterDebugger::EnterDebugger(Isolate* isolate)
// Create the new break info. If there is no JavaScript frames there is no
// break frame id.
JavaScriptFrameIterator it(isolate_);
has_js_frames_ = !it.done();
debug->thread_local_.break_frame_id_ = has_js_frames_ ? it.frame()->id()
: StackFrame::NO_ID;
bool has_js_frames = !it.done();
debug->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id()
: StackFrame::NO_ID;
debug->SetNextBreakId();
debug->UpdateState();
@ -3187,9 +3151,7 @@ EnterDebugger::~EnterDebugger() {
// pending exception as clearing the mirror cache calls back into
// JavaScript. This can happen if the v8::Debug::Call is used in which
// case the exception should end up in the calling code.
if (!isolate_->has_pending_exception()) {
debug->ClearMirrorCache();
}
if (!isolate_->has_pending_exception()) debug->ClearMirrorCache();
// If there are commands in the queue when leaving the debugger request
// that these commands are processed.
@ -3369,10 +3331,6 @@ CommandMessage::CommandMessage(const Vector<uint16_t>& text,
}
CommandMessage::~CommandMessage() {
}
void CommandMessage::Dispose() {
text_.Dispose();
delete client_data_;
@ -3393,10 +3351,7 @@ CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
CommandMessageQueue::~CommandMessageQueue() {
while (!IsEmpty()) {
CommandMessage m = Get();
m.Dispose();
}
while (!IsEmpty()) Get().Dispose();
DeleteArray(messages_);
}

View File

@ -150,10 +150,7 @@ class BreakLocationIterator {
// the cache is the script id.
class ScriptCache : private HashMap {
public:
explicit ScriptCache(Isolate* isolate)
: HashMap(HashMap::PointersMatch),
isolate_(isolate),
collected_scripts_(10) {}
explicit ScriptCache(Isolate* isolate);
virtual ~ScriptCache() { Clear(); }
// Add script to the cache.
@ -287,7 +284,6 @@ class CommandMessage {
static CommandMessage New(const Vector<uint16_t>& command,
v8::Debug::ClientData* data);
CommandMessage();
~CommandMessage();
// Deletes user data and disposes of the text.
void Dispose();
@ -342,6 +338,23 @@ class LockingCommandMessageQueue BASE_EMBEDDED {
};
class PromiseOnStack {
public:
PromiseOnStack(Isolate* isolate,
PromiseOnStack* prev,
Handle<JSFunction> getter);
~PromiseOnStack();
StackHandler* handler() { return handler_; }
Handle<JSFunction> getter() { return getter_; }
PromiseOnStack* prev() { return prev_; }
private:
Isolate* isolate_;
StackHandler* handler_;
Handle<JSFunction> getter_;
PromiseOnStack* prev_;
};
// This class contains the debugger support. The main purpose is to handle
// setting break points in the code.
//
@ -374,29 +387,18 @@ class Debug {
MUST_USE_RESULT MaybeHandle<Object> Call(Handle<JSFunction> fun,
Handle<Object> data);
Handle<Context> GetDebugContext();
void DebugBreakHelper();
void HandleDebugBreak();
void ProcessDebugMessages(bool debug_command_only);
// Flags and states.
void set_live_edit_enabled(bool v) { live_edit_enabled_ = v; }
bool live_edit_enabled() const {
return FLAG_enable_liveedit && live_edit_enabled_ ;
}
inline bool is_active() const { return is_active_; }
inline bool is_loaded() const { return !debug_context_.is_null(); }
inline bool has_break_points() const { return has_break_points_; }
inline bool is_entered() const {
return thread_local_.debugger_entry_ != NULL;
}
void set_disable_break(bool v) { break_disabled_ = v; }
// Internal logic
bool Load();
void Break(Arguments args, JavaScriptFrame*);
void SetAfterBreakTarget(JavaScriptFrame* frame);
// Scripts handling.
Handle<FixedArray> GetLoadedScripts();
// Break point handling.
bool SetBreakPoint(Handle<JSFunction> function,
Handle<Object> break_point_object,
int* source_position);
@ -412,11 +414,7 @@ class Debug {
void ChangeBreakOnException(ExceptionBreakType type, bool enable);
bool IsBreakOnException(ExceptionBreakType type);
void PromiseHandlePrologue(Handle<JSFunction> promise_getter);
void PromiseHandleEpilogue();
// Returns a promise if it does not have a reject handler.
Handle<Object> GetPromiseForUncaughtException();
// Stepping handling.
void PrepareStep(StepAction step_action,
int step_count,
StackFrame::Id frame_id);
@ -425,6 +423,15 @@ class Debug {
bool IsStepping() { return thread_local_.step_count_ > 0; }
bool StepNextContinue(BreakLocationIterator* break_location_iterator,
JavaScriptFrame* frame);
bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
void HandleStepIn(Handle<JSFunction> function,
Handle<Object> holder,
Address fp,
bool is_constructor);
bool StepOutActive() { return thread_local_.step_out_fp_ != 0; }
// Purge all code objects that have no debug break slots.
void PrepareForBreakPoints();
// Returns whether the operation succeeded. Compilation can only be triggered
// if a valid closure is passed as the second argument, otherwise the shared
@ -434,74 +441,70 @@ class Debug {
static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared);
static bool HasDebugInfo(Handle<SharedFunctionInfo> shared);
void PrepareForBreakPoints();
// This function is used in FunctionNameUsing* tests.
Object* FindSharedFunctionInfoInScript(Handle<Script> script, int position);
// Returns true if the current stub call is patched to call the debugger.
static bool IsDebugBreak(Address addr);
// Returns true if the current return statement has been patched to be
// a debugger breakpoint.
static bool IsDebugBreakAtReturn(RelocInfo* rinfo);
// Check whether a code stub with the specified major key is a possible break
// point location.
static bool IsSourceBreakStub(Code* code);
static bool IsBreakStub(Code* code);
// Find the builtin to use for invoking the debug break
static Handle<Code> FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode);
static Handle<Object> GetSourceBreakLocations(
Handle<SharedFunctionInfo> shared,
BreakPositionAlignment position_aligment);
// Getter for the debug_context.
inline Handle<Context> debug_context() { return debug_context_; }
// Check whether a global object is the debug global object.
bool IsDebugGlobal(GlobalObject* global);
// Check whether this frame is just about to return.
bool IsBreakAtReturn(JavaScriptFrame* frame);
StackFrame::Id break_frame_id() { return thread_local_.break_frame_id_; }
int break_id() { return thread_local_.break_id_; }
bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
void HandleStepIn(Handle<JSFunction> function,
Handle<Object> holder,
Address fp,
bool is_constructor);
Address step_in_fp() { return thread_local_.step_into_fp_; }
Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; }
bool StepOutActive() { return thread_local_.step_out_fp_ != 0; }
Address step_out_fp() { return thread_local_.step_out_fp_; }
EnterDebugger* debugger_entry() { return thread_local_.debugger_entry_; }
// Check whether any of the specified interrupts are pending.
bool has_pending_interrupt() {
return thread_local_.has_pending_interrupt_;
}
// Set specified interrupts as pending.
void set_has_pending_interrupt(bool value) {
thread_local_.has_pending_interrupt_ = value;
}
// Getters for the current exception break state.
bool break_on_exception() { return break_on_exception_; }
bool break_on_uncaught_exception() {
return break_on_uncaught_exception_;
}
// Promise handling.
void PromiseHandlePrologue(Handle<JSFunction> promise_getter);
void PromiseHandleEpilogue();
// Support for LiveEdit
void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
LiveEdit::FrameDropMode mode,
Object** restarter_frame_function_pointer);
// Support for setting the address to jump to when returning from break point.
// Passed to MakeWeak.
static void HandleWeakDebugInfo(
const v8::WeakCallbackData<v8::Value, void>& data);
// Threading support.
char* ArchiveDebug(char* to);
char* RestoreDebug(char* from);
static int ArchiveSpacePerThread();
void FreeThreadResources() { }
// Record function from which eval was called.
static void RecordEvalCaller(Handle<Script> script);
// Garbage collection notifications.
void AfterGarbageCollection();
// Flags and states.
EnterDebugger* debugger_entry() { return thread_local_.debugger_entry_; }
inline Handle<Context> debug_context() { return debug_context_; }
void set_live_edit_enabled(bool v) { live_edit_enabled_ = v; }
bool live_edit_enabled() const {
return FLAG_enable_liveedit && live_edit_enabled_ ;
}
inline bool is_active() const { return is_active_; }
inline bool is_loaded() const { return !debug_context_.is_null(); }
inline bool has_break_points() const { return has_break_points_; }
inline bool is_entered() const {
return thread_local_.debugger_entry_ != NULL;
}
void set_disable_break(bool v) { break_disabled_ = v; }
StackFrame::Id break_frame_id() { return thread_local_.break_frame_id_; }
int break_id() { return thread_local_.break_id_; }
// Support for embedding into generated code.
Address after_break_target_address() {
return reinterpret_cast<Address>(&after_break_target_);
}
@ -511,48 +514,22 @@ class Debug {
return reinterpret_cast<Address>(address);
}
static const int kEstimatedNofBreakPointsInFunction = 16;
// Passed to MakeWeak.
static void HandleWeakDebugInfo(
const v8::WeakCallbackData<v8::Value, void>& data);
friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc
friend void CheckDebuggerUnloaded(bool check_functions); // In test-debug.cc
// Threading support.
char* ArchiveDebug(char* to);
char* RestoreDebug(char* from);
static int ArchiveSpacePerThread();
void FreeThreadResources() { }
// Script cache handling.
void CreateScriptCache();
void DestroyScriptCache();
void AddScriptToScriptCache(Handle<Script> script);
Handle<FixedArray> GetLoadedScripts();
// Record function from which eval was called.
static void RecordEvalCaller(Handle<Script> script);
// Garbage collection notifications.
void AfterGarbageCollection();
Address step_in_fp_addr() {
return reinterpret_cast<Address>(&thread_local_.step_into_fp_);
}
private:
explicit Debug(Isolate* isolate);
void UpdateState();
void Unload();
// Mirror cache handling.
void ClearMirrorCache();
void SetNextBreakId() {
thread_local_.break_id_ = ++thread_local_.break_count_;
}
// Check whether there are commands in the command queue.
inline bool has_commands() const { return !command_queue_.IsEmpty(); }
inline bool ignore_events() const { return is_suppressed_ || !is_active_; }
// Constructors for debug event objects.
MUST_USE_RESULT MaybeHandle<Object> MakeJSObject(
@ -570,12 +547,16 @@ class Debug {
Handle<Script> script, bool before);
MUST_USE_RESULT MaybeHandle<Object> MakeScriptCollectedEvent(int id);
// Mirror cache handling.
void ClearMirrorCache();
// Returns a promise if it does not have a reject handler.
Handle<Object> GetPromiseForUncaughtException();
void CallEventCallback(v8::DebugEvent event,
Handle<Object> exec_state,
Handle<Object> event_data,
v8::Debug::ClientData* client_data);
void ProcessDebugEvent(v8::DebugEvent event,
Handle<JSObject> event_data,
bool auto_continue);
@ -583,17 +564,8 @@ class Debug {
Handle<JSObject> exec_state,
Handle<JSObject> event_data,
bool auto_continue);
// Invoke the message handler function.
void InvokeMessageHandler(MessageImpl message);
inline bool EventActive() {
// Check whether the message handler was been cleared.
// TODO(yangguo): handle loading and unloading of the debugger differently.
// Currently argument event is not used.
return !is_suppressed_ && is_active_;
}
static bool CompileDebuggerScript(Isolate* isolate, int index);
void ClearOneShot();
void ActivateStepIn(StackFrame* frame);
@ -605,28 +577,8 @@ class Debug {
Handle<Object> CheckBreakPoints(Handle<Object> break_point);
bool CheckBreakPoint(Handle<Object> break_point_object);
void EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function);
void RecompileAndRelocateSuspendedGenerators(
const List<Handle<JSGeneratorObject> > &suspended_generators);
void ThreadInit();
class PromiseOnStack {
public:
PromiseOnStack(Isolate* isolate,
PromiseOnStack* prev,
Handle<JSFunction> getter);
~PromiseOnStack();
StackHandler* handler() { return handler_; }
Handle<JSFunction> getter() { return getter_; }
PromiseOnStack* prev() { return prev_; }
private:
Isolate* isolate_;
StackHandler* handler_;
Handle<JSFunction> getter_;
PromiseOnStack* prev_;
};
// Global handles.
Handle<Context> debug_context_;
Handle<Object> event_listener_;
@ -692,9 +644,6 @@ class Debug {
// step out action is completed.
Address step_out_fp_;
// Pending interrupts scheduled while debugging.
bool has_pending_interrupt_;
// Stores the way how LiveEdit has patched the stack. It is used when
// debugger returns control back to user script.
LiveEdit::FrameDropMode frame_drop_mode_;
@ -723,6 +672,9 @@ class Debug {
friend class DisableBreak;
friend class SuppressDebug;
friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc
friend void CheckDebuggerUnloaded(bool check_functions); // In test-debug.cc
DISALLOW_COPY_AND_ASSIGN(Debug);
};
@ -742,16 +694,12 @@ class EnterDebugger BASE_EMBEDDED {
// Check whether the debugger could be entered.
inline bool FailedToEnter() { return load_failed_; }
// Check whether there are any JavaScript frames on the stack.
inline bool HasJavaScriptFrames() { return has_js_frames_; }
// Get the active context from before entering the debugger.
inline Handle<Context> GetContext() { return save_.context(); }
private:
Isolate* isolate_;
EnterDebugger* prev_; // Previous debugger entry if entered recursively.
bool has_js_frames_; // Were there any JavaScript frames?
StackFrame::Id break_frame_id_; // Previous break frame id.
int break_id_; // Previous break id.
bool load_failed_; // Did the debugger fail to load?

View File

@ -667,7 +667,7 @@ Object* StackGuard::HandleInterrupts() {
}
if (CheckDebugBreak() || CheckDebugCommand()) {
isolate_->debug()->DebugBreakHelper();
isolate_->debug()->HandleDebugBreak();
}
if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {

View File

@ -2039,7 +2039,7 @@ Handle<DebugInfo> Factory::NewDebugInfo(Handle<SharedFunctionInfo> shared) {
// debug info object to avoid allocation while setting up the debug info
// object.
Handle<FixedArray> break_points(
NewFixedArray(Debug::kEstimatedNofBreakPointsInFunction));
NewFixedArray(DebugInfo::kEstimatedNofBreakPointsInFunction));
// Create and set up the debug info object. Debug info contains function, a
// copy of the original code, the executing code and initial fixed array for

View File

@ -1850,8 +1850,8 @@ static const char* DropActivationsInActiveThreadImpl(
break;
}
}
debug->FramesHaveBeenDropped(new_id, drop_mode,
restarter_frame_function_pointer);
debug->FramesHaveBeenDropped(
new_id, drop_mode, restarter_frame_function_pointer);
return NULL;
}

View File

@ -16696,7 +16696,7 @@ void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
Handle<FixedArray> new_break_points =
isolate->factory()->NewFixedArray(
old_break_points->length() +
Debug::kEstimatedNofBreakPointsInFunction);
DebugInfo::kEstimatedNofBreakPointsInFunction);
debug_info->set_break_points(*new_break_points);
for (int i = 0; i < old_break_points->length(); i++) {

View File

@ -10882,6 +10882,8 @@ class DebugInfo: public Struct {
kActiveBreakPointsCountIndex + kPointerSize;
static const int kSize = kBreakPointsStateIndex + kPointerSize;
static const int kEstimatedNofBreakPointsInFunction = 16;
private:
static const int kNoBreakPointInfo = -1;

View File

@ -10698,7 +10698,7 @@ RUNTIME_FUNCTION(Runtime_LookupAccessor) {
RUNTIME_FUNCTION(Runtime_DebugBreak) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 0);
isolate->debug()->DebugBreakHelper();
isolate->debug()->HandleDebugBreak();
return isolate->heap()->undefined_value();
}