Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(534)

Unified Diff: src/codegen-ia32.cc

Issue 21040: Experimental: handle single-entry basic blocks as a special case.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 11 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/codegen-ia32.h ('k') | src/jump-target.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/codegen-ia32.cc
===================================================================
--- src/codegen-ia32.cc (revision 1215)
+++ src/codegen-ia32.cc (working copy)
@@ -1443,9 +1443,7 @@
node->set_break_stack_height(break_stack_height_);
node->break_target()->Initialize(this);
VisitStatements(node->statements());
- if (node->break_target()->is_linked()) {
- node->break_target()->Bind();
- }
+ node->break_target()->Bind();
}
@@ -1602,9 +1600,7 @@
}
}
- if (exit.is_linked()) {
- exit.Bind();
- }
+ exit.Bind();
}
@@ -1755,9 +1751,9 @@
SwitchStatement* node,
int min_index,
int range,
- JumpTarget* fail_label,
- Vector<JumpTarget*> case_targets,
- Vector<JumpTarget> case_labels) {
+ Label* default_label,
+ Vector<Label*> case_targets,
+ Vector<Label> case_labels) {
// Notice: Internal references, used by both the jmp instruction and
// the table entries, need to be relocated if the buffer grows. This
// prevents the forward use of Labels, since a displacement cannot
@@ -1766,38 +1762,48 @@
// placeholders, and fill in the addresses after the labels have been
// bound.
- Result switch_value = frame_->Pop(); // supposed Smi
- // If value is not in range [0..length-1] then jump to the default/end label.
+ 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".
+ JumpTarget* default_target =
+ (default_label == NULL) ? node->break_target() : &setup_default;
+
+ // Test whether input is a smi.
ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
-
- // Test whether input is a HeapNumber that is really a Smi
- JumpTarget is_smi(this);
+ Result switch_value = frame_->Pop();
switch_value.ToRegister();
__ test(switch_value.reg(), Immediate(kSmiTagMask));
is_smi.Branch(equal, &switch_value, taken);
- // It's a heap object, not a Smi or a Failure
+
+ // It's a heap object, not a smi or a failure. Check if it is a
+ // heap number.
Result temp = allocator()->Allocate();
ASSERT(temp.is_valid());
__ mov(temp.reg(), FieldOperand(switch_value.reg(), HeapObject::kMapOffset));
__ movzx_b(temp.reg(), FieldOperand(temp.reg(), Map::kInstanceTypeOffset));
__ cmp(temp.reg(), HEAP_NUMBER_TYPE);
temp.Unuse();
- fail_label->Branch(not_equal);
- // Result switch_value is a heap number.
+ default_target->Branch(not_equal);
+
+ // The switch value is a heap number. Convert it to a smi.
frame_->Push(&switch_value);
Result smi_value = frame_->CallRuntime(Runtime::kNumberToSmi, 1);
+
is_smi.Bind(&smi_value);
smi_value.ToRegister();
-
+ // Convert the switch value to a 0-based table index.
if (min_index != 0) {
frame_->Spill(smi_value.reg());
__ sub(Operand(smi_value.reg()), Immediate(min_index << kSmiTagSize));
}
+ // Go to the default case if the table index is negative or not a smi.
__ test(smi_value.reg(), Immediate(0x80000000 | kSmiTagMask));
- // Go to slow case if adjusted index is negative or not a Smi.
- fail_label->Branch(not_equal, not_taken);
+ default_target->Branch(not_equal, not_taken);
__ cmp(smi_value.reg(), range << kSmiTagSize);
- fail_label->Branch(greater_equal, not_taken);
+ default_target->Branch(greater_equal, not_taken);
// 0 is placeholder.
// Jump to the address at table_address + 2 * smi_value.reg().
@@ -1805,27 +1811,50 @@
// The Smi encoding of smi_value.reg() is 2 * switch_value.
__ jmp(Operand(smi_value.reg(), smi_value.reg(),
times_1, 0x0, RelocInfo::INTERNAL_REFERENCE));
+ smi_value.Unuse();
+
+ // The expected frame at all the case labels is the (mergable
+ // version of the) current one. Keep a copy to restore at the start
+ // of every label.
+ frame_->MakeMergable();
+ VirtualFrame* start_frame = new VirtualFrame(frame_);
+
// Calculate address to overwrite later with actual address of table.
int32_t jump_table_ref = __ pc_offset() - sizeof(int32_t);
-
__ Align(4);
- JumpTarget table_start(this);
- smi_value.Unuse();
- table_start.Bind();
- __ WriteInternalReference(jump_table_ref, *table_start.entry_label());
+ Label table_start;
+ __ bind(&table_start);
+ __ WriteInternalReference(jump_table_ref, table_start);
for (int i = 0; i < range; i++) {
// These are the table entries. 0x0 is the placeholder for case address.
__ dd(0x0, RelocInfo::INTERNAL_REFERENCE);
}
- GenerateFastCaseSwitchCases(node, case_labels, &table_start);
+ GenerateFastCaseSwitchCases(node, case_labels, start_frame);
- for (int i = 0, entry_pos = table_start.entry_label()->pos();
+ // If there was a default case, we need to emit the code to match it.
+ if (default_label != NULL) {
+ node->break_target()->Jump();
+ setup_default.Bind();
+ frame_->MergeTo(start_frame);
+ __ jmp(default_label);
+ DeleteFrame();
+ }
+ node->break_target()->Bind();
+
+ for (int i = 0, entry_pos = table_start.pos();
i < range;
i++, entry_pos += sizeof(uint32_t)) {
- __ WriteInternalReference(entry_pos, *case_targets[i]->entry_label());
+ if (case_targets[i] == NULL) {
+ __ WriteInternalReference(entry_pos,
+ *node->break_target()->entry_label());
+ } else {
+ __ WriteInternalReference(entry_pos, *case_targets[i]);
+ }
}
+
+ delete start_frame;
}
@@ -1837,7 +1866,6 @@
node->break_target()->Initialize(this);
Load(node->tag());
-
if (TryGenerateFastCaseSwitchStatement(node)) {
return;
}
@@ -1918,13 +1946,8 @@
}
}
- if (fall_through.is_linked()) {
- fall_through.Bind();
- }
-
- if (node->break_target()->is_linked()) {
- node->break_target()->Bind();
- }
+ fall_through.Bind();
+ node->break_target()->Bind();
}
@@ -1984,16 +2007,12 @@
}
} else if (info == ALWAYS_FALSE) {
// If we had a continue in the body we have to bind its jump target.
- if (node->continue_target()->is_linked()) {
- node->continue_target()->Bind();
- }
+ node->continue_target()->Bind();
} else {
ASSERT(info == DONT_KNOW);
// We have to compile the test expression if it can be reached by
// control flow falling out of the body or via continue.
- if (node->continue_target()->is_linked()) {
- node->continue_target()->Bind();
- }
+ node->continue_target()->Bind();
if (has_valid_frame()) {
LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
&body, node->break_target(), true);
@@ -2021,9 +2040,7 @@
JumpTarget body(this);
LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
&body, node->break_target(), true);
- if (body.is_linked()) {
- body.Bind();
- }
+ body.Bind();
}
if (has_valid_frame()) {
@@ -2066,9 +2083,7 @@
JumpTarget body(this);
LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
&body, node->break_target(), true);
- if (body.is_linked()) {
- body.Bind();
- }
+ body.Bind();
}
if (has_valid_frame()) {
@@ -2085,9 +2100,7 @@
// If there is an update statement and control flow can reach it
// via falling out of the body of the loop or continuing, we
// compile the update statement.
- if (node->continue_target()->is_linked()) {
- node->continue_target()->Bind();
- }
+ node->continue_target()->Bind();
if (has_valid_frame()) {
// Record source position of the statement as this code which is
// after the code for the body actually belongs to the loop
@@ -2104,9 +2117,7 @@
}
DecrementLoopNesting();
- if (node->break_target()->is_linked()) {
- node->break_target()->Bind();
- }
+ node->break_target()->Bind();
}
@@ -2130,7 +2141,6 @@
JumpTarget fixed_array(this);
JumpTarget entry(this, JumpTarget::BIDIRECTIONAL);
JumpTarget end_del_check(this);
- JumpTarget cleanup(this);
JumpTarget exit(this);
// Get the object to enumerate over (converted to JSObject).
@@ -2216,7 +2226,7 @@
entry.Bind();
__ mov(eax, frame_->ElementAt(0)); // load the current count
__ cmp(eax, frame_->ElementAt(1)); // compare to the array length
- cleanup.Branch(above_equal);
+ node->break_target()->Branch(above_equal);
// Get the i'th entry of the array.
__ mov(edx, frame_->ElementAt(2));
@@ -2291,7 +2301,6 @@
entry.Jump();
// Cleanup.
- cleanup.Bind();
node->break_target()->Bind();
frame_->Drop(5);
@@ -2661,9 +2670,7 @@
Load(node->else_expression(), typeof_state());
}
- if (exit.is_linked()) {
- exit.Bind();
- }
+ exit.Bind();
}
@@ -2801,12 +2808,7 @@
// scope.
}
- // If we definitely did not jump over the assignment, we do not need
- // to bind the exit label. Doing so can defeat peephole
- // optimization.
- if (exit.is_linked()) {
- exit.Bind();
- }
+ exit.Bind();
}
}
« no previous file with comments | « src/codegen-ia32.h ('k') | src/jump-target.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698