Remove the unused support for jump-table switch statements.
authorkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 16 Jun 2009 09:50:37 +0000 (09:50 +0000)
committerkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 16 Jun 2009 09:50:37 +0000 (09:50 +0000)
Review URL: http://codereview.chromium.org/126193

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2183 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/codegen-arm.cc
src/arm/codegen-arm.h
src/codegen.cc
src/codegen.h
src/ia32/assembler-ia32.cc
src/ia32/assembler-ia32.h
src/ia32/codegen-ia32.cc
src/ia32/codegen-ia32.h
src/x64/assembler-x64.h

index fe19a2c12a40c9b6abe462536c231ca0615c13a0..662661991271e950562aa74ce1c7da6d428072fd 100644 (file)
@@ -1471,85 +1471,6 @@ void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) {
 }
 
 
-int CodeGenerator::FastCaseSwitchMaxOverheadFactor() {
-  return kFastSwitchMaxOverheadFactor;
-}
-
-int CodeGenerator::FastCaseSwitchMinCaseCount() {
-  return kFastSwitchMinCaseCount;
-}
-
-
-void CodeGenerator::GenerateFastCaseSwitchJumpTable(
-    SwitchStatement* node,
-    int min_index,
-    int range,
-    Label* default_label,
-    Vector<Label*> case_targets,
-    Vector<Label> case_labels) {
-  VirtualFrame::SpilledScope spilled_scope;
-  JumpTarget setup_default;
-  JumpTarget is_smi;
-
-  // 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.
-  __ tst(r0, Operand(kSmiTagMask));
-  is_smi.Branch(eq);
-  __ CompareObjectType(r0, r1, r1, HEAP_NUMBER_TYPE);
-  default_target->Branch(ne);
-  frame_->EmitPush(r0);
-  frame_->CallRuntime(Runtime::kNumberToSmi, 1);
-  is_smi.Bind();
-
-  if (min_index != 0) {
-    // Small positive numbers can be immediate operands.
-    if (min_index < 0) {
-      // If min_index is Smi::kMinValue, -min_index is not a Smi.
-      if (Smi::IsValid(-min_index)) {
-        __ add(r0, r0, Operand(Smi::FromInt(-min_index)));
-      } else {
-        __ add(r0, r0, Operand(Smi::FromInt(-min_index - 1)));
-        __ add(r0, r0, Operand(Smi::FromInt(1)));
-      }
-    } else {
-      __ sub(r0, r0, Operand(Smi::FromInt(min_index)));
-    }
-  }
-  __ tst(r0, Operand(0x80000000 | kSmiTagMask));
-  default_target->Branch(ne);
-  __ cmp(r0, Operand(Smi::FromInt(range)));
-  default_target->Branch(ge);
-  VirtualFrame* start_frame = new VirtualFrame(frame_);
-  __ SmiJumpTable(r0, case_targets);
-
-  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();
-  }
-}
-
-
 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
 #ifdef DEBUG
   int original_height = frame_->height();
@@ -1560,10 +1481,6 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
   node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
 
   LoadAndSpill(node->tag());
-  if (TryGenerateFastCaseSwitchStatement(node)) {
-    ASSERT(!has_valid_frame() || frame_->height() == original_height);
-    return;
-  }
 
   JumpTarget next_test;
   JumpTarget fall_through;
