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

Unified Diff: src/codegen-ia32.cc

Issue 5002: Port of fast-case switch to ARM (Closed)
Patch Set: Updates based on review comments Created 12 years, 3 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-arm.cc ('k') | src/macro-assembler-arm.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/codegen-ia32.cc
diff --git a/src/codegen-ia32.cc b/src/codegen-ia32.cc
index 773e9f4f60a1e04d158582bdae782af5dab62dcc..56566e6e06227fd5436d23d0d867980bc03ed21a 100644
--- a/src/codegen-ia32.cc
+++ b/src/codegen-ia32.cc
@@ -325,28 +325,16 @@ class Ia32CodeGenerator: public CodeGenerator {
// optimization.
static const int kFastSwitchMinCaseCount = 5;
- // Create fast switch implementation if all labels are small integers
- // in a limited range. Returns false if this is not the case, and no
- // code has been generated (i.e., the default implementation should be used).
- bool TryFastCaseSwitchStatement(SwitchStatement *switchStmt);
+ virtual int FastCaseSwitchMaxOverheadFactor();
+ virtual int FastCaseSwitchMinCaseCount();
// Generate a computed jump with an empty jump table.
// Binds a label to the start of the jump table. This table must
// be populated later when the adresses of the targets are known.
// Used by GenerateFastCaseSwitchStatement.
- void GenerateFastCaseSwitchJumpTable(
- int min_index, int range, Label *fail_label, Label &table_start);
-
- // Populate an empty jump table with the adresses of bound labels.
- // Used by GenerateFastCaseSwitchStatement.
- void PopulateFastCaseSwitchJumpTable(
- Label &table_start, SmartPointer<Label*> &case_targets, int table_size);
-
- // Generates a fast-case switch statement for a switch with all-Smi labels
- // in a limited range.
- // Used by TryFastCaseSwitchStatement.
- void GenerateFastCaseSwitchStatement(
- SwitchStatement *node, int min_index, int range, int default_index);
+ virtual void GenerateFastCaseSwitchJumpTable(
+ SwitchStatement* node, int min_index, int range, Label *fail_label,
+ SmartPointer<Label*> &case_targets, SmartPointer<Label> &case_labels);
void RecordStatementPosition(Node* node);
@@ -2933,29 +2921,35 @@ void Ia32CodeGenerator::VisitWithExitStatement(WithExitStatement* node) {
__ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
}
+int Ia32CodeGenerator::FastCaseSwitchMaxOverheadFactor() {
+ return kFastSwitchMaxOverheadFactor;
+}
-// Generate a computed jump with an empty jump table.
-// Returns a label pointing to the start of the jump table. This must
-// be populated later when the adresses of the targets are known
+int Ia32CodeGenerator::FastCaseSwitchMinCaseCount() {
+ return kFastSwitchMinCaseCount;
+}
+
+// Generate a computed jump to a switch case.
void Ia32CodeGenerator::GenerateFastCaseSwitchJumpTable(
- int min_index, int range, Label *fail_label, Label &table_start) {
+ SwitchStatement* node, int min_index, int range, Label *fail_label,
+ SmartPointer<Label*> &case_targets, SmartPointer<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
// survive relocation, and it also cannot safely be distinguished
// from a real address. Instead we put in zero-values as
- // placeholders, and fill in the adresses after the labels have been
+ // placeholders, and fill in the addresses after the labels have been
// bound.
__ pop(eax); // supposed smi
// check range of value, if outside [0..length-1] jump to default/end label.
ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
if (min_index != 0) {
- __ sub(Operand(eax), Immediate(min_index * 2)); // smi subtraction
+ __ sub(Operand(eax), Immediate(min_index << kSmiTagSize));
}
- __ test(eax, Immediate(0x80000000 | kSmiTagMask)); // negative or not smi
+ __ test(eax, Immediate(0x80000000 | kSmiTagMask)); // negative or not Smi
__ j(not_equal, fail_label, not_taken);
- __ cmp(eax, range * 2);
+ __ cmp(eax, range << kSmiTagSize);
__ j(greater_equal, fail_label, not_taken);
__ jmp(Operand(eax, times_2, 0x0, internal_reference)); // 0 is placeholder
@@ -2963,120 +2957,20 @@ void Ia32CodeGenerator::GenerateFastCaseSwitchJumpTable(
int32_t jump_table_ref = __ pc_offset() - sizeof(int32_t);
__ Align(4);
+ Label table_start;
__ bind(&table_start);
__ WriteInternalReference(jump_table_ref, table_start);
for (int i = 0; i < range; i++) {
__ dd(0x0, internal_reference); // table entry, 0 is placeholder
}
-}
-
-
-// Populate an empty jump table with the adresses of bound labels.
-void Ia32CodeGenerator::PopulateFastCaseSwitchJumpTable(
- Label &table_start, SmartPointer<Label*> &case_targets, int table_size) {
- for (int i = 0; i < table_size; i++) {
- int table_entry_pos = table_start.pos() + i * sizeof(uint32_t);
- __ WriteInternalReference(table_entry_pos, *case_targets[i]);
- }
-}
-
-
-// Generates a fast-case switch statement for a switch with all-Smi labels
-// in a limited range.
-void Ia32CodeGenerator::GenerateFastCaseSwitchStatement(
- SwitchStatement *node, int min_index, int range, int default_index) {
- ZoneList<CaseClause*>* cases = node->cases();
- int length = cases->length();
-
- SmartPointer<Label*> case_targets(NewArray<Label*>(range));
- SmartPointer<Label> case_labels(NewArray<Label>(length));
-
- Label* fail_label = (default_index >= 0 ? &(case_labels[default_index])
- : node->break_target());
-
- // Create array of labels to jump to by index and set default jump
- // targets everywhere.
- for (int i = 0; i < range; i++) {
- // length => end label
- case_targets[i] = fail_label;
- }
-
- // Overwrite for values of cases:
- // (reverse order, so that if same label twice, the first one wins).
- for (int i = length-1; i >= 0 ; i--) {
- CaseClause* clause = cases->at(i);
- if (!clause->is_default()) {
- Object* label_value = *(clause->label()->AsLiteral()->handle());
- int case_value = Smi::cast(label_value)->value();
- case_targets[case_value - min_index] = &(case_labels[i]);
- }
- }
-
- // Generate the jump table and code for all cases.
- Label table_start;
-
- GenerateFastCaseSwitchJumpTable(min_index, range, fail_label, table_start);
-
- for (int i = 0; i < length; i++) {
- Comment cmnt(masm_, "[ case clause");
- __ bind(&(case_labels[i]));
- VisitStatements(cases->at(i)->statements());
- }
-
- __ bind(node->break_target());
-
- // All labels bound now, so we can populate the table with the
- // correct addresses.
- PopulateFastCaseSwitchJumpTable(table_start, case_targets, range);
-}
-
-
-bool Ia32CodeGenerator::TryFastCaseSwitchStatement(SwitchStatement *node) {
- ZoneList<CaseClause*>* cases = node->cases();
- int length = cases->length();
-
- if (length < kFastSwitchMinCaseCount) {
- return false;
- }
- // Test whether fast-case should be used.
- int default_index = -1;
- int min_index = Smi::kMaxValue;
- int max_index = Smi::kMinValue;
- for (int i = 0; i < length; i++) {
- CaseClause* clause = cases->at(i);
- if (clause->is_default()) {
- if (default_index >= 0) {
- return false; // More than one default label:
- // Defer to normal case for error.
- }
- default_index = i;
- } else {
- Expression* label = clause->label();
- Literal* literal = label->AsLiteral();
- if (literal == NULL) {
- return false; // fail fast case
- }
- Object* value = *(literal->handle());
- if (!value->IsSmi()) {
- return false;
- }
- int smi = Smi::cast(value)->value();
- if (smi < min_index) { min_index = smi; }
- if (smi > max_index) { max_index = smi; }
- }
- }
+ GenerateFastCaseSwitchCases(node, case_labels);
- // After this all labels are smis.
- int range = max_index - min_index + 1; // |min..max| inclusive
- if (range / kFastSwitchMaxOverheadFactor > length) {
- return false; // range of labels is too sparse
+ for (int i = 0, entry_pos = table_start.pos();
+ i < range; i++, entry_pos += sizeof(uint32_t)) {
+ __ WriteInternalReference(entry_pos, *case_targets[i]);
}
-
- // Optimization accepted, generate code.
- GenerateFastCaseSwitchStatement(node, min_index, range, default_index);
- return true;
}
@@ -3087,7 +2981,7 @@ void Ia32CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
Load(node->tag());
- if (TryFastCaseSwitchStatement(node)) {
+ if (TryGenerateFastCaseSwitchStatement(node)) {
return;
}
« no previous file with comments | « src/codegen-arm.cc ('k') | src/macro-assembler-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698