Author: [email protected]
Date: Tue Feb 24 04:28:43 2009
New Revision: 1346
Modified:
branches/experimental/toiger/src/codegen-arm.cc
branches/experimental/toiger/src/codegen-ia32.cc
branches/experimental/toiger/src/codegen.cc
branches/experimental/toiger/test/mjsunit/compare-constants.js
Log:
Experimental: fix two issues with ARM fast (jump table) switches.
(1) do not emit the jump table twice, (2) do bind the break target.
Review URL: http://codereview.chromium.org/28066
Modified: branches/experimental/toiger/src/codegen-arm.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-arm.cc (original)
+++ branches/experimental/toiger/src/codegen-arm.cc Tue Feb 24 04:28:43 2009
@@ -1448,18 +1448,25 @@
Vector<Label*> case_targets,
Vector<Label> case_labels) {
VirtualFrame::SpilledScope spilled_scope(this);
- ASSERT(kSmiTag == 0 && kSmiTagSize <= 2);
+ JumpTarget setup_default(this);
+ JumpTarget is_smi(this);
+ // A non-null default label pointer indicates a default case among
+ // the case labels. Otherwise we use the break target as a
+ // "default" for failure to hit the jump table.
+ JumpTarget* default_target =
+ (default_label == NULL) ? node->break_target() : &setup_default;
+
+ ASSERT(kSmiTag == 0 && kSmiTagSize <= 2);
frame_->EmitPop(r0);
// Test for a Smi value in a HeapNumber.
- JumpTarget is_smi(this);
__ tst(r0, Operand(kSmiTagMask));
is_smi.Branch(eq);
__ ldr(r1, MemOperand(r0, HeapObject::kMapOffset - kHeapObjectTag));
__ ldrb(r1, MemOperand(r1, Map::kInstanceTypeOffset - kHeapObjectTag));
__ cmp(r1, Operand(HEAP_NUMBER_TYPE));
- __ b(ne, default_label);
+ default_target->Branch(ne);
frame_->EmitPush(r0);
frame_->CallRuntime(Runtime::kNumberToSmi, 1);
is_smi.Bind();
@@ -1479,17 +1486,30 @@
}
}
__ tst(r0, Operand(0x80000000 | kSmiTagMask));
- __ b(ne, default_label);
+ default_target->Branch(ne);
__ cmp(r0, Operand(Smi::FromInt(range)));
- __ b(ge, default_label);
+ default_target->Branch(ge);
+ VirtualFrame* start_frame = new VirtualFrame(frame_);
__ SmiJumpTable(r0, case_targets);
- VirtualFrame* start_frame = new VirtualFrame(frame_);
- // Table containing branch operations.
- for (int i = 0; i < range; i++) {
- __ jmp(case_targets[i]);
- }
GenerateFastCaseSwitchCases(node, case_labels, start_frame);
+
+ // If there was a default case among the case labels, we need to
+ // emit code to jump to it from the default target used for failure
+ // to hit the jump table.
+ if (default_label != NULL) {
+ if (has_valid_frame()) {
+ node->break_target()->Jump();
+ }
+ setup_default.Bind();
+ frame_->MergeTo(start_frame);
+ __ b(default_label);
+ DeleteFrame();
+ }
+ if (node->break_target()->is_linked()) {
+ node->break_target()->Bind();
+ }
+
delete start_frame;
}
@@ -1513,7 +1533,7 @@
JumpTarget next_test(this);
JumpTarget fall_through(this);
JumpTarget default_entry(this);
- JumpTarget default_exit(this);
+ JumpTarget default_exit(this, JumpTarget::BIDIRECTIONAL);
ZoneList<CaseClause*>* cases = node->cases();
int length = cases->length();
CaseClause* default_clause = NULL;
Modified: branches/experimental/toiger/src/codegen-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.cc (original)
+++ branches/experimental/toiger/src/codegen-ia32.cc Tue Feb 24 04:28:43
2009
@@ -2000,13 +2000,17 @@
// If there was a default case, we need to emit the code to match it.
if (default_label != NULL) {
- node->break_target()->Jump();
+ if (has_valid_frame()) {
+ node->break_target()->Jump();
+ }
setup_default.Bind();
frame_->MergeTo(start_frame);
__ jmp(default_label);
DeleteFrame();
}
- node->break_target()->Bind();
+ if (node->break_target()->is_linked()) {
+ node->break_target()->Bind();
+ }
for (int i = 0, entry_pos = table_start.pos();
i < range;
Modified: branches/experimental/toiger/src/codegen.cc
==============================================================================
--- branches/experimental/toiger/src/codegen.cc (original)
+++ branches/experimental/toiger/src/codegen.cc Tue Feb 24 04:28:43 2009
@@ -453,19 +453,19 @@
for (int i = 0; i < length; i++) {
Comment cmnt(masm(), "[ Case clause");
- masm()->bind(&case_labels[i]);
- VisitStatements(cases->at(i)->statements());
- // If control flow did not fall off the end of the case statement,
- // we restore the expected frame for the next iteration (or exit
- // of the loop). Otherwise we have to generate merge code to
- // expectation at the next case.
+ // We may not have a virtual frame if control flow did not fall
+ // off the end of the previous case. In that case, use the start
+ // frame. Otherwise, we have to merge the existing one to the
+ // start frame as part of the previous case.
if (!has_valid_frame()) {
RegisterFile non_frame_registers = RegisterAllocator::Reserved();
SetFrame(new VirtualFrame(start_frame), &non_frame_registers);
} else {
frame_->MergeTo(start_frame);
}
+ masm()->bind(&case_labels[i]);
+ VisitStatements(cases->at(i)->statements());
}
}
Modified: branches/experimental/toiger/test/mjsunit/compare-constants.js
==============================================================================
--- branches/experimental/toiger/test/mjsunit/compare-constants.js
(original)
+++ branches/experimental/toiger/test/mjsunit/compare-constants.js Tue Feb
24 04:28:43 2009
@@ -25,13 +25,12 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Test comparison operations that involve one or two constant Smis.
+// Test comparison operations that involve one or two constant smis.
-
-function foo() {
+function test() {
var i = 5;
var j = 3;
-
+
assertTrue( j < i );
i = 5; j = 3;
assertTrue( j <= i );
@@ -61,8 +60,7 @@
++i;
}
j = 21;
-
-
+
assertTrue( j < i );
j = 21;
assertTrue( j <= i );
@@ -116,8 +114,8 @@
assertUnreachable();
break;
}
- assertEquals(17, j, "switch with constant value");
+ assertEquals(17, j, "switch with constant value");
}
-foo();
+test();
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---