index 0df793a4ae7ebd370dd81dc4a588fe140fee714e..4fab9001669c44822a910595cc0ce8ff1c529a31 100644 (file)
@@ -358,59 +358,6 @@ class CodeGenerator: public AstVisitor {
   inline void GenerateMathSin(ZoneList<Expression*>* args);
   inline void GenerateMathCos(ZoneList<Expression*>* args);
 
-  // Methods and constants for fast case switch statement support.
-  //
-  // Only allow fast-case switch if the range of labels is at most
-  // this factor times the number of case labels.
-  // Value is derived from comparing the size of code generated by the normal
-  // switch code for Smi-labels to the size of a single pointer. If code
-  // quality increases this number should be decreased to match.
-  static const int kFastSwitchMaxOverheadFactor = 10;
-
-  // Minimal number of switch cases required before we allow jump-table
-  // optimization.
-  static const int kFastSwitchMinCaseCount = 5;
-
-  // The limit of the range of a fast-case switch, as a factor of the number
-  // of cases of the switch. Each platform should return a value that
-  // is optimal compared to the default code generated for a switch statement
-  // on that platform.
-  int FastCaseSwitchMaxOverheadFactor();
-
-  // The minimal number of cases in a switch before the fast-case switch
-  // optimization is enabled. Each platform should return a value that
-  // is optimal compared to the default code generated for a switch statement
-  // on that platform.
-  int FastCaseSwitchMinCaseCount();
-
-  // Allocate a jump table and create code to jump through it.
-  // Should call GenerateFastCaseSwitchCases to generate the code for
-  // all the cases at the appropriate point.
-  void GenerateFastCaseSwitchJumpTable(SwitchStatement* node,
-                                       int min_index,
-                                       int range,
-                                       Label* default_label,
-                                       Vector<Label*> case_targets,
-                                       Vector<Label> case_labels);
-
-  // Generate the code for cases for the fast case switch.
-  // Called by GenerateFastCaseSwitchJumpTable.
-  void GenerateFastCaseSwitchCases(SwitchStatement* node,
-                                   Vector<Label> case_labels,
-                                   VirtualFrame* start_frame);
-
-  // Fast support for constant-Smi switches.
-  void GenerateFastCaseSwitchStatement(SwitchStatement* node,
-                                       int min_index,
-                                       int range,
-                                       int default_index);
-
-  // Fast support for constant-Smi switches. Tests whether switch statement
-  // permits optimization and calls GenerateFastCaseSwitch if it does.
-  // Returns true if the fast-case switch was generated, and false if not.
-  bool TryGenerateFastCaseSwitchStatement(SwitchStatement* node);
-
-
   // Methods used to indicate which source code is generated for. Source
   // positions are collected by the assembler and emitted with the relocation
   // information.
index e359c348aedc5ca1eeea3d89c563bac35e24571d..c718bb58f9553d16993521d224b7032b27a714b2 100644 (file)
@@ -472,129 +472,6 @@ bool CodeGenerator::PatchInlineRuntimeEntry(Handle<String> name,
 }
 
 
-void CodeGenerator::GenerateFastCaseSwitchStatement(SwitchStatement* node,
-                                                    int min_index,
-                                                    int range,
-                                                    int default_index) {
-  ZoneList<CaseClause*>* cases = node->cases();
-  int length = cases->length();
-
-  // Label pointer per number in range.
-  SmartPointer<Label*> case_targets(NewArray<Label*>(range));
-
-  // Label per switch case.
-  SmartPointer<Label> case_labels(NewArray<Label>(length));
-
-  Label* fail_label =
-      default_index >= 0 ? &(case_labels[default_index]) : NULL;
-
-  // Populate array of label pointers for each number in the range.
-  // Initally put the failure label everywhere.
-  for (int i = 0; i < range; i++) {
-    case_targets[i] = fail_label;
-  }
-
-  // Overwrite with label of a case for the number value of that case.
-  // (In reverse order, so that if the same label occurs 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]);
-    }
-  }
-
-  GenerateFastCaseSwitchJumpTable(node,
-                                  min_index,
-                                  range,
-                                  fail_label,
-                                  Vector<Label*>(*case_targets, range),
-                                  Vector<Label>(*case_labels, length));
-}
-
-
-void CodeGenerator::GenerateFastCaseSwitchCases(
-    SwitchStatement* node,
-    Vector<Label> case_labels,
-    VirtualFrame* start_frame) {
-  ZoneList<CaseClause*>* cases = node->cases();
-  int length = cases->length();
-
-  for (int i = 0; i < length; i++) {
-    Comment cmnt(masm(), "[ Case clause");
-
-    // 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 empty;
-      SetFrame(new VirtualFrame(start_frame), &empty);
-    } else {
-      frame_->MergeTo(start_frame);
-    }
-    masm()->bind(&case_labels[i]);
-    VisitStatements(cases->at(i)->statements());
-  }
-}
-
-
-bool CodeGenerator::TryGenerateFastCaseSwitchStatement(SwitchStatement* node) {
-  // TODO(238): Due to issue 238, fast case switches can crash on ARM
-  // and possibly IA32.  They are disabled for now.
-  // See http://code.google.com/p/v8/issues/detail?id=238
-  return false;
-
-  ZoneList<CaseClause*>* cases = node->cases();
-  int length = cases->length();
-
-  if (length < FastCaseSwitchMinCaseCount()) {
-    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) {
-        // There is more than one default label. Defer to the normal case
-        // for error.
-        return false;
-      }
-      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 int_value = Smi::cast(value)->value();
-      min_index = Min(int_value, min_index);
-      max_index = Max(int_value, max_index);
-    }
-  }
-
-  // All labels are known to be Smis.
-  int range = max_index - min_index + 1;  // |min..max| inclusive
-  if (range / FastCaseSwitchMaxOverheadFactor() > length) {
-    return false;  // range of labels is too sparse
-  }
-
-  // Optimization accepted, generate code.
-  GenerateFastCaseSwitchStatement(node, min_index, range, default_index);
-  return true;
-}
-
-
 void CodeGenerator::CodeForFunctionPosition(FunctionLiteral* fun) {
   if (FLAG_debug_info) {
     int pos = fun->start_position();
index 0b42935f5b9a10974b82327599cd894c551675e8..fa414d4128dc4d754d3750decf0e6b6b8b6c781c 100644 (file)
 //   FindInlineRuntimeLUT
 //   CheckForInlineRuntimeCall
 //   PatchInlineRuntimeEntry
-//   GenerateFastCaseSwitchStatement
-//   GenerateFastCaseSwitchCases
-//   TryGenerateFastCaseSwitchStatement
-//   GenerateFastCaseSwitchJumpTable
-//   FastCaseSwitchMinCaseCount
-//   FastCaseSwitchMaxOverheadFactor
 //   CodeForFunctionPosition
 //   CodeForReturnPosition
 //   CodeForStatementPosition
index b5efe9e4c79bf3f412b53c43f31607a554a10f04..233d1851bd7d2c8617dc8be0b355a1ac9518b64d 100644 (file)
@@ -2182,17 +2182,6 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
 }
 
 
-void Assembler::WriteInternalReference(int position, const Label& bound_label) {
-  ASSERT(bound_label.is_bound());
-  ASSERT(0 <= position);
-  ASSERT(position + static_cast<int>(sizeof(uint32_t)) <= pc_offset());
-  ASSERT(long_at(position) == 0);  // only initialize once!
-
-  uint32_t label_loc = reinterpret_cast<uint32_t>(addr_at(bound_label.pos()));
-  long_at_put(position, label_loc);
-}
-
-
 #ifdef GENERATED_CODE_COVERAGE
 static FILE* coverage_log = NULL;
 
index ae16e700f1156d452285f70d549051f1b0138970..462bd05fe18ac53c4b9e7e92073ded8f9b56c7e1 100644 (file)
@@ -731,11 +731,6 @@ class Assembler : public Malloced {
   // Used for inline tables, e.g., jump-tables.
   void dd(uint32_t data, RelocInfo::Mode reloc_info);
 
-  // Writes the absolute address of a bound label at the given position in
-  // the generated code. That positions should have the relocation mode
-  // internal_reference!
-  void WriteInternalReference(int position, const Label& bound_label);
-
   int pc_offset() const  { return pc_ - buffer_; }
   int current_statement_position() const { return current_statement_position_; }
   int current_position() const  { return current_position_; }
index 3357f57e45a1ff0ed302dd55a1f57c583accf75b..42fe9da9f5ee18a3b0c3a4ed484b32b4ec806898 100644 (file)
@@ -2420,131 +2420,6 @@ void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) {
 }
 
 
-int CodeGenerator::FastCaseSwitchMaxOverheadFactor() {
-    return kFastSwitchMaxOverheadFactor;
-}
-
-
-int CodeGenerator::FastCaseSwitchMinCaseCount() {
-    return kFastSwitchMinCaseCount;
-}
-
-
-// Generate a computed jump to a switch case.
-void CodeGenerator::GenerateFastCaseSwitchJumpTable(
-    SwitchStatement* node,
-    int min_index,
-    int range,
-    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
-  // 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 addresses after the labels have been
-  // bound.
-
-  JumpTarget setup_default;
-  JumpTarget is_smi;
-
-  // 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);
-  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.  Check if it is a
-  // heap number.
-  Result temp = allocator()->Allocate();
-  ASSERT(temp.is_valid());
-  __ CmpObjectType(switch_value.reg(), HEAP_NUMBER_TYPE, temp.reg());
-  temp.Unuse();
-  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));
-  default_target->Branch(not_equal, not_taken);
-  __ cmp(smi_value.reg(), range << kSmiTagSize);
-  default_target->Branch(greater_equal, not_taken);
-
-  // The expected frame at all the case labels is a version of the
-  // current one (the bidirectional entry frame, which an arbitrary
-  // frame of the correct height can be merged to).  Keep a copy to
-  // restore at the start of every label.  Create a jump target and
-  // bind it to set its entry frame properly.
-  JumpTarget entry_target(JumpTarget::BIDIRECTIONAL);
-  entry_target.Bind(&smi_value);
-  VirtualFrame* start_frame = new VirtualFrame(frame_);
-
-  // 0 is placeholder.
-  // Jump to the address at table_address + 2 * smi_value.reg().
-  // The target of the jump is read from table_address + 4 * switch_value.
-  // The Smi encoding of smi_value.reg() is 2 * switch_value.
-  smi_value.ToRegister();
-  __ jmp(Operand(smi_value.reg(), smi_value.reg(),
-                 times_1, 0x0, RelocInfo::INTERNAL_REFERENCE));
-  smi_value.Unuse();
-  // Calculate address to overwrite later with actual address of table.
-  int32_t jump_table_ref = masm_->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++) {
-    // These are the table entries. 0x0 is the placeholder for case address.
-    __ dd(0x0, RelocInfo::INTERNAL_REFERENCE);
-  }
-
-  GenerateFastCaseSwitchCases(node, case_labels, start_frame);
-
-  // If there was a default case, we need to emit the code to match it.
-  if (default_label != NULL) {
-    if (has_valid_frame()) {
-      node->break_target()->Jump();
-    }
-    setup_default.Bind();
-    frame_->MergeTo(start_frame);
-    __ jmp(default_label);
-    DeleteFrame();
-  }
-  if (node->break_target()->is_linked()) {
-    node->break_target()->Bind();
-  }
-
-  for (int i = 0, entry_pos = table_start.pos();
-       i < range;
-       i++, entry_pos += sizeof(uint32_t)) {
-    if (case_targets[i] == NULL) {
-      __ WriteInternalReference(entry_pos,
-                                *node->break_target()->entry_label());
-    } else {
-      __ WriteInternalReference(entry_pos, *case_targets[i]);
-    }
-  }
-}
-
-
 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
   ASSERT(!in_spilled_code());
   Comment cmnt(masm_, "[ SwitchStatement");
