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

Unified Diff: src/hydrogen.cc

Issue 111573003: Hydrogen: Re-use regular comparisons infrastructure for switch statements (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: added comment Created 7 years 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/hydrogen.h ('k') | src/type-info.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index bb2b08984d4ace32f9fa3fab0ca1efd762913218..2c8bac9e8c64a596bac92595786ab69fd1af9164 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -4136,8 +4136,7 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- // We only optimize switch statements with smi-literal smi comparisons,
- // with a bounded number of clauses.
+ // We only optimize switch statements with a bounded number of clauses.
const int kCaseClauseLimit = 128;
ZoneList<CaseClause*>* clauses = stmt->cases();
int clause_count = clauses->length();
@@ -4146,28 +4145,10 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
return Bailout(kSwitchStatementTooManyClauses);
}
- ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH);
-
CHECK_ALIVE(VisitForValue(stmt->tag()));
Add<HSimulate>(stmt->EntryId());
HValue* tag_value = Top();
-
- HUnaryControlInstruction* string_check = NULL;
- HBasicBlock* not_string_block = NULL;
-
- // Test switch's tag value if all clauses are string literals
- if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) {
- HBasicBlock* first_test_block = graph()->CreateBasicBlock();
- not_string_block = graph()->CreateBasicBlock();
- string_check = New<HIsStringAndBranch>(
- tag_value, first_test_block, not_string_block);
- FinishCurrentBlock(string_check);
-
- set_current_block(not_string_block);
- Drop(1); // tag_value
-
- set_current_block(first_test_block);
- }
+ Handle<Type> tag_type = stmt->tag()->bounds().lower;
// 1. Build all the tests, with dangling true branches
BailoutId default_id = BailoutId::None();
@@ -4183,35 +4164,12 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
CHECK_ALIVE(VisitForValue(clause->label()));
HValue* label_value = Pop();
- HControlInstruction* compare;
-
- if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) {
- if (!clause->compare_type()->Is(Type::Smi())) {
- Add<HDeoptimize>("Non-smi switch type", Deoptimizer::SOFT);
- }
-
- HCompareNumericAndBranch* compare_ =
- New<HCompareNumericAndBranch>(tag_value,
- label_value,
- Token::EQ_STRICT);
- compare_->set_observed_input_representation(
- Representation::Smi(), Representation::Smi());
- compare = compare_;
- } else if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) {
- compare = New<HStringCompareAndBranch>(tag_value,
- label_value,
- Token::EQ_STRICT);
- } else {
- HValue* test = Add<HCompareGeneric>(tag_value,
- label_value,
- Token::EQ_STRICT);
- if (test->HasObservableSideEffects()) {
- Push(test);
- Add<HSimulate>(clause->id(), REMOVABLE_SIMULATE);
- Drop(1);
- }
- compare = New<HBranch>(test);
- }
+ Handle<Type> label_type = clause->label()->bounds().lower;
+ Handle<Type> combined_type = clause->compare_type();
+ HControlInstruction* compare = BuildCompareInstruction(
+ Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
+ combined_type, stmt->tag()->position(), clause->label()->position(),
+ clause->id());
HBasicBlock* next_test_block = graph()->CreateBasicBlock();
HBasicBlock* body_block = graph()->CreateBasicBlock();
@@ -4231,11 +4189,6 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
HBasicBlock* last_block = current_block();
Drop(1); // tag_value
- if (not_string_block != NULL) {
- BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId();
- last_block = CreateJoin(last_block, not_string_block, join_id);
- }
-
// 2. Loop over the clauses and the linked list of tests in lockstep,
// translating the clause bodies.
HBasicBlock* fall_through_block = NULL;
@@ -9142,9 +9095,6 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
Handle<Type> left_type = expr->left()->bounds().lower;
Handle<Type> right_type = expr->right()->bounds().lower;
Handle<Type> combined_type = expr->combined_type();
- Representation combined_rep = Representation::FromType(combined_type);
- Representation left_rep = Representation::FromType(left_type);
- Representation right_rep = Representation::FromType(right_type);
CHECK_ALIVE(VisitForValue(expr->left()));
CHECK_ALIVE(VisitForValue(expr->right()));
@@ -9218,34 +9168,54 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
combined_type = left_type = right_type = handle(Type::Any(), isolate());
}
+ HControlInstruction* compare = BuildCompareInstruction(
+ op, left, right, left_type, right_type, combined_type,
+ expr->left()->position(), expr->right()->position(), expr->id());
+ if (compare == NULL) return; // Bailed out.
+ return ast_context()->ReturnControl(compare, expr->id());
+}
+
+
+HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
+ Token::Value op,
+ HValue* left,
+ HValue* right,
+ Handle<Type> left_type,
+ Handle<Type> right_type,
+ Handle<Type> combined_type,
+ int left_position,
+ int right_position,
+ BailoutId bailout_id) {
+ Representation left_rep = Representation::FromType(left_type);
+ Representation right_rep = Representation::FromType(right_type);
+ Representation combined_rep = Representation::FromType(combined_type);
+
if (combined_type->Is(Type::Receiver())) {
- switch (op) {
- case Token::EQ:
- case Token::EQ_STRICT: {
- // Can we get away with map check and not instance type check?
- if (combined_type->IsClass()) {
- Handle<Map> map = combined_type->AsClass();
- AddCheckMap(left, map);
- AddCheckMap(right, map);
- HCompareObjectEqAndBranch* result =
- New<HCompareObjectEqAndBranch>(left, right);
- if (FLAG_emit_opt_code_positions) {
- result->set_operand_position(zone(), 0, expr->left()->position());
- result->set_operand_position(zone(), 1, expr->right()->position());
- }
- return ast_context()->ReturnControl(result, expr->id());
- } else {
- BuildCheckHeapObject(left);
- Add<HCheckInstanceType>(left, HCheckInstanceType::IS_SPEC_OBJECT);
- BuildCheckHeapObject(right);
- Add<HCheckInstanceType>(right, HCheckInstanceType::IS_SPEC_OBJECT);
- HCompareObjectEqAndBranch* result =
- New<HCompareObjectEqAndBranch>(left, right);
- return ast_context()->ReturnControl(result, expr->id());
+ if (Token::IsEqualityOp(op)) {
+ // Can we get away with map check and not instance type check?
+ if (combined_type->IsClass()) {
+ Handle<Map> map = combined_type->AsClass();
+ AddCheckMap(left, map);
+ AddCheckMap(right, map);
+ HCompareObjectEqAndBranch* result =
+ New<HCompareObjectEqAndBranch>(left, right);
+ if (FLAG_emit_opt_code_positions) {
+ result->set_operand_position(zone(), 0, left_position);
+ result->set_operand_position(zone(), 1, right_position);
}
+ return result;
+ } else {
+ BuildCheckHeapObject(left);
+ Add<HCheckInstanceType>(left, HCheckInstanceType::IS_SPEC_OBJECT);
+ BuildCheckHeapObject(right);
+ Add<HCheckInstanceType>(right, HCheckInstanceType::IS_SPEC_OBJECT);
+ HCompareObjectEqAndBranch* result =
+ New<HCompareObjectEqAndBranch>(left, right);
+ return result;
}
- default:
- return Bailout(kUnsupportedNonPrimitiveCompare);
+ } else {
+ Bailout(kUnsupportedNonPrimitiveCompare);
+ return NULL;
}
} else if (combined_type->Is(Type::InternalizedString()) &&
Token::IsEqualityOp(op)) {
@@ -9255,7 +9225,7 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING);
HCompareObjectEqAndBranch* result =
New<HCompareObjectEqAndBranch>(left, right);
- return ast_context()->ReturnControl(result, expr->id());
+ return result;
} else if (combined_type->Is(Type::String())) {
BuildCheckHeapObject(left);
Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
@@ -9263,23 +9233,28 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
HStringCompareAndBranch* result =
New<HStringCompareAndBranch>(left, right, op);
- return ast_context()->ReturnControl(result, expr->id());
+ return result;
} else {
if (combined_rep.IsTagged() || combined_rep.IsNone()) {
- HCompareGeneric* result = New<HCompareGeneric>(left, right, op);
+ HCompareGeneric* result = Add<HCompareGeneric>(left, right, op);
result->set_observed_input_representation(1, left_rep);
result->set_observed_input_representation(2, right_rep);
- return ast_context()->ReturnInstruction(result, expr->id());
+ if (result->HasObservableSideEffects()) {
+ Push(result);
+ AddSimulate(bailout_id, REMOVABLE_SIMULATE);
+ Drop(1);
+ }
+ // TODO(jkummerow): Can we make this more efficient?
+ HBranch* branch = New<HBranch>(result);
+ return branch;
} else {
HCompareNumericAndBranch* result =
New<HCompareNumericAndBranch>(left, right, op);
result->set_observed_input_representation(left_rep, right_rep);
if (FLAG_emit_opt_code_positions) {
- result->SetOperandPositions(zone(),
- expr->left()->position(),
- expr->right()->position());
+ result->SetOperandPositions(zone(), left_position, right_position);
}
- return ast_context()->ReturnControl(result, expr->id());
+ return result;
}
}
}
« no previous file with comments | « src/hydrogen.h ('k') | src/type-info.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698