Revision: 4998
Author: [email protected]
Date: Thu Jul 1 06:19:32 2010
Log: X64: Made simpler version of fast-smi-loop code.
It avoids the overflow check on the increment.
Review URL: http://codereview.chromium.org/2835030
http://code.google.com/p/v8/source/detail?r=4998
Modified:
/branches/bleeding_edge/src/x64/codegen-x64.cc
/branches/bleeding_edge/src/x64/codegen-x64.h
/branches/bleeding_edge/src/x64/virtual-frame-x64.h
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc Wed Jun 30 06:39:03 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc Thu Jul 1 06:19:32 2010
@@ -1598,6 +1598,120 @@
__ AbortIfNotSmi(var.reg());
}
}
+
+
+void CodeGenerator::GenerateFastSmiLoop(ForStatement* node) {
+ // A fast smi loop is a for loop with an initializer
+ // that is a simple assignment of a smi to a stack variable,
+ // a test that is a simple test of that variable against a smi constant,
+ // and a step that is a increment/decrement of the variable, and
+ // where the variable isn't modified in the loop body.
+ // This guarantees that the variable is always a smi.
+
+ Variable* loop_var = node->loop_variable();
+ Smi* initial_value = *Handle<Smi>::cast(node->init()
+ ->StatementAsSimpleAssignment()->value()->AsLiteral()->handle());
+ Smi* limit_value = *Handle<Smi>::cast(
+ node->cond()->AsCompareOperation()->right()->AsLiteral()->handle());
+ Token::Value compare_op =
+ node->cond()->AsCompareOperation()->op();
+ bool increments =
+ node->next()->StatementAsCountOperation()->op() == Token::INC;
+
+ // Check that the condition isn't initially false.
+ bool initially_false = false;
+ int initial_int_value = initial_value->value();
+ int limit_int_value = limit_value->value();
+ switch (compare_op) {
+ case Token::LT:
+ initially_false = initial_int_value >= limit_int_value;
+ break;
+ case Token::LTE:
+ initially_false = initial_int_value > limit_int_value;
+ break;
+ case Token::GT:
+ initially_false = initial_int_value <= limit_int_value;
+ break;
+ case Token::GTE:
+ initially_false = initial_int_value < limit_int_value;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ if (initially_false) return;
+
+ // Only check loop condition at the end.
+
+ Visit(node->init());
+
+ JumpTarget loop(JumpTarget::BIDIRECTIONAL);
+
+ IncrementLoopNesting();
+ loop.Bind();
+
+ // Set number type of the loop variable to smi.
+ CheckStack(); // TODO(1222600): ignore if body contains calls.
+
+ SetTypeForStackSlot(loop_var->slot(), TypeInfo::Smi());
+ Visit(node->body());
+
+ if (node->continue_target()->is_linked()) {
+ node->continue_target()->Bind();
+ }
+
+ if (has_valid_frame()) {
+ CodeForStatementPosition(node);
+ Slot* loop_var_slot = loop_var->slot();
+ if (loop_var_slot->type() == Slot::LOCAL) {
+ frame_->PushLocalAt(loop_var_slot->index());
+ } else {
+ ASSERT(loop_var_slot->type() == Slot::PARAMETER);
+ frame_->PushParameterAt(loop_var_slot->index());
+ }
+ Result loop_var_result = frame_->Pop();
+ if (!loop_var_result.is_register()) {
+ loop_var_result.ToRegister();
+ }
+
+ if (increments) {
+ __ SmiAddConstant(loop_var_result.reg(),
+ loop_var_result.reg(),
+ Smi::FromInt(1));
+ } else {
+ __ SmiSubConstant(loop_var_result.reg(),
+ loop_var_result.reg(),
+ Smi::FromInt(1));
+ }
+
+ {
+ __ SmiCompare(loop_var_result.reg(), limit_value);
+ Condition condition;
+ switch (compare_op) {
+ case Token::LT:
+ condition = less;
+ break;
+ case Token::LTE:
+ condition = less_equal;
+ break;
+ case Token::GT:
+ condition = greater;
+ break;
+ case Token::GTE:
+ condition = greater_equal;
+ break;
+ default:
+ condition = never;
+ UNREACHABLE();
+ }
+ loop.Branch(condition);
+ }
+ loop_var_result.Unuse();
+ }
+ if (node->break_target()->is_linked()) {
+ node->break_target()->Bind();
+ }
+ DecrementLoopNesting();
+}
void CodeGenerator::VisitForStatement(ForStatement* node) {
@@ -1605,6 +1719,11 @@
Comment cmnt(masm_, "[ ForStatement");
CodeForStatementPosition(node);
+ if (node->is_fast_smi_loop()) {
+ GenerateFastSmiLoop(node);
+ return;
+ }
+
// Compile the init expression if present.
if (node->init() != NULL) {
Visit(node->init());
@@ -1693,16 +1812,6 @@
}
CheckStack(); // TODO(1222600): ignore if body contains calls.
-
- // We know that the loop index is a smi if it is not modified in the
- // loop body and it is checked against a constant limit in the loop
- // condition. In this case, we reset the static type information of the
- // loop index to smi before compiling the body, the update expression,
and
- // the bottom check of the loop condition.
- if (node->is_fast_smi_loop()) {
- // Set number type of the loop variable to smi.
- SetTypeForStackSlot(node->loop_variable()->slot(), TypeInfo::Smi());
- }
Visit(node->body());
@@ -1722,13 +1831,6 @@
Visit(node->next());
}
}
-
- // Set the type of the loop variable to smi before compiling the test
- // expression if we are in a fast smi loop condition.
- if (node->is_fast_smi_loop() && has_valid_frame()) {
- // Set number type of the loop variable to smi.
- SetTypeForStackSlot(node->loop_variable()->slot(), TypeInfo::Smi());
- }
// Based on the condition analysis, compile the backward jump as
// necessary.
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.h Thu Jun 10 07:37:49 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.h Thu Jul 1 06:19:32 2010
@@ -393,6 +393,9 @@
// target (which can not be done more than once).
void GenerateReturnSequence(Result* return_value);
+ // Generate code for a fast smi loop.
+ void GenerateFastSmiLoop(ForStatement* node);
+
// Returns the arguments allocation mode.
ArgumentsAllocationMode ArgumentsMode();
=======================================
--- /branches/bleeding_edge/src/x64/virtual-frame-x64.h Thu Jun 24 02:03:49
2010
+++ /branches/bleeding_edge/src/x64/virtual-frame-x64.h Thu Jul 1 06:19:32
2010
@@ -387,6 +387,13 @@
// Duplicate the top element of the frame.
void Dup() { PushFrameSlotAt(element_count() - 1); }
+
+ // Duplicate the n'th element from the top of the frame.
+ // Dup(1) is equivalent to Dup().
+ void Dup(int n) {
+ ASSERT(n > 0);
+ PushFrameSlotAt(element_count() - n);
+ }
// Pop an element from the top of the expression stack. Returns a
// Result, which may be a constant or a register.
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev