| 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;
|
| }
|
| }
|
| }
|
|
|