Revision: 3312 Author: [email protected] Date: Mon Nov 16 13:59:31 2009 Log: Step next should respect do/while condition block.
Condition block of do/while statements is a valid break location so it should have its own position. The block is represented by a regular Expression node so we cannot store the position in it, instead the position is stored in a separate field in DoWhileStatement AST node. BUG=514 Review URL: http://codereview.chromium.org/385136 http://code.google.com/p/v8/source/detail?r=3312 Added: /branches/bleeding_edge/test/mjsunit/debug-stepnext-do-while.js Modified: /branches/bleeding_edge/src/arm/codegen-arm.cc /branches/bleeding_edge/src/arm/codegen-arm.h /branches/bleeding_edge/src/ast.h /branches/bleeding_edge/src/codegen.cc /branches/bleeding_edge/src/codegen.h /branches/bleeding_edge/src/ia32/codegen-ia32.cc /branches/bleeding_edge/src/ia32/codegen-ia32.h /branches/bleeding_edge/src/parser.cc /branches/bleeding_edge/src/x64/codegen-x64.cc /branches/bleeding_edge/src/x64/codegen-x64.h ======================================= --- /dev/null +++ /branches/bleeding_edge/test/mjsunit/debug-stepnext-do-while.js Mon Nov 16 13:59:31 2009 @@ -0,0 +1,79 @@ +// Copyright 2009 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --expose-debug-as debug +// Get the Debug object exposed from the debug context global object. +Debug = debug.Debug + +var exception = null; +var break_break_point_hit_count = 0; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + if (break_break_point_hit_count == 0) { + assertEquals(' debugger;', + event_data.sourceLineText()); + assertEquals('runDoWhile', event_data.func().name()); + } else if (break_break_point_hit_count == 1) { + assertEquals(' } while(condition());', + event_data.sourceLineText()); + assertEquals('runDoWhile', event_data.func().name()); + } + + break_break_point_hit_count++; + // Continue stepping until returned to bottom frame. + if (exec_state.frameCount() > 1) { + exec_state.prepareStep(Debug.StepAction.StepNext); + } + + } + } catch(e) { + exception = e; + } +}; + +// Add the debug event listener. +Debug.setListener(listener); + +function condition() { + return false; +} + +function runDoWhile() { + do { + debugger; + } while(condition()); +}; + +break_break_point_hit_count = 0; +runDoWhile(); +assertNull(exception); +assertEquals(4, break_break_point_hit_count); + +// Get rid of the debug event listener. +Debug.setListener(null); ======================================= --- /branches/bleeding_edge/src/arm/codegen-arm.cc Mon Nov 16 06:12:27 2009 +++ /branches/bleeding_edge/src/arm/codegen-arm.cc Mon Nov 16 13:59:31 2009 @@ -1583,6 +1583,8 @@ node->continue_target()->Bind(); } if (has_valid_frame()) { + Comment cmnt(masm_, "[ DoWhileCondition"); + CodeForDoWhileConditionPosition(node); LoadConditionAndSpill(node->cond(), &body, node->break_target(), true); if (has_valid_frame()) { // A invalid frame here indicates that control did not ======================================= --- /branches/bleeding_edge/src/arm/codegen-arm.h Wed Nov 4 09:59:24 2009 +++ /branches/bleeding_edge/src/arm/codegen-arm.h Mon Nov 16 13:59:31 2009 @@ -378,6 +378,7 @@ void CodeForFunctionPosition(FunctionLiteral* fun); void CodeForReturnPosition(FunctionLiteral* fun); void CodeForStatementPosition(Statement* node); + void CodeForDoWhileConditionPosition(DoWhileStatement* stmt); void CodeForSourcePosition(int pos); #ifdef DEBUG ======================================= --- /branches/bleeding_edge/src/ast.h Wed Nov 11 01:00:09 2009 +++ /branches/bleeding_edge/src/ast.h Mon Nov 16 13:59:31 2009 @@ -322,7 +322,7 @@ class DoWhileStatement: public IterationStatement { public: explicit DoWhileStatement(ZoneStringList* labels) - : IterationStatement(labels), cond_(NULL) { + : IterationStatement(labels), cond_(NULL), condition_position_(-1) { } void Initialize(Expression* cond, Statement* body) { @@ -333,9 +333,15 @@ virtual void Accept(AstVisitor* v); Expression* cond() const { return cond_; } + + // Position where condition expression starts. We need it to make + // the loop's condition a breakable location. + int condition_position() { return condition_position_; } + void set_condition_position(int pos) { condition_position_ = pos; } private: Expression* cond_; + int condition_position_; }; ======================================= --- /branches/bleeding_edge/src/codegen.cc Wed Nov 4 09:59:24 2009 +++ /branches/bleeding_edge/src/codegen.cc Mon Nov 16 13:59:31 2009 @@ -431,6 +431,9 @@ if (FLAG_debug_info) RecordPositions(masm(), stmt->statement_pos()); } +void CodeGenerator::CodeForDoWhileConditionPosition(DoWhileStatement* stmt) { + if (FLAG_debug_info) RecordPositions(masm(), stmt->condition_position()); +} void CodeGenerator::CodeForSourcePosition(int pos) { if (FLAG_debug_info && pos != RelocInfo::kNoPosition) { ======================================= --- /branches/bleeding_edge/src/codegen.h Wed Nov 4 09:59:24 2009 +++ /branches/bleeding_edge/src/codegen.h Mon Nov 16 13:59:31 2009 @@ -69,6 +69,7 @@ // CodeForFunctionPosition // CodeForReturnPosition // CodeForStatementPosition +// CodeForDoWhileConditionPosition // CodeForSourcePosition ======================================= --- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Nov 13 04:32:57 2009 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Mon Nov 16 13:59:31 2009 @@ -2449,6 +2449,7 @@ CodeForStatementPosition(node); Load(node->expression()); Result return_value = frame_->Pop(); + masm()->WriteRecordedPositions(); if (function_return_is_shadowed_) { function_return_.Jump(&return_value); } else { @@ -2712,6 +2713,8 @@ node->continue_target()->Bind(); } if (has_valid_frame()) { + Comment cmnt(masm_, "[ DoWhileCondition"); + CodeForDoWhileConditionPosition(node); ControlDestination dest(&body, node->break_target(), false); LoadCondition(node->cond(), &dest, true); } ======================================= --- /branches/bleeding_edge/src/ia32/codegen-ia32.h Fri Nov 13 04:32:57 2009 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.h Mon Nov 16 13:59:31 2009 @@ -556,6 +556,7 @@ void CodeForFunctionPosition(FunctionLiteral* fun); void CodeForReturnPosition(FunctionLiteral* fun); void CodeForStatementPosition(Statement* stmt); + void CodeForDoWhileConditionPosition(DoWhileStatement* stmt); void CodeForSourcePosition(int pos); #ifdef DEBUG ======================================= --- /branches/bleeding_edge/src/parser.cc Wed Nov 11 01:00:09 2009 +++ /branches/bleeding_edge/src/parser.cc Mon Nov 16 13:59:31 2009 @@ -2542,6 +2542,12 @@ Statement* body = ParseStatement(NULL, CHECK_OK); Expect(Token::WHILE, CHECK_OK); Expect(Token::LPAREN, CHECK_OK); + + if (loop != NULL) { + int position = scanner().location().beg_pos; + loop->set_condition_position(position); + } + Expression* cond = ParseExpression(true, CHECK_OK); Expect(Token::RPAREN, CHECK_OK); ======================================= --- /branches/bleeding_edge/src/x64/codegen-x64.cc Fri Nov 13 04:32:57 2009 +++ /branches/bleeding_edge/src/x64/codegen-x64.cc Mon Nov 16 13:59:31 2009 @@ -1318,6 +1318,8 @@ node->continue_target()->Bind(); } if (has_valid_frame()) { + Comment cmnt(masm_, "[ DoWhileCondition"); + CodeForDoWhileConditionPosition(node); ControlDestination dest(&body, node->break_target(), false); LoadCondition(node->cond(), &dest, true); } ======================================= --- /branches/bleeding_edge/src/x64/codegen-x64.h Fri Nov 13 04:32:57 2009 +++ /branches/bleeding_edge/src/x64/codegen-x64.h Mon Nov 16 13:59:31 2009 @@ -556,6 +556,7 @@ void CodeForFunctionPosition(FunctionLiteral* fun); void CodeForReturnPosition(FunctionLiteral* fun); void CodeForStatementPosition(Statement* node); + void CodeForDoWhileConditionPosition(DoWhileStatement* stmt); void CodeForSourcePosition(int pos); #ifdef DEBUG --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---
