[debugger] Ensure at least one breakable position per function.

The function literal consists of a list of statements. Each statement
is associated with a statement position including break location. The
only exception to this rule is when the function immediately throws if
scope resolution found an illegal redeclaration. Make sure that we add a
break location for this case as well. The debugger relies on this.

R=bmeurer@chromium.org, vogelheim@chromium.org
BUG=v8:4690
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#34422}
This commit is contained in:
yangguo 2016-03-02 02:30:30 -08:00 committed by Commit bot
parent 7b40af9701
commit 44e9622aea
16 changed files with 36 additions and 29 deletions

View File

@ -98,7 +98,9 @@ BreakLocation::CodeIterator::CodeIterator(Handle<DebugInfo> debug_info,
: Iterator(debug_info), : Iterator(debug_info),
reloc_iterator_(debug_info->abstract_code()->GetCode(), reloc_iterator_(debug_info->abstract_code()->GetCode(),
GetModeMask(type)) { GetModeMask(type)) {
if (!Done()) Next(); // There is at least one break location.
DCHECK(!Done());
Next();
} }
int BreakLocation::CodeIterator::GetModeMask(BreakLocatorType type) { int BreakLocation::CodeIterator::GetModeMask(BreakLocatorType type) {
@ -179,7 +181,9 @@ BreakLocation::BytecodeArrayIterator::BytecodeArrayIterator(
->source_position_table()), ->source_position_table()),
break_locator_type_(type), break_locator_type_(type),
start_position_(debug_info->shared()->start_position()) { start_position_(debug_info->shared()->start_position()) {
if (!Done()) Next(); // There is at least one break location.
DCHECK(!Done());
Next();
} }
void BreakLocation::BytecodeArrayIterator::Next() { void BreakLocation::BytecodeArrayIterator::Next() {

View File

@ -296,9 +296,7 @@ void FullCodeGenerator::Generate() {
// Visit the declarations and body unless there is an illegal // Visit the declarations and body unless there is an illegal
// redeclaration. // redeclaration.
if (scope()->HasIllegalRedeclaration()) { if (scope()->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ Declarations"); EmitIllegalRedeclaration();
VisitForEffect(scope()->GetIllegalRedeclaration());
} else { } else {
PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
{ Comment cmnt(masm_, "[ Declarations"); { Comment cmnt(masm_, "[ Declarations");

View File

@ -299,9 +299,7 @@ void FullCodeGenerator::Generate() {
// Visit the declarations and body unless there is an illegal // Visit the declarations and body unless there is an illegal
// redeclaration. // redeclaration.
if (scope()->HasIllegalRedeclaration()) { if (scope()->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ Declarations"); EmitIllegalRedeclaration();
VisitForEffect(scope()->GetIllegalRedeclaration());
} else { } else {
PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
{ Comment cmnt(masm_, "[ Declarations"); { Comment cmnt(masm_, "[ Declarations");

View File

@ -984,6 +984,13 @@ void FullCodeGenerator::EmitBreak(Statement* target) {
__ jmp(current->AsBreakable()->break_label()); __ jmp(current->AsBreakable()->break_label());
} }
void FullCodeGenerator::EmitIllegalRedeclaration() {
Comment cmnt(masm_, "[ Declarations");
Expression* illegal = scope()->GetIllegalRedeclaration();
SetExpressionAsStatementPosition(illegal);
VisitForEffect(illegal);
}
void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
Comment cmnt(masm_, "[ BreakStatement"); Comment cmnt(masm_, "[ BreakStatement");
SetStatementPosition(stmt); SetStatementPosition(stmt);

View File

@ -684,6 +684,8 @@ class FullCodeGenerator: public AstVisitor {
void EmitContinue(Statement* target); void EmitContinue(Statement* target);
void EmitBreak(Statement* target); void EmitBreak(Statement* target);
void EmitIllegalRedeclaration();
// Loop nesting counter. // Loop nesting counter.
int loop_depth() { return loop_depth_; } int loop_depth() { return loop_depth_; }
void increment_loop_depth() { loop_depth_++; } void increment_loop_depth() { loop_depth_++; }

View File

@ -291,9 +291,7 @@ void FullCodeGenerator::Generate() {
// Visit the declarations and body unless there is an illegal // Visit the declarations and body unless there is an illegal
// redeclaration. // redeclaration.
if (scope()->HasIllegalRedeclaration()) { if (scope()->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ Declarations"); EmitIllegalRedeclaration();
VisitForEffect(scope()->GetIllegalRedeclaration());
} else { } else {
PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
{ Comment cmnt(masm_, "[ Declarations"); { Comment cmnt(masm_, "[ Declarations");

View File

@ -306,9 +306,7 @@ void FullCodeGenerator::Generate() {
// Visit the declarations and body unless there is an illegal // Visit the declarations and body unless there is an illegal
// redeclaration. // redeclaration.
if (scope()->HasIllegalRedeclaration()) { if (scope()->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ Declarations"); EmitIllegalRedeclaration();
VisitForEffect(scope()->GetIllegalRedeclaration());
} else { } else {
PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
{ Comment cmnt(masm_, "[ Declarations"); { Comment cmnt(masm_, "[ Declarations");

View File

@ -304,9 +304,7 @@ void FullCodeGenerator::Generate() {
// Visit the declarations and body unless there is an illegal // Visit the declarations and body unless there is an illegal
// redeclaration. // redeclaration.
if (scope()->HasIllegalRedeclaration()) { if (scope()->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ Declarations"); EmitIllegalRedeclaration();
VisitForEffect(scope()->GetIllegalRedeclaration());
} else { } else {
PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
{ Comment cmnt(masm_, "[ Declarations"); { Comment cmnt(masm_, "[ Declarations");

View File

@ -302,9 +302,7 @@ void FullCodeGenerator::Generate() {
// Visit the declarations and body unless there is an illegal // Visit the declarations and body unless there is an illegal
// redeclaration. // redeclaration.
if (scope()->HasIllegalRedeclaration()) { if (scope()->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ Declarations"); EmitIllegalRedeclaration();
VisitForEffect(scope()->GetIllegalRedeclaration());
} else { } else {
PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
{ {

View File

@ -287,9 +287,7 @@ void FullCodeGenerator::Generate() {
// Visit the declarations and body unless there is an illegal // Visit the declarations and body unless there is an illegal
// redeclaration. // redeclaration.
if (scope()->HasIllegalRedeclaration()) { if (scope()->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ Declarations"); EmitIllegalRedeclaration();
VisitForEffect(scope()->GetIllegalRedeclaration());
} else { } else {
PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
{ Comment cmnt(masm_, "[ Declarations"); { Comment cmnt(masm_, "[ Declarations");

View File

@ -288,9 +288,7 @@ void FullCodeGenerator::Generate() {
// Visit the declarations and body unless there is an illegal // Visit the declarations and body unless there is an illegal
// redeclaration. // redeclaration.
if (scope()->HasIllegalRedeclaration()) { if (scope()->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ Declarations"); EmitIllegalRedeclaration();
VisitForEffect(scope()->GetIllegalRedeclaration());
} else { } else {
PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
{ Comment cmnt(masm_, "[ Declarations"); { Comment cmnt(masm_, "[ Declarations");

View File

@ -1212,6 +1212,13 @@ void BytecodeArrayBuilder::SetExpressionPosition(Expression* expr) {
expr->position()); expr->position());
} }
void BytecodeArrayBuilder::SetExpressionAsStatementPosition(Expression* expr) {
if (expr->position() == RelocInfo::kNoPosition) return;
if (exit_seen_in_block_) return;
source_position_table_builder_.AddStatementPosition(bytecodes_.size(),
expr->position());
}
bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const {
return temporary_register_allocator()->RegisterIsLive(reg); return temporary_register_allocator()->RegisterIsLive(reg);
} }

View File

@ -263,6 +263,7 @@ class BytecodeArrayBuilder final : public ZoneObject, private RegisterMover {
void SetStatementPosition(Statement* stmt); void SetStatementPosition(Statement* stmt);
void SetExpressionPosition(Expression* expr); void SetExpressionPosition(Expression* expr);
void SetExpressionAsStatementPosition(Expression* expr);
// Accessors // Accessors
Zone* zone() const { return zone_; } Zone* zone() const { return zone_; }

View File

@ -620,7 +620,9 @@ void BytecodeGenerator::MakeBytecodeBody() {
// Visit illegal re-declaration and bail out if it exists. // Visit illegal re-declaration and bail out if it exists.
if (scope()->HasIllegalRedeclaration()) { if (scope()->HasIllegalRedeclaration()) {
VisitForEffect(scope()->GetIllegalRedeclaration()); Expression* illegal = scope()->GetIllegalRedeclaration();
builder()->SetExpressionAsStatementPosition(illegal);
VisitForEffect(illegal);
return; return;
} }

View File

@ -151,9 +151,10 @@ void SourcePositionTableBuilder::AddEntry(const PositionTableEntry& entry) {
} }
Handle<ByteArray> SourcePositionTableBuilder::ToSourcePositionTable() { Handle<ByteArray> SourcePositionTableBuilder::ToSourcePositionTable() {
if (bytes_.empty()) return isolate_->factory()->empty_byte_array();
Handle<ByteArray> table = isolate_->factory()->NewByteArray( Handle<ByteArray> table = isolate_->factory()->NewByteArray(
static_cast<int>(bytes_.size()), TENURED); static_cast<int>(bytes_.size()), TENURED);
if (bytes_.empty()) return table;
MemCopy(table->GetDataStartAddress(), &*bytes_.begin(), bytes_.size()); MemCopy(table->GetDataStartAddress(), &*bytes_.begin(), bytes_.size());

View File

@ -790,7 +790,6 @@
'es6/debug-stepin-string-template': [FAIL], 'es6/debug-stepin-string-template': [FAIL],
'es6/debug-promises/stepin-constructor': [FAIL], 'es6/debug-promises/stepin-constructor': [FAIL],
'harmony/debug-stepin-proxies': [FAIL], 'harmony/debug-stepin-proxies': [FAIL],
'regress/regress-debugger-redirect': [PASS, FAIL],
'regress/regress-crbug-119800': [FAIL], 'regress/regress-crbug-119800': [FAIL],
'regress/regress-crbug-467180': [FAIL], 'regress/regress-crbug-467180': [FAIL],
'regress/regress-opt-after-debug-deopt': [FAIL], 'regress/regress-opt-after-debug-deopt': [FAIL],