Index: src/debug/debug.cc |
diff --git a/src/debug/debug.cc b/src/debug/debug.cc |
index 13700ff0d420b09328bef971f01e3967645e4866..235c5f37734366f41e10811695acd8169d9ea1a8 100644 |
--- a/src/debug/debug.cc |
+++ b/src/debug/debug.cc |
@@ -16,6 +16,7 @@ |
#include "src/frames-inl.h" |
#include "src/full-codegen/full-codegen.h" |
#include "src/global-handles.h" |
+#include "src/interpreter/bytecodes.h" |
#include "src/isolate-inl.h" |
#include "src/list.h" |
#include "src/log.h" |
@@ -69,24 +70,21 @@ BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, DebugBreakType type, |
BreakLocation::Iterator* BreakLocation::GetIterator( |
Handle<DebugInfo> debug_info, BreakLocatorType type) { |
- if (debug_info->shared()->HasBytecodeArray()) { |
- UNIMPLEMENTED(); |
- return nullptr; |
+ if (debug_info->abstract_code()->IsBytecodeArray()) { |
+ return new BytecodeArrayIterator(debug_info, type); |
} |
rmcilroy
2016/02/11 12:32:03
nit - make this an else? Seems lopsided to me to m
Yang
2016/02/11 14:16:55
Done.
|
return new CodeIterator(debug_info, type); |
} |
-BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info, |
- BreakLocatorType type) |
+BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info) |
: debug_info_(debug_info), |
break_index_(-1), |
position_(1), |
- statement_position_(1) { |
-} |
+ statement_position_(1) {} |
BreakLocation::CodeIterator::CodeIterator(Handle<DebugInfo> debug_info, |
BreakLocatorType type) |
- : Iterator(debug_info, type), |
+ : Iterator(debug_info), |
reloc_iterator_(debug_info->abstract_code()->GetCode(), |
GetModeMask(type)) { |
if (!Done()) Next(); |
@@ -109,8 +107,7 @@ void BreakLocation::CodeIterator::Next() { |
DisallowHeapAllocation no_gc; |
DCHECK(!Done()); |
- // Iterate through reloc info for code and original code stopping at each |
- // breakable code target. |
+ // Iterate through reloc info stopping at each breakable code target. |
bool first = break_index_ == -1; |
while (!Done()) { |
if (!first) reloc_iterator_.next(); |
@@ -169,6 +166,65 @@ BreakLocation BreakLocation::CodeIterator::GetBreakLocation() { |
statement_position()); |
} |
+BreakLocation::BytecodeArrayIterator::BytecodeArrayIterator( |
+ Handle<DebugInfo> debug_info, BreakLocatorType type) |
+ : Iterator(debug_info), |
+ iterator_(debug_info->abstract_code()->GetBytecodeArray()), |
+ break_locator_type_(type), |
+ start_position_(debug_info->shared()->start_position()) { |
+ if (!Done()) Next(); |
+} |
+ |
+void BreakLocation::BytecodeArrayIterator::Next() { |
+ DisallowHeapAllocation no_gc; |
+ DCHECK(!Done()); |
+ bool first = break_index_ == -1; |
+ while (!Done()) { |
+ if (!first) iterator_.Advance(); |
+ first = false; |
+ if (Done()) return; |
+ position_ = iterator_.source_position() - start_position_; |
+ if (iterator_.is_statement()) statement_position_ = position_; |
+ DCHECK(position_ >= 0); |
+ DCHECK(statement_position_ >= 0); |
+ break_index_++; |
+ |
+ if (break_locator_type_ == ALL_BREAK_LOCATIONS) break; |
+ DCHECK_EQ(CALLS_AND_RETURNS, break_locator_type_); |
rmcilroy
2016/02/11 12:32:03
nit - new line above
Yang
2016/02/11 14:16:55
Done.
|
+ enum DebugBreakType type = DebugBreakType(); |
+ if (type == DEBUG_BREAK_SLOT_AT_CALL || |
+ type == DEBUG_BREAK_SLOT_AT_RETURN) { |
+ break; |
+ } |
+ } |
+} |
+ |
+BreakLocation::DebugBreakType |
+BreakLocation::BytecodeArrayIterator::DebugBreakType() { |
+ BytecodeArray* bytecode_array = |
+ debug_info_->abstract_code()->GetBytecodeArray(); |
+ interpreter::Bytecode bytecode = |
+ static_cast<interpreter::Bytecode>(bytecode_array->get(code_offset())); |
+ |
+ switch (bytecode) { |
+ case interpreter::Bytecode::kDebugger: |
+ return DEBUGGER_STATEMENT; |
+ case interpreter::Bytecode::kCall: |
rmcilroy
2016/02/11 12:32:03
You need to list KCallWide and kNewWide as well (a
Yang
2016/02/11 14:16:55
Done.
|
+ case interpreter::Bytecode::kNew: |
+ return DEBUG_BREAK_SLOT_AT_CALL; |
+ case interpreter::Bytecode::kReturn: |
+ return DEBUG_BREAK_SLOT_AT_RETURN; |
+ default: |
+ break; |
+ } |
+ return iterator_.is_statement() ? DEBUG_BREAK_SLOT : NOT_DEBUG_BREAK; |
+} |
+ |
+BreakLocation BreakLocation::BytecodeArrayIterator::GetBreakLocation() { |
+ return BreakLocation(debug_info_, DebugBreakType(), code_offset(), position(), |
+ statement_position()); |
+} |
+ |
// Find the break point at the supplied address, or the closest one before |
// the address. |
BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, |
@@ -342,7 +398,7 @@ void BreakLocation::SetDebugBreak() { |
DebugCodegen::PatchDebugBreakSlot(isolate(), pc, target); |
DCHECK(IsDebugBreak()); |
} else { |
- UNIMPLEMENTED(); |
+ // TODO(yangguo): implement this once we have a way to record break points. |
} |
} |
@@ -359,7 +415,7 @@ void BreakLocation::ClearDebugBreak() { |
DebugCodegen::ClearDebugBreakSlot(isolate(), pc); |
DCHECK(!IsDebugBreak()); |
} else { |
- UNIMPLEMENTED(); |
+ // TODO(yangguo): implement this once we have a way to record break points. |
} |
} |
@@ -373,7 +429,7 @@ bool BreakLocation::IsDebugBreak() const { |
Address pc = code->instruction_start() + code_offset(); |
return DebugCodegen::DebugBreakSlotIsPatched(pc); |
} else { |
- UNIMPLEMENTED(); |
+ // TODO(yangguo): implement this once we have a way to record break points. |
return false; |
} |
} |
@@ -1163,6 +1219,10 @@ class RedirectActiveFunctions : public ThreadVisitor { |
for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { |
JavaScriptFrame* frame = it.frame(); |
JSFunction* function = frame->function(); |
+ if (frame->is_interpreted()) { |
+ // TODO(yangguo): replace dispatch table for activated frames. |
+ continue; |
+ } |
if (frame->is_optimized()) continue; |
if (!function->Inlines(shared_)) continue; |