@@ -2554,10 +2429,6 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
   // Compile the switch value.
   Load(node->tag());
 
-  if (TryGenerateFastCaseSwitchStatement(node)) {
-    return;
-  }
-
   ZoneList<CaseClause*>* cases = node->cases();
   int length = cases->length();
   CaseClause* default_clause = NULL;
index e4095134884f9e3d42d98dfa8d5f27d05265ecc2..7bf1c63cb914b2ac6095b571f9e6c6286d6fb9f5 100644 (file)
@@ -527,58 +527,6 @@ class CodeGenerator: public AstVisitor {
   inline void GenerateMathSin(ZoneList<Expression*>* args);
   inline void GenerateMathCos(ZoneList<Expression*>* args);
 
-  // Methods and constants for fast case switch statement support.
-  //
-  // Only allow fast-case switch if the range of labels is at most
-  // this factor times the number of case labels.
-  // Value is derived from comparing the size of code generated by the normal
-  // switch code for Smi-labels to the size of a single pointer. If code
-  // quality increases this number should be decreased to match.
-  static const int kFastSwitchMaxOverheadFactor = 5;
-
-  // Minimal number of switch cases required before we allow jump-table
-  // optimization.
-  static const int kFastSwitchMinCaseCount = 5;
-
-  // The limit of the range of a fast-case switch, as a factor of the number
-  // of cases of the switch. Each platform should return a value that
-  // is optimal compared to the default code generated for a switch statement
-  // on that platform.
-  int FastCaseSwitchMaxOverheadFactor();
-
-  // The minimal number of cases in a switch before the fast-case switch
-  // optimization is enabled. Each platform should return a value that
-  // is optimal compared to the default code generated for a switch statement
-  // on that platform.
-  int FastCaseSwitchMinCaseCount();
-
-  // Allocate a jump table and create code to jump through it.
-  // Should call GenerateFastCaseSwitchCases to generate the code for
-  // all the cases at the appropriate point.
-  void GenerateFastCaseSwitchJumpTable(SwitchStatement* node,
-                                       int min_index,
-                                       int range,
-                                       Label* fail_label,
-                                       Vector<Label*> case_targets,
-                                       Vector<Label> case_labels);
-
-  // Generate the code for cases for the fast case switch.
-  // Called by GenerateFastCaseSwitchJumpTable.
-  void GenerateFastCaseSwitchCases(SwitchStatement* node,
-                                   Vector<Label> case_labels,
-                                   VirtualFrame* start_frame);
-
-  // Fast support for constant-Smi switches.
-  void GenerateFastCaseSwitchStatement(SwitchStatement* node,
-                                       int min_index,
-                                       int range,
-                                       int default_index);
-
-  // Fast support for constant-Smi switches. Tests whether switch statement
-  // permits optimization and calls GenerateFastCaseSwitch if it does.
-  // Returns true if the fast-case switch was generated, and false if not.
-  bool TryGenerateFastCaseSwitchStatement(SwitchStatement* node);
-
   // Methods used to indicate which source code is generated for. Source
   // positions are collected by the assembler and emitted with the relocation
   // information.
index 650c218f1112a01f66814055568b232423c193bf..2010375eaf262b7d945221df82e26e12fb286152 100644 (file)
@@ -812,11 +812,6 @@ class Assembler : public Malloced {
   // Used for inline tables, e.g., jump-tables.
   // void dd(uint64_t data, RelocInfo::Mode reloc_info);
 
-  // Writes the absolute address of a bound label at the given position in
-  // the generated code. That positions should have the relocation mode
-  // internal_reference!
-  void WriteInternalReference(int position, const Label& bound_label);
-
   int pc_offset() const  { return pc_ - buffer_; }
   int current_statement_position() const { return current_statement_position_; }
   int current_position() const  { return current_position_; }