Reland "Fix stepping in for-loops."
BUG=v8:3634 LOG=N R=ulan@chromium.org Review URL: https://codereview.chromium.org/688243005 Cr-Commit-Position: refs/heads/master@{#25279} git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25279 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
dc12fbf002
commit
4fd9ba9042
@ -1111,6 +1111,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
|
|
||||||
// Get the object to enumerate over. If the object is null or undefined, skip
|
// Get the object to enumerate over. If the object is null or undefined, skip
|
||||||
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
||||||
|
SetExpressionPosition(stmt->enumerable());
|
||||||
VisitForAccumulatorValue(stmt->enumerable());
|
VisitForAccumulatorValue(stmt->enumerable());
|
||||||
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
|
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
|
||||||
__ cmp(r0, ip);
|
__ cmp(r0, ip);
|
||||||
@ -1214,6 +1215,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
// Generate code for doing the condition check.
|
// Generate code for doing the condition check.
|
||||||
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
||||||
__ bind(&loop);
|
__ bind(&loop);
|
||||||
|
SetExpressionPosition(stmt->each());
|
||||||
|
|
||||||
// Load the current count to r0, load the length to r1.
|
// Load the current count to r0, load the length to r1.
|
||||||
__ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
|
__ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
|
||||||
__ cmp(r0, r1); // Compare to the array length.
|
__ cmp(r0, r1); // Compare to the array length.
|
||||||
@ -1283,48 +1286,6 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
|
|
||||||
Comment cmnt(masm_, "[ ForOfStatement");
|
|
||||||
SetStatementPosition(stmt);
|
|
||||||
|
|
||||||
Iteration loop_statement(this, stmt);
|
|
||||||
increment_loop_depth();
|
|
||||||
|
|
||||||
// var iterator = iterable[Symbol.iterator]();
|
|
||||||
VisitForEffect(stmt->assign_iterator());
|
|
||||||
|
|
||||||
// Loop entry.
|
|
||||||
__ bind(loop_statement.continue_label());
|
|
||||||
|
|
||||||
// result = iterator.next()
|
|
||||||
VisitForEffect(stmt->next_result());
|
|
||||||
|
|
||||||
// if (result.done) break;
|
|
||||||
Label result_not_done;
|
|
||||||
VisitForControl(stmt->result_done(),
|
|
||||||
loop_statement.break_label(),
|
|
||||||
&result_not_done,
|
|
||||||
&result_not_done);
|
|
||||||
__ bind(&result_not_done);
|
|
||||||
|
|
||||||
// each = result.value
|
|
||||||
VisitForEffect(stmt->assign_each());
|
|
||||||
|
|
||||||
// Generate code for the body of the loop.
|
|
||||||
Visit(stmt->body());
|
|
||||||
|
|
||||||
// Check stack before looping.
|
|
||||||
PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
|
|
||||||
EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
|
|
||||||
__ jmp(loop_statement.continue_label());
|
|
||||||
|
|
||||||
// Exit and decrement the loop depth.
|
|
||||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
|
||||||
__ bind(loop_statement.break_label());
|
|
||||||
decrement_loop_depth();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
||||||
bool pretenure) {
|
bool pretenure) {
|
||||||
// Use the fast case closure allocation code that allocates in new
|
// Use the fast case closure allocation code that allocates in new
|
||||||
|
@ -1109,6 +1109,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
|
|
||||||
// Get the object to enumerate over. If the object is null or undefined, skip
|
// Get the object to enumerate over. If the object is null or undefined, skip
|
||||||
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
||||||
|
SetExpressionPosition(stmt->enumerable());
|
||||||
VisitForAccumulatorValue(stmt->enumerable());
|
VisitForAccumulatorValue(stmt->enumerable());
|
||||||
__ JumpIfRoot(x0, Heap::kUndefinedValueRootIndex, &exit);
|
__ JumpIfRoot(x0, Heap::kUndefinedValueRootIndex, &exit);
|
||||||
Register null_value = x15;
|
Register null_value = x15;
|
||||||
@ -1202,6 +1203,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
// Generate code for doing the condition check.
|
// Generate code for doing the condition check.
|
||||||
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
||||||
__ Bind(&loop);
|
__ Bind(&loop);
|
||||||
|
SetExpressionPosition(stmt->each());
|
||||||
|
|
||||||
// Load the current count to x0, load the length to x1.
|
// Load the current count to x0, load the length to x1.
|
||||||
__ PeekPair(x0, x1, 0);
|
__ PeekPair(x0, x1, 0);
|
||||||
__ Cmp(x0, x1); // Compare to the array length.
|
__ Cmp(x0, x1); // Compare to the array length.
|
||||||
@ -1271,48 +1274,6 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
|
|
||||||
Comment cmnt(masm_, "[ ForOfStatement");
|
|
||||||
SetStatementPosition(stmt);
|
|
||||||
|
|
||||||
Iteration loop_statement(this, stmt);
|
|
||||||
increment_loop_depth();
|
|
||||||
|
|
||||||
// var iterator = iterable[Symbol.iterator]();
|
|
||||||
VisitForEffect(stmt->assign_iterator());
|
|
||||||
|
|
||||||
// Loop entry.
|
|
||||||
__ Bind(loop_statement.continue_label());
|
|
||||||
|
|
||||||
// result = iterator.next()
|
|
||||||
VisitForEffect(stmt->next_result());
|
|
||||||
|
|
||||||
// if (result.done) break;
|
|
||||||
Label result_not_done;
|
|
||||||
VisitForControl(stmt->result_done(),
|
|
||||||
loop_statement.break_label(),
|
|
||||||
&result_not_done,
|
|
||||||
&result_not_done);
|
|
||||||
__ Bind(&result_not_done);
|
|
||||||
|
|
||||||
// each = result.value
|
|
||||||
VisitForEffect(stmt->assign_each());
|
|
||||||
|
|
||||||
// Generate code for the body of the loop.
|
|
||||||
Visit(stmt->body());
|
|
||||||
|
|
||||||
// Check stack before looping.
|
|
||||||
PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
|
|
||||||
EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
|
|
||||||
__ B(loop_statement.continue_label());
|
|
||||||
|
|
||||||
// Exit and decrement the loop depth.
|
|
||||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
|
||||||
__ Bind(loop_statement.break_label());
|
|
||||||
decrement_loop_depth();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
||||||
bool pretenure) {
|
bool pretenure) {
|
||||||
// Use the fast case closure allocation code that allocates in new space for
|
// Use the fast case closure allocation code that allocates in new space for
|
||||||
|
@ -136,21 +136,19 @@ void BreakableStatementChecker::VisitWhileStatement(WhileStatement* stmt) {
|
|||||||
|
|
||||||
|
|
||||||
void BreakableStatementChecker::VisitForStatement(ForStatement* stmt) {
|
void BreakableStatementChecker::VisitForStatement(ForStatement* stmt) {
|
||||||
// Mark for statements breakable if the condition expression is.
|
// We set positions for both init and condition, if they exist.
|
||||||
if (stmt->cond() != NULL) {
|
if (stmt->cond() != NULL || stmt->init() != NULL) is_breakable_ = true;
|
||||||
Visit(stmt->cond());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BreakableStatementChecker::VisitForInStatement(ForInStatement* stmt) {
|
void BreakableStatementChecker::VisitForInStatement(ForInStatement* stmt) {
|
||||||
// Mark for in statements breakable if the enumerable expression is.
|
// For-in is breakable because we set the position for the enumerable.
|
||||||
Visit(stmt->enumerable());
|
is_breakable_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BreakableStatementChecker::VisitForOfStatement(ForOfStatement* stmt) {
|
void BreakableStatementChecker::VisitForOfStatement(ForOfStatement* stmt) {
|
||||||
// For-of is breakable because of the next() call.
|
// For-of is breakable because we set the position for the next() call.
|
||||||
is_breakable_ = true;
|
is_breakable_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1345,6 +1343,7 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
|
|||||||
SetStatementPosition(stmt);
|
SetStatementPosition(stmt);
|
||||||
|
|
||||||
if (stmt->init() != NULL) {
|
if (stmt->init() != NULL) {
|
||||||
|
SetStatementPosition(stmt->init());
|
||||||
Visit(stmt->init());
|
Visit(stmt->init());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1359,6 +1358,7 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
|
|||||||
PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
|
PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
|
||||||
__ bind(loop_statement.continue_label());
|
__ bind(loop_statement.continue_label());
|
||||||
if (stmt->next() != NULL) {
|
if (stmt->next() != NULL) {
|
||||||
|
SetStatementPosition(stmt->next());
|
||||||
Visit(stmt->next());
|
Visit(stmt->next());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1371,6 +1371,7 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
|
|||||||
|
|
||||||
__ bind(&test);
|
__ bind(&test);
|
||||||
if (stmt->cond() != NULL) {
|
if (stmt->cond() != NULL) {
|
||||||
|
SetExpressionPosition(stmt->cond());
|
||||||
VisitForControl(stmt->cond(),
|
VisitForControl(stmt->cond(),
|
||||||
&body,
|
&body,
|
||||||
loop_statement.break_label(),
|
loop_statement.break_label(),
|
||||||
@ -1385,6 +1386,47 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
|
||||||
|
Comment cmnt(masm_, "[ ForOfStatement");
|
||||||
|
SetStatementPosition(stmt);
|
||||||
|
|
||||||
|
Iteration loop_statement(this, stmt);
|
||||||
|
increment_loop_depth();
|
||||||
|
|
||||||
|
// var iterator = iterable[Symbol.iterator]();
|
||||||
|
VisitForEffect(stmt->assign_iterator());
|
||||||
|
|
||||||
|
// Loop entry.
|
||||||
|
__ bind(loop_statement.continue_label());
|
||||||
|
|
||||||
|
// result = iterator.next()
|
||||||
|
SetExpressionPosition(stmt->next_result());
|
||||||
|
VisitForEffect(stmt->next_result());
|
||||||
|
|
||||||
|
// if (result.done) break;
|
||||||
|
Label result_not_done;
|
||||||
|
VisitForControl(stmt->result_done(), loop_statement.break_label(),
|
||||||
|
&result_not_done, &result_not_done);
|
||||||
|
__ bind(&result_not_done);
|
||||||
|
|
||||||
|
// each = result.value
|
||||||
|
VisitForEffect(stmt->assign_each());
|
||||||
|
|
||||||
|
// Generate code for the body of the loop.
|
||||||
|
Visit(stmt->body());
|
||||||
|
|
||||||
|
// Check stack before looping.
|
||||||
|
PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
|
||||||
|
EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
|
||||||
|
__ jmp(loop_statement.continue_label());
|
||||||
|
|
||||||
|
// Exit and decrement the loop depth.
|
||||||
|
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
||||||
|
__ bind(loop_statement.break_label());
|
||||||
|
decrement_loop_depth();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
||||||
Comment cmnt(masm_, "[ TryCatchStatement");
|
Comment cmnt(masm_, "[ TryCatchStatement");
|
||||||
SetStatementPosition(stmt);
|
SetStatementPosition(stmt);
|
||||||
|
@ -1045,6 +1045,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
|
|
||||||
// Get the object to enumerate over. If the object is null or undefined, skip
|
// Get the object to enumerate over. If the object is null or undefined, skip
|
||||||
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
||||||
|
SetExpressionPosition(stmt->enumerable());
|
||||||
VisitForAccumulatorValue(stmt->enumerable());
|
VisitForAccumulatorValue(stmt->enumerable());
|
||||||
__ cmp(eax, isolate()->factory()->undefined_value());
|
__ cmp(eax, isolate()->factory()->undefined_value());
|
||||||
__ j(equal, &exit);
|
__ j(equal, &exit);
|
||||||
@ -1139,6 +1140,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
// Generate code for doing the condition check.
|
// Generate code for doing the condition check.
|
||||||
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
||||||
__ bind(&loop);
|
__ bind(&loop);
|
||||||
|
SetExpressionPosition(stmt->each());
|
||||||
|
|
||||||
__ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index.
|
__ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index.
|
||||||
__ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length.
|
__ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length.
|
||||||
__ j(above_equal, loop_statement.break_label());
|
__ j(above_equal, loop_statement.break_label());
|
||||||
@ -1205,48 +1208,6 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
|
|
||||||
Comment cmnt(masm_, "[ ForOfStatement");
|
|
||||||
SetStatementPosition(stmt);
|
|
||||||
|
|
||||||
Iteration loop_statement(this, stmt);
|
|
||||||
increment_loop_depth();
|
|
||||||
|
|
||||||
// var iterator = iterable[Symbol.iterator]();
|
|
||||||
VisitForEffect(stmt->assign_iterator());
|
|
||||||
|
|
||||||
// Loop entry.
|
|
||||||
__ bind(loop_statement.continue_label());
|
|
||||||
|
|
||||||
// result = iterator.next()
|
|
||||||
VisitForEffect(stmt->next_result());
|
|
||||||
|
|
||||||
// if (result.done) break;
|
|
||||||
Label result_not_done;
|
|
||||||
VisitForControl(stmt->result_done(),
|
|
||||||
loop_statement.break_label(),
|
|
||||||
&result_not_done,
|
|
||||||
&result_not_done);
|
|
||||||
__ bind(&result_not_done);
|
|
||||||
|
|
||||||
// each = result.value
|
|
||||||
VisitForEffect(stmt->assign_each());
|
|
||||||
|
|
||||||
// Generate code for the body of the loop.
|
|
||||||
Visit(stmt->body());
|
|
||||||
|
|
||||||
// Check stack before looping.
|
|
||||||
PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
|
|
||||||
EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
|
|
||||||
__ jmp(loop_statement.continue_label());
|
|
||||||
|
|
||||||
// Exit and decrement the loop depth.
|
|
||||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
|
||||||
__ bind(loop_statement.break_label());
|
|
||||||
decrement_loop_depth();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
||||||
bool pretenure) {
|
bool pretenure) {
|
||||||
// Use the fast case closure allocation code that allocates in new
|
// Use the fast case closure allocation code that allocates in new
|
||||||
|
@ -1102,6 +1102,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
|
|
||||||
// Get the object to enumerate over. If the object is null or undefined, skip
|
// Get the object to enumerate over. If the object is null or undefined, skip
|
||||||
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
||||||
|
SetExpressionPosition(stmt->enumerable());
|
||||||
VisitForAccumulatorValue(stmt->enumerable());
|
VisitForAccumulatorValue(stmt->enumerable());
|
||||||
__ mov(a0, result_register()); // Result as param to InvokeBuiltin below.
|
__ mov(a0, result_register()); // Result as param to InvokeBuiltin below.
|
||||||
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
|
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
|
||||||
@ -1201,6 +1202,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
// Generate code for doing the condition check.
|
// Generate code for doing the condition check.
|
||||||
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
||||||
__ bind(&loop);
|
__ bind(&loop);
|
||||||
|
SetExpressionPosition(stmt->each());
|
||||||
|
|
||||||
// Load the current count to a0, load the length to a1.
|
// Load the current count to a0, load the length to a1.
|
||||||
__ lw(a0, MemOperand(sp, 0 * kPointerSize));
|
__ lw(a0, MemOperand(sp, 0 * kPointerSize));
|
||||||
__ lw(a1, MemOperand(sp, 1 * kPointerSize));
|
__ lw(a1, MemOperand(sp, 1 * kPointerSize));
|
||||||
@ -1270,48 +1273,6 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
|
|
||||||
Comment cmnt(masm_, "[ ForOfStatement");
|
|
||||||
SetStatementPosition(stmt);
|
|
||||||
|
|
||||||
Iteration loop_statement(this, stmt);
|
|
||||||
increment_loop_depth();
|
|
||||||
|
|
||||||
// var iterator = iterable[Symbol.iterator]();
|
|
||||||
VisitForEffect(stmt->assign_iterator());
|
|
||||||
|
|
||||||
// Loop entry.
|
|
||||||
__ bind(loop_statement.continue_label());
|
|
||||||
|
|
||||||
// result = iterator.next()
|
|
||||||
VisitForEffect(stmt->next_result());
|
|
||||||
|
|
||||||
// if (result.done) break;
|
|
||||||
Label result_not_done;
|
|
||||||
VisitForControl(stmt->result_done(),
|
|
||||||
loop_statement.break_label(),
|
|
||||||
&result_not_done,
|
|
||||||
&result_not_done);
|
|
||||||
__ bind(&result_not_done);
|
|
||||||
|
|
||||||
// each = result.value
|
|
||||||
VisitForEffect(stmt->assign_each());
|
|
||||||
|
|
||||||
// Generate code for the body of the loop.
|
|
||||||
Visit(stmt->body());
|
|
||||||
|
|
||||||
// Check stack before looping.
|
|
||||||
PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
|
|
||||||
EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
|
|
||||||
__ jmp(loop_statement.continue_label());
|
|
||||||
|
|
||||||
// Exit and decrement the loop depth.
|
|
||||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
|
||||||
__ bind(loop_statement.break_label());
|
|
||||||
decrement_loop_depth();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
||||||
bool pretenure) {
|
bool pretenure) {
|
||||||
// Use the fast case closure allocation code that allocates in new
|
// Use the fast case closure allocation code that allocates in new
|
||||||
|
@ -1097,6 +1097,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
|
|
||||||
// Get the object to enumerate over. If the object is null or undefined, skip
|
// Get the object to enumerate over. If the object is null or undefined, skip
|
||||||
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
||||||
|
SetExpressionPosition(stmt->enumerable());
|
||||||
VisitForAccumulatorValue(stmt->enumerable());
|
VisitForAccumulatorValue(stmt->enumerable());
|
||||||
__ mov(a0, result_register()); // Result as param to InvokeBuiltin below.
|
__ mov(a0, result_register()); // Result as param to InvokeBuiltin below.
|
||||||
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
|
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
|
||||||
@ -1196,6 +1197,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
// Generate code for doing the condition check.
|
// Generate code for doing the condition check.
|
||||||
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
||||||
__ bind(&loop);
|
__ bind(&loop);
|
||||||
|
SetExpressionPosition(stmt->each());
|
||||||
|
|
||||||
// Load the current count to a0, load the length to a1.
|
// Load the current count to a0, load the length to a1.
|
||||||
__ ld(a0, MemOperand(sp, 0 * kPointerSize));
|
__ ld(a0, MemOperand(sp, 0 * kPointerSize));
|
||||||
__ ld(a1, MemOperand(sp, 1 * kPointerSize));
|
__ ld(a1, MemOperand(sp, 1 * kPointerSize));
|
||||||
@ -1265,48 +1268,6 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
|
|
||||||
Comment cmnt(masm_, "[ ForOfStatement");
|
|
||||||
SetStatementPosition(stmt);
|
|
||||||
|
|
||||||
Iteration loop_statement(this, stmt);
|
|
||||||
increment_loop_depth();
|
|
||||||
|
|
||||||
// var iterator = iterable[Symbol.iterator]();
|
|
||||||
VisitForEffect(stmt->assign_iterator());
|
|
||||||
|
|
||||||
// Loop entry.
|
|
||||||
__ bind(loop_statement.continue_label());
|
|
||||||
|
|
||||||
// result = iterator.next()
|
|
||||||
VisitForEffect(stmt->next_result());
|
|
||||||
|
|
||||||
// if (result.done) break;
|
|
||||||
Label result_not_done;
|
|
||||||
VisitForControl(stmt->result_done(),
|
|
||||||
loop_statement.break_label(),
|
|
||||||
&result_not_done,
|
|
||||||
&result_not_done);
|
|
||||||
__ bind(&result_not_done);
|
|
||||||
|
|
||||||
// each = result.value
|
|
||||||
VisitForEffect(stmt->assign_each());
|
|
||||||
|
|
||||||
// Generate code for the body of the loop.
|
|
||||||
Visit(stmt->body());
|
|
||||||
|
|
||||||
// Check stack before looping.
|
|
||||||
PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
|
|
||||||
EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
|
|
||||||
__ jmp(loop_statement.continue_label());
|
|
||||||
|
|
||||||
// Exit and decrement the loop depth.
|
|
||||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
|
||||||
__ bind(loop_statement.break_label());
|
|
||||||
decrement_loop_depth();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
||||||
bool pretenure) {
|
bool pretenure) {
|
||||||
// Use the fast case closure allocation code that allocates in new
|
// Use the fast case closure allocation code that allocates in new
|
||||||
|
@ -2941,7 +2941,7 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
|
|||||||
// var iterator = subject[Symbol.iterator]();
|
// var iterator = subject[Symbol.iterator]();
|
||||||
assign_iterator = factory()->NewAssignment(
|
assign_iterator = factory()->NewAssignment(
|
||||||
Token::ASSIGN, factory()->NewVariableProxy(iterator),
|
Token::ASSIGN, factory()->NewVariableProxy(iterator),
|
||||||
GetIterator(subject, factory()), RelocInfo::kNoPosition);
|
GetIterator(subject, factory()), subject->position());
|
||||||
|
|
||||||
// var result = iterator.next();
|
// var result = iterator.next();
|
||||||
{
|
{
|
||||||
@ -2952,11 +2952,11 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
|
|||||||
iterator_proxy, next_literal, RelocInfo::kNoPosition);
|
iterator_proxy, next_literal, RelocInfo::kNoPosition);
|
||||||
ZoneList<Expression*>* next_arguments =
|
ZoneList<Expression*>* next_arguments =
|
||||||
new(zone()) ZoneList<Expression*>(0, zone());
|
new(zone()) ZoneList<Expression*>(0, zone());
|
||||||
Expression* next_call = factory()->NewCall(
|
Expression* next_call = factory()->NewCall(next_property, next_arguments,
|
||||||
next_property, next_arguments, RelocInfo::kNoPosition);
|
subject->position());
|
||||||
Expression* result_proxy = factory()->NewVariableProxy(result);
|
Expression* result_proxy = factory()->NewVariableProxy(result);
|
||||||
next_result = factory()->NewAssignment(
|
next_result = factory()->NewAssignment(Token::ASSIGN, result_proxy,
|
||||||
Token::ASSIGN, result_proxy, next_call, RelocInfo::kNoPosition);
|
next_call, subject->position());
|
||||||
}
|
}
|
||||||
|
|
||||||
// result.done
|
// result.done
|
||||||
@ -2975,8 +2975,8 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
|
|||||||
Expression* result_proxy = factory()->NewVariableProxy(result);
|
Expression* result_proxy = factory()->NewVariableProxy(result);
|
||||||
Expression* result_value = factory()->NewProperty(
|
Expression* result_value = factory()->NewProperty(
|
||||||
result_proxy, value_literal, RelocInfo::kNoPosition);
|
result_proxy, value_literal, RelocInfo::kNoPosition);
|
||||||
assign_each = factory()->NewAssignment(
|
assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value,
|
||||||
Token::ASSIGN, each, result_value, RelocInfo::kNoPosition);
|
each->position());
|
||||||
}
|
}
|
||||||
|
|
||||||
for_of->Initialize(each, subject, body,
|
for_of->Initialize(each, subject, body,
|
||||||
@ -3154,7 +3154,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
|||||||
// ForStatement ::
|
// ForStatement ::
|
||||||
// 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
|
// 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
|
||||||
|
|
||||||
int pos = peek_position();
|
int stmt_pos = peek_position();
|
||||||
Statement* init = NULL;
|
Statement* init = NULL;
|
||||||
ZoneList<const AstRawString*> let_bindings(1, zone());
|
ZoneList<const AstRawString*> let_bindings(1, zone());
|
||||||
|
|
||||||
@ -3177,19 +3177,20 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
|||||||
CHECK_OK);
|
CHECK_OK);
|
||||||
bool accept_OF = decl_props == kHasNoInitializers;
|
bool accept_OF = decl_props == kHasNoInitializers;
|
||||||
ForEachStatement::VisitMode mode;
|
ForEachStatement::VisitMode mode;
|
||||||
|
int each_pos = position();
|
||||||
|
|
||||||
if (name != NULL && CheckInOrOf(accept_OF, &mode)) {
|
if (name != NULL && CheckInOrOf(accept_OF, &mode)) {
|
||||||
Interface* interface =
|
Interface* interface =
|
||||||
is_const ? Interface::NewConst() : Interface::NewValue();
|
is_const ? Interface::NewConst() : Interface::NewValue();
|
||||||
ForEachStatement* loop =
|
ForEachStatement* loop =
|
||||||
factory()->NewForEachStatement(mode, labels, pos);
|
factory()->NewForEachStatement(mode, labels, stmt_pos);
|
||||||
Target target(&this->target_stack_, loop);
|
Target target(&this->target_stack_, loop);
|
||||||
|
|
||||||
Expression* enumerable = ParseExpression(true, CHECK_OK);
|
Expression* enumerable = ParseExpression(true, CHECK_OK);
|
||||||
Expect(Token::RPAREN, CHECK_OK);
|
Expect(Token::RPAREN, CHECK_OK);
|
||||||
|
|
||||||
VariableProxy* each =
|
VariableProxy* each =
|
||||||
scope_->NewUnresolved(factory(), name, interface);
|
scope_->NewUnresolved(factory(), name, interface, each_pos);
|
||||||
Statement* body = ParseStatement(NULL, CHECK_OK);
|
Statement* body = ParseStatement(NULL, CHECK_OK);
|
||||||
InitializeForEachStatement(loop, each, enumerable, body);
|
InitializeForEachStatement(loop, each, enumerable, body);
|
||||||
Block* result =
|
Block* result =
|
||||||
@ -3216,6 +3217,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
|||||||
bool accept_IN = name != NULL && decl_props != kHasInitializers;
|
bool accept_IN = name != NULL && decl_props != kHasInitializers;
|
||||||
bool accept_OF = decl_props == kHasNoInitializers;
|
bool accept_OF = decl_props == kHasNoInitializers;
|
||||||
ForEachStatement::VisitMode mode;
|
ForEachStatement::VisitMode mode;
|
||||||
|
int each_pos = position();
|
||||||
|
|
||||||
if (accept_IN && CheckInOrOf(accept_OF, &mode)) {
|
if (accept_IN && CheckInOrOf(accept_OF, &mode)) {
|
||||||
// Rewrite a for-in statement of the form
|
// Rewrite a for-in statement of the form
|
||||||
@ -3235,9 +3237,9 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
|||||||
// implementing stack allocated block scoped variables.
|
// implementing stack allocated block scoped variables.
|
||||||
Variable* temp = scope_->DeclarationScope()->NewTemporary(
|
Variable* temp = scope_->DeclarationScope()->NewTemporary(
|
||||||
ast_value_factory()->dot_for_string());
|
ast_value_factory()->dot_for_string());
|
||||||
VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
|
VariableProxy* temp_proxy = factory()->NewVariableProxy(temp, each_pos);
|
||||||
ForEachStatement* loop =
|
ForEachStatement* loop =
|
||||||
factory()->NewForEachStatement(mode, labels, pos);
|
factory()->NewForEachStatement(mode, labels, stmt_pos);
|
||||||
Target target(&this->target_stack_, loop);
|
Target target(&this->target_stack_, loop);
|
||||||
|
|
||||||
// The expression does not see the loop variable.
|
// The expression does not see the loop variable.
|
||||||
@ -3246,7 +3248,8 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
|||||||
scope_ = for_scope;
|
scope_ = for_scope;
|
||||||
Expect(Token::RPAREN, CHECK_OK);
|
Expect(Token::RPAREN, CHECK_OK);
|
||||||
|
|
||||||
VariableProxy* each = scope_->NewUnresolved(factory(), name);
|
VariableProxy* each = scope_->NewUnresolved(
|
||||||
|
factory(), name, Interface::NewValue(), each_pos);
|
||||||
Statement* body = ParseStatement(NULL, CHECK_OK);
|
Statement* body = ParseStatement(NULL, CHECK_OK);
|
||||||
Block* body_block =
|
Block* body_block =
|
||||||
factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
|
factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
|
||||||
@ -3280,7 +3283,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
|||||||
expression, lhs_location, "invalid_lhs_in_for", CHECK_OK);
|
expression, lhs_location, "invalid_lhs_in_for", CHECK_OK);
|
||||||
|
|
||||||
ForEachStatement* loop =
|
ForEachStatement* loop =
|
||||||
factory()->NewForEachStatement(mode, labels, pos);
|
factory()->NewForEachStatement(mode, labels, stmt_pos);
|
||||||
Target target(&this->target_stack_, loop);
|
Target target(&this->target_stack_, loop);
|
||||||
|
|
||||||
Expression* enumerable = ParseExpression(true, CHECK_OK);
|
Expression* enumerable = ParseExpression(true, CHECK_OK);
|
||||||
@ -3296,14 +3299,13 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
|||||||
return loop;
|
return loop;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
init = factory()->NewExpressionStatement(
|
init = factory()->NewExpressionStatement(expression, position());
|
||||||
expression, RelocInfo::kNoPosition);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Standard 'for' loop
|
// Standard 'for' loop
|
||||||
ForStatement* loop = factory()->NewForStatement(labels, pos);
|
ForStatement* loop = factory()->NewForStatement(labels, stmt_pos);
|
||||||
Target target(&this->target_stack_, loop);
|
Target target(&this->target_stack_, loop);
|
||||||
|
|
||||||
// Parsed initializer at this point.
|
// Parsed initializer at this point.
|
||||||
@ -3326,8 +3328,9 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
|||||||
|
|
||||||
Statement* next = NULL;
|
Statement* next = NULL;
|
||||||
if (peek() != Token::RPAREN) {
|
if (peek() != Token::RPAREN) {
|
||||||
|
int next_pos = position();
|
||||||
Expression* exp = ParseExpression(true, CHECK_OK);
|
Expression* exp = ParseExpression(true, CHECK_OK);
|
||||||
next = factory()->NewExpressionStatement(exp, RelocInfo::kNoPosition);
|
next = factory()->NewExpressionStatement(exp, next_pos);
|
||||||
}
|
}
|
||||||
Expect(Token::RPAREN, CHECK_OK);
|
Expect(Token::RPAREN, CHECK_OK);
|
||||||
|
|
||||||
|
@ -1067,6 +1067,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
|
|
||||||
// Get the object to enumerate over. If the object is null or undefined, skip
|
// Get the object to enumerate over. If the object is null or undefined, skip
|
||||||
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
||||||
|
SetExpressionPosition(stmt->enumerable());
|
||||||
VisitForAccumulatorValue(stmt->enumerable());
|
VisitForAccumulatorValue(stmt->enumerable());
|
||||||
__ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
|
__ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
|
||||||
__ j(equal, &exit);
|
__ j(equal, &exit);
|
||||||
@ -1170,6 +1171,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
// Generate code for doing the condition check.
|
// Generate code for doing the condition check.
|
||||||
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
||||||
__ bind(&loop);
|
__ bind(&loop);
|
||||||
|
SetExpressionPosition(stmt->each());
|
||||||
|
|
||||||
__ movp(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index.
|
__ movp(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index.
|
||||||
__ cmpp(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length.
|
__ cmpp(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length.
|
||||||
__ j(above_equal, loop_statement.break_label());
|
__ j(above_equal, loop_statement.break_label());
|
||||||
@ -1239,48 +1242,6 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
|
|
||||||
Comment cmnt(masm_, "[ ForOfStatement");
|
|
||||||
SetStatementPosition(stmt);
|
|
||||||
|
|
||||||
Iteration loop_statement(this, stmt);
|
|
||||||
increment_loop_depth();
|
|
||||||
|
|
||||||
// var iterator = iterable[Symbol.iterator]();
|
|
||||||
VisitForEffect(stmt->assign_iterator());
|
|
||||||
|
|
||||||
// Loop entry.
|
|
||||||
__ bind(loop_statement.continue_label());
|
|
||||||
|
|
||||||
// result = iterator.next()
|
|
||||||
VisitForEffect(stmt->next_result());
|
|
||||||
|
|
||||||
// if (result.done) break;
|
|
||||||
Label result_not_done;
|
|
||||||
VisitForControl(stmt->result_done(),
|
|
||||||
loop_statement.break_label(),
|
|
||||||
&result_not_done,
|
|
||||||
&result_not_done);
|
|
||||||
__ bind(&result_not_done);
|
|
||||||
|
|
||||||
// each = result.value
|
|
||||||
VisitForEffect(stmt->assign_each());
|
|
||||||
|
|
||||||
// Generate code for the body of the loop.
|
|
||||||
Visit(stmt->body());
|
|
||||||
|
|
||||||
// Check stack before looping.
|
|
||||||
PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
|
|
||||||
EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
|
|
||||||
__ jmp(loop_statement.continue_label());
|
|
||||||
|
|
||||||
// Exit and decrement the loop depth.
|
|
||||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
|
||||||
__ bind(loop_statement.break_label());
|
|
||||||
decrement_loop_depth();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
||||||
bool pretenure) {
|
bool pretenure) {
|
||||||
// Use the fast case closure allocation code that allocates in new
|
// Use the fast case closure allocation code that allocates in new
|
||||||
|
@ -1034,6 +1034,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
|
|
||||||
// Get the object to enumerate over. If the object is null or undefined, skip
|
// Get the object to enumerate over. If the object is null or undefined, skip
|
||||||
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
||||||
|
SetExpressionPosition(stmt->enumerable());
|
||||||
VisitForAccumulatorValue(stmt->enumerable());
|
VisitForAccumulatorValue(stmt->enumerable());
|
||||||
__ cmp(eax, isolate()->factory()->undefined_value());
|
__ cmp(eax, isolate()->factory()->undefined_value());
|
||||||
__ j(equal, &exit);
|
__ j(equal, &exit);
|
||||||
@ -1128,6 +1129,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
// Generate code for doing the condition check.
|
// Generate code for doing the condition check.
|
||||||
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
||||||
__ bind(&loop);
|
__ bind(&loop);
|
||||||
|
SetExpressionPosition(stmt->each());
|
||||||
|
|
||||||
__ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index.
|
__ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index.
|
||||||
__ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length.
|
__ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length.
|
||||||
__ j(above_equal, loop_statement.break_label());
|
__ j(above_equal, loop_statement.break_label());
|
||||||
@ -1194,48 +1197,6 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
|
|
||||||
Comment cmnt(masm_, "[ ForOfStatement");
|
|
||||||
SetStatementPosition(stmt);
|
|
||||||
|
|
||||||
Iteration loop_statement(this, stmt);
|
|
||||||
increment_loop_depth();
|
|
||||||
|
|
||||||
// var iterator = iterable[Symbol.iterator]();
|
|
||||||
VisitForEffect(stmt->assign_iterator());
|
|
||||||
|
|
||||||
// Loop entry.
|
|
||||||
__ bind(loop_statement.continue_label());
|
|
||||||
|
|
||||||
// result = iterator.next()
|
|
||||||
VisitForEffect(stmt->next_result());
|
|
||||||
|
|
||||||
// if (result.done) break;
|
|
||||||
Label result_not_done;
|
|
||||||
VisitForControl(stmt->result_done(),
|
|
||||||
loop_statement.break_label(),
|
|
||||||
&result_not_done,
|
|
||||||
&result_not_done);
|
|
||||||
__ bind(&result_not_done);
|
|
||||||
|
|
||||||
// each = result.value
|
|
||||||
VisitForEffect(stmt->assign_each());
|
|
||||||
|
|
||||||
// Generate code for the body of the loop.
|
|
||||||
Visit(stmt->body());
|
|
||||||
|
|
||||||
// Check stack before looping.
|
|
||||||
PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
|
|
||||||
EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
|
|
||||||
__ jmp(loop_statement.continue_label());
|
|
||||||
|
|
||||||
// Exit and decrement the loop depth.
|
|
||||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
|
||||||
__ bind(loop_statement.break_label());
|
|
||||||
decrement_loop_depth();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
||||||
bool pretenure) {
|
bool pretenure) {
|
||||||
// Use the fast case closure allocation code that allocates in new
|
// Use the fast case closure allocation code that allocates in new
|
||||||
|
@ -2860,7 +2860,7 @@ TEST(DebugStepKeyedLoadLoop) {
|
|||||||
foo->Call(env->Global(), kArgc, args);
|
foo->Call(env->Global(), kArgc, args);
|
||||||
|
|
||||||
// With stepping all break locations are hit.
|
// With stepping all break locations are hit.
|
||||||
CHECK_EQ(35, break_point_hit_count);
|
CHECK_EQ(45, break_point_hit_count);
|
||||||
|
|
||||||
v8::Debug::SetDebugEventListener(NULL);
|
v8::Debug::SetDebugEventListener(NULL);
|
||||||
CheckDebuggerUnloaded();
|
CheckDebuggerUnloaded();
|
||||||
@ -2908,7 +2908,7 @@ TEST(DebugStepKeyedStoreLoop) {
|
|||||||
foo->Call(env->Global(), kArgc, args);
|
foo->Call(env->Global(), kArgc, args);
|
||||||
|
|
||||||
// With stepping all break locations are hit.
|
// With stepping all break locations are hit.
|
||||||
CHECK_EQ(34, break_point_hit_count);
|
CHECK_EQ(44, break_point_hit_count);
|
||||||
|
|
||||||
v8::Debug::SetDebugEventListener(NULL);
|
v8::Debug::SetDebugEventListener(NULL);
|
||||||
CheckDebuggerUnloaded();
|
CheckDebuggerUnloaded();
|
||||||
@ -2952,7 +2952,7 @@ TEST(DebugStepNamedLoadLoop) {
|
|||||||
foo->Call(env->Global(), 0, NULL);
|
foo->Call(env->Global(), 0, NULL);
|
||||||
|
|
||||||
// With stepping all break locations are hit.
|
// With stepping all break locations are hit.
|
||||||
CHECK_EQ(55, break_point_hit_count);
|
CHECK_EQ(65, break_point_hit_count);
|
||||||
|
|
||||||
v8::Debug::SetDebugEventListener(NULL);
|
v8::Debug::SetDebugEventListener(NULL);
|
||||||
CheckDebuggerUnloaded();
|
CheckDebuggerUnloaded();
|
||||||
@ -2995,9 +2995,7 @@ static void DoDebugStepNamedStoreLoop(int expected) {
|
|||||||
|
|
||||||
|
|
||||||
// Test of the stepping mechanism for named load in a loop.
|
// Test of the stepping mechanism for named load in a loop.
|
||||||
TEST(DebugStepNamedStoreLoop) {
|
TEST(DebugStepNamedStoreLoop) { DoDebugStepNamedStoreLoop(34); }
|
||||||
DoDebugStepNamedStoreLoop(24);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Test the stepping mechanism with different ICs.
|
// Test the stepping mechanism with different ICs.
|
||||||
@ -3330,14 +3328,14 @@ TEST(DebugStepFor) {
|
|||||||
break_point_hit_count = 0;
|
break_point_hit_count = 0;
|
||||||
v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
|
v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
|
||||||
foo->Call(env->Global(), argc, argv_10);
|
foo->Call(env->Global(), argc, argv_10);
|
||||||
CHECK_EQ(23, break_point_hit_count);
|
CHECK_EQ(45, break_point_hit_count);
|
||||||
|
|
||||||
// Looping 100 times.
|
// Looping 100 times.
|
||||||
step_action = StepIn;
|
step_action = StepIn;
|
||||||
break_point_hit_count = 0;
|
break_point_hit_count = 0;
|
||||||
v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
|
v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
|
||||||
foo->Call(env->Global(), argc, argv_100);
|
foo->Call(env->Global(), argc, argv_100);
|
||||||
CHECK_EQ(203, break_point_hit_count);
|
CHECK_EQ(405, break_point_hit_count);
|
||||||
|
|
||||||
// Get rid of the debug event listener.
|
// Get rid of the debug event listener.
|
||||||
v8::Debug::SetDebugEventListener(NULL);
|
v8::Debug::SetDebugEventListener(NULL);
|
||||||
@ -3381,7 +3379,7 @@ TEST(DebugStepForContinue) {
|
|||||||
v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
|
v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
|
||||||
result = foo->Call(env->Global(), argc, argv_10);
|
result = foo->Call(env->Global(), argc, argv_10);
|
||||||
CHECK_EQ(5, result->Int32Value());
|
CHECK_EQ(5, result->Int32Value());
|
||||||
CHECK_EQ(52, break_point_hit_count);
|
CHECK_EQ(62, break_point_hit_count);
|
||||||
|
|
||||||
// Looping 100 times.
|
// Looping 100 times.
|
||||||
step_action = StepIn;
|
step_action = StepIn;
|
||||||
@ -3389,7 +3387,7 @@ TEST(DebugStepForContinue) {
|
|||||||
v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
|
v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
|
||||||
result = foo->Call(env->Global(), argc, argv_100);
|
result = foo->Call(env->Global(), argc, argv_100);
|
||||||
CHECK_EQ(50, result->Int32Value());
|
CHECK_EQ(50, result->Int32Value());
|
||||||
CHECK_EQ(457, break_point_hit_count);
|
CHECK_EQ(557, break_point_hit_count);
|
||||||
|
|
||||||
// Get rid of the debug event listener.
|
// Get rid of the debug event listener.
|
||||||
v8::Debug::SetDebugEventListener(NULL);
|
v8::Debug::SetDebugEventListener(NULL);
|
||||||
@ -3434,7 +3432,7 @@ TEST(DebugStepForBreak) {
|
|||||||
v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
|
v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
|
||||||
result = foo->Call(env->Global(), argc, argv_10);
|
result = foo->Call(env->Global(), argc, argv_10);
|
||||||
CHECK_EQ(9, result->Int32Value());
|
CHECK_EQ(9, result->Int32Value());
|
||||||
CHECK_EQ(55, break_point_hit_count);
|
CHECK_EQ(64, break_point_hit_count);
|
||||||
|
|
||||||
// Looping 100 times.
|
// Looping 100 times.
|
||||||
step_action = StepIn;
|
step_action = StepIn;
|
||||||
@ -3442,7 +3440,7 @@ TEST(DebugStepForBreak) {
|
|||||||
v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
|
v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
|
||||||
result = foo->Call(env->Global(), argc, argv_100);
|
result = foo->Call(env->Global(), argc, argv_100);
|
||||||
CHECK_EQ(99, result->Int32Value());
|
CHECK_EQ(99, result->Int32Value());
|
||||||
CHECK_EQ(505, break_point_hit_count);
|
CHECK_EQ(604, break_point_hit_count);
|
||||||
|
|
||||||
// Get rid of the debug event listener.
|
// Get rid of the debug event listener.
|
||||||
v8::Debug::SetDebugEventListener(NULL);
|
v8::Debug::SetDebugEventListener(NULL);
|
||||||
@ -3473,7 +3471,7 @@ TEST(DebugStepForIn) {
|
|||||||
step_action = StepIn;
|
step_action = StepIn;
|
||||||
break_point_hit_count = 0;
|
break_point_hit_count = 0;
|
||||||
foo->Call(env->Global(), 0, NULL);
|
foo->Call(env->Global(), 0, NULL);
|
||||||
CHECK_EQ(6, break_point_hit_count);
|
CHECK_EQ(8, break_point_hit_count);
|
||||||
|
|
||||||
// Create a function for testing stepping. Run it to allow it to get
|
// Create a function for testing stepping. Run it to allow it to get
|
||||||
// optimized.
|
// optimized.
|
||||||
@ -3490,7 +3488,7 @@ TEST(DebugStepForIn) {
|
|||||||
step_action = StepIn;
|
step_action = StepIn;
|
||||||
break_point_hit_count = 0;
|
break_point_hit_count = 0;
|
||||||
foo->Call(env->Global(), 0, NULL);
|
foo->Call(env->Global(), 0, NULL);
|
||||||
CHECK_EQ(8, break_point_hit_count);
|
CHECK_EQ(10, break_point_hit_count);
|
||||||
|
|
||||||
// Get rid of the debug event listener.
|
// Get rid of the debug event listener.
|
||||||
v8::Debug::SetDebugEventListener(NULL);
|
v8::Debug::SetDebugEventListener(NULL);
|
||||||
|
@ -68,7 +68,7 @@ bp1 = Debug.setBreakPoint(f, 1);
|
|||||||
state = 0;
|
state = 0;
|
||||||
result = -1;
|
result = -1;
|
||||||
f();
|
f();
|
||||||
assertEquals(499, result);
|
assertEquals(332, result);
|
||||||
|
|
||||||
// Check that performing 1000 steps with a break point on the statement in the
|
// Check that performing 1000 steps with a break point on the statement in the
|
||||||
// for loop (line 2) will only make i 0 as a real break point breaks even when
|
// for loop (line 2) will only make i 0 as a real break point breaks even when
|
||||||
|
116
test/mjsunit/es6/debug-stepnext-for.js
Normal file
116
test/mjsunit/es6/debug-stepnext-for.js
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
// Flags: --expose-debug-as debug --harmony
|
||||||
|
|
||||||
|
Debug = debug.Debug;
|
||||||
|
var break_count = 0
|
||||||
|
var exception = null;
|
||||||
|
var log = []
|
||||||
|
|
||||||
|
var s = 0;
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
|
function f() {
|
||||||
|
"use strict";
|
||||||
|
debugger; // Break a
|
||||||
|
var j; // Break b
|
||||||
|
|
||||||
|
for (var i in null) { // Break c
|
||||||
|
s += a[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j in null) { // Break d
|
||||||
|
s += a[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i in a) { // Break e
|
||||||
|
s += a[i]; // Break E
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j in a) { // Break f
|
||||||
|
s += a[j]; // Break F
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i in a) { // Break g
|
||||||
|
s += a[i]; // Break G
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i of a) { // Break h
|
||||||
|
s += i; // Break H
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j of a) { // Break i
|
||||||
|
s += j; // Break I
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i of a) { // Break j
|
||||||
|
s += i; // Break J
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < 3; i++) { // Break k
|
||||||
|
s += a[i]; // Break K
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < 3; j++) { // Break l
|
||||||
|
s += a[j]; // Break L
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(yangguo): add test case for for-let.
|
||||||
|
} // Break y
|
||||||
|
|
||||||
|
function listener(event, exec_state, event_data, data) {
|
||||||
|
if (event != Debug.DebugEvent.Break) return;
|
||||||
|
try {
|
||||||
|
var line = exec_state.frame(0).sourceLineText();
|
||||||
|
var col = exec_state.frame(0).sourceColumn();
|
||||||
|
print(line);
|
||||||
|
var match = line.match(/\/\/ Break (\w)$/);
|
||||||
|
assertEquals(2, match.length);
|
||||||
|
log.push(match[1] + col);
|
||||||
|
exec_state.prepareStep(Debug.StepAction.StepNext, 1);
|
||||||
|
break_count++;
|
||||||
|
} catch (e) {
|
||||||
|
exception = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.setListener(listener);
|
||||||
|
f();
|
||||||
|
Debug.setListener(null); // Break z
|
||||||
|
|
||||||
|
print(JSON.stringify(log));
|
||||||
|
// The let declaration differs from var in that the loop variable
|
||||||
|
// is declared in every iteration.
|
||||||
|
var expected = [
|
||||||
|
// Entry
|
||||||
|
"a2","b2",
|
||||||
|
// Empty for-in-var: var decl, get enumerable
|
||||||
|
"c7","c16",
|
||||||
|
// Empty for-in: get enumerable
|
||||||
|
"d12",
|
||||||
|
// For-in-var: var decl, get enumerable, assign, body, assign, body, ...
|
||||||
|
"e7","e16","e11","E4","e11","E4","e11","E4","e11",
|
||||||
|
// For-in: get enumerable, assign, body, assign, body, ...
|
||||||
|
"f12","f7","F4","f7","F4","f7","F4","f7",
|
||||||
|
// For-in-let: get enumerable, next, new let, body, next, new let, ...
|
||||||
|
"g16","g11","g7","G4","g11","g7","G4","g11","g7","G4","g11",
|
||||||
|
// For-of-var: var decl, next(), body, next(), body, ...
|
||||||
|
"h7","h16","H4","h16","H4","h16","H4","h16",
|
||||||
|
// For-of: next(), body, next(), body, ...
|
||||||
|
"i12","I4","i12","I4","i12","I4","i12",
|
||||||
|
// For-of-let: next(), new let, body, next(), new let, ...
|
||||||
|
"j16","j7","J4","j16","j7","J4","j16","j7","J4","j16",
|
||||||
|
// For-var: var decl, condition, body, next, condition, body, ...
|
||||||
|
"k7","k20","K4","k23","k20","K4","k23","k20","K4","k23","k20",
|
||||||
|
// For: init, condition, body, next, condition, body, ...
|
||||||
|
"l11","l16","L4","l19","l16","L4","l19","l16","L4","l19","l16",
|
||||||
|
// Exit.
|
||||||
|
"y0","z0",
|
||||||
|
]
|
||||||
|
|
||||||
|
assertArrayEquals(expected, log);
|
||||||
|
assertEquals(48, s);
|
||||||
|
assertNull(exception);
|
Loading…
Reference in New Issue
Block a user