| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 7409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7420 CreateJoin(materialize_false, materialize_true, expr->id()); | 7420 CreateJoin(materialize_false, materialize_true, expr->id()); |
| 7421 set_current_block(join); | 7421 set_current_block(join); |
| 7422 if (join != NULL) return ast_context()->ReturnValue(Pop()); | 7422 if (join != NULL) return ast_context()->ReturnValue(Pop()); |
| 7423 } | 7423 } |
| 7424 | 7424 |
| 7425 | 7425 |
| 7426 HInstruction* HOptimizedGraphBuilder::BuildIncrement( | 7426 HInstruction* HOptimizedGraphBuilder::BuildIncrement( |
| 7427 bool returns_original_input, | 7427 bool returns_original_input, |
| 7428 CountOperation* expr) { | 7428 CountOperation* expr) { |
| 7429 // The input to the count operation is on top of the expression stack. | 7429 // The input to the count operation is on top of the expression stack. |
| 7430 TypeInfo info = expr->type(); | 7430 Handle<Type> info = expr->type(); |
| 7431 Representation rep = Representation::FromType(info); | 7431 Representation rep = Representation::FromType(info); |
| 7432 if (rep.IsNone() || rep.IsTagged()) { | 7432 if (rep.IsNone() || rep.IsTagged()) { |
| 7433 rep = Representation::Smi(); | 7433 rep = Representation::Smi(); |
| 7434 } | 7434 } |
| 7435 | 7435 |
| 7436 if (returns_original_input) { | 7436 if (returns_original_input) { |
| 7437 // We need an explicit HValue representing ToNumber(input). The | 7437 // We need an explicit HValue representing ToNumber(input). The |
| 7438 // actual HChange instruction we need is (sometimes) added in a later | 7438 // actual HChange instruction we need is (sometimes) added in a later |
| 7439 // phase, so it is not available now to be used as an input to HAdd and | 7439 // phase, so it is not available now to be used as an input to HAdd and |
| 7440 // as the return value. | 7440 // as the return value. |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7631 return false; | 7631 return false; |
| 7632 } | 7632 } |
| 7633 return (sub->right() == sa); | 7633 return (sub->right() == sa); |
| 7634 } | 7634 } |
| 7635 | 7635 |
| 7636 | 7636 |
| 7637 // Checks if the left and the right are shift instructions with the oposite | 7637 // Checks if the left and the right are shift instructions with the oposite |
| 7638 // directions that can be replaced by one rotate right instruction or not. | 7638 // directions that can be replaced by one rotate right instruction or not. |
| 7639 // Returns the operand and the shift amount for the rotate instruction in the | 7639 // Returns the operand and the shift amount for the rotate instruction in the |
| 7640 // former case. | 7640 // former case. |
| 7641 bool HOptimizedGraphBuilder::MatchRotateRight(HValue* left, | 7641 bool HGraphBuilder::MatchRotateRight(HValue* left, |
| 7642 HValue* right, | 7642 HValue* right, |
| 7643 HValue** operand, | 7643 HValue** operand, |
| 7644 HValue** shift_amount) { | 7644 HValue** shift_amount) { |
| 7645 HShl* shl; | 7645 HShl* shl; |
| 7646 HShr* shr; | 7646 HShr* shr; |
| 7647 if (left->IsShl() && right->IsShr()) { | 7647 if (left->IsShl() && right->IsShr()) { |
| 7648 shl = HShl::cast(left); | 7648 shl = HShl::cast(left); |
| 7649 shr = HShr::cast(right); | 7649 shr = HShr::cast(right); |
| 7650 } else if (left->IsShr() && right->IsShl()) { | 7650 } else if (left->IsShr() && right->IsShl()) { |
| 7651 shl = HShl::cast(right); | 7651 shl = HShl::cast(right); |
| 7652 shr = HShr::cast(left); | 7652 shr = HShr::cast(left); |
| 7653 } else { | 7653 } else { |
| 7654 return false; | 7654 return false; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 7670 HConstant* right_const = HConstant::cast(right); | 7670 HConstant* right_const = HConstant::cast(right); |
| 7671 if (right_const->HasInteger32Value() && | 7671 if (right_const->HasInteger32Value() && |
| 7672 (right_const->Integer32Value() & 0x1f) != 0) { | 7672 (right_const->Integer32Value() & 0x1f) != 0) { |
| 7673 return false; | 7673 return false; |
| 7674 } | 7674 } |
| 7675 } | 7675 } |
| 7676 return true; | 7676 return true; |
| 7677 } | 7677 } |
| 7678 | 7678 |
| 7679 | 7679 |
| 7680 HValue* HGraphBuilder::EnforceNumberType(HValue* number, |
| 7681 Handle<Type> expected) { |
| 7682 if (expected->Is(Type::Smi())) { |
| 7683 return Add<HForceRepresentation>(number, Representation::Smi()); |
| 7684 } else if (expected->Is(Type::Signed32())) { |
| 7685 return Add<HForceRepresentation>(number, Representation::Integer32()); |
| 7686 } |
| 7687 |
| 7688 return number; |
| 7689 } |
| 7690 |
| 7691 |
| 7680 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { | 7692 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { |
| 7681 if (value->IsConstant()) { | 7693 if (value->IsConstant()) { |
| 7682 HConstant* constant = HConstant::cast(value); | 7694 HConstant* constant = HConstant::cast(value); |
| 7683 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); | 7695 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); |
| 7684 if (number.has_value) { | 7696 if (number.has_value) { |
| 7685 *expected = handle(Type::Number(), isolate()); | 7697 *expected = handle(Type::Number(), isolate()); |
| 7686 return AddInstruction(number.value); | 7698 return AddInstruction(number.value); |
| 7687 } | 7699 } |
| 7688 } | 7700 } |
| 7689 | 7701 |
| 7702 NoObservableSideEffectsScope no_effects(this); |
| 7703 Handle<Type> expected_type = *expected; |
| 7704 |
| 7705 // Separate the number type from the rest. |
| 7706 Handle<Type> expected_obj = handle(Type::Intersect( |
| 7707 expected_type, handle(Type::NonNumber(), isolate())), isolate()); |
| 7708 Handle<Type> expected_number = handle(Type::Intersect( |
| 7709 expected_type, handle(Type::Number(), isolate())), isolate()); |
| 7710 |
| 7711 // We expect to get a number. |
| 7712 // (We need to check first, since Type::None->Is(Type::Any()) == true. |
| 7713 if (expected_obj->Is(Type::None())) { |
| 7714 ASSERT(!expected_number->Is(Type::None())); |
| 7715 return value; |
| 7716 } |
| 7717 |
| 7718 if (expected_obj->Is(Type::Undefined())) { |
| 7719 // This is already done by HChange. |
| 7720 *expected = handle(Type::Union( |
| 7721 expected_number, handle(Type::Double(), isolate())), isolate()); |
| 7722 return value; |
| 7723 } |
| 7724 |
| 7725 if (expected_obj->Is(Type::Null())) { |
| 7726 *expected = handle(Type::Union( |
| 7727 expected_number, handle(Type::Smi(), isolate())), isolate()); |
| 7728 IfBuilder if_null(this); |
| 7729 if_null.If<HCompareObjectEqAndBranch>(value, |
| 7730 graph()->GetConstantNull()); |
| 7731 if_null.Then(); |
| 7732 Push(graph()->GetConstant0()); |
| 7733 if_null.Else(); |
| 7734 Push(value); |
| 7735 if_null.End(); |
| 7736 return Pop(); |
| 7737 } |
| 7738 |
| 7739 if (expected_obj->Is(Type::Boolean())) { |
| 7740 *expected = handle(Type::Union( |
| 7741 expected_number, handle(Type::Smi(), isolate())), isolate()); |
| 7742 IfBuilder if_true(this); |
| 7743 if_true.If<HCompareObjectEqAndBranch>(value, |
| 7744 graph()->GetConstantTrue()); |
| 7745 if_true.Then(); |
| 7746 Push(graph()->GetConstant1()); |
| 7747 if_true.Else(); |
| 7748 IfBuilder if_false(this); |
| 7749 if_false.If<HCompareObjectEqAndBranch>(value, |
| 7750 graph()->GetConstantFalse()); |
| 7751 if_false.Then(); |
| 7752 Push(graph()->GetConstant0()); |
| 7753 if_false.Else(); |
| 7754 Push(value); |
| 7755 if_false.End(); |
| 7756 if_true.End(); |
| 7757 return Pop(); |
| 7758 } |
| 7759 |
| 7690 return value; | 7760 return value; |
| 7691 } | 7761 } |
| 7692 | 7762 |
| 7693 | 7763 |
| 7694 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( | 7764 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( |
| 7695 BinaryOperation* expr, | 7765 BinaryOperation* expr, |
| 7696 HValue* left, | 7766 HValue* left, |
| 7697 HValue* right) { | 7767 HValue* right) { |
| 7698 HValue* context = environment()->context(); | 7768 HValue* context = environment()->context(); |
| 7699 Handle<Type> left_type = expr->left()->bounds().lower; | 7769 Handle<Type> left_type = expr->left()->bounds().lower; |
| 7700 Handle<Type> right_type = expr->right()->bounds().lower; | 7770 Handle<Type> right_type = expr->right()->bounds().lower; |
| 7701 Handle<Type> result_type = expr->bounds().lower; | 7771 Handle<Type> result_type = expr->bounds().lower; |
| 7702 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 7772 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
| 7773 |
| 7774 return HGraphBuilder::BuildBinaryOperation(expr->op(), left, right, |
| 7775 left_type, right_type, result_type, fixed_right_arg, context); |
| 7776 } |
| 7777 |
| 7778 |
| 7779 HInstruction* HGraphBuilder::BuildBinaryOperation( |
| 7780 Token::Value op, |
| 7781 HValue* left, |
| 7782 HValue* right, |
| 7783 Handle<Type> left_type, |
| 7784 Handle<Type> right_type, |
| 7785 Handle<Type> result_type, |
| 7786 Maybe<int> fixed_right_arg, |
| 7787 HValue* context) { |
| 7788 |
| 7789 bool is_stub = top_info()->IsStub(); |
| 7703 Representation left_rep = Representation::FromType(left_type); | 7790 Representation left_rep = Representation::FromType(left_type); |
| 7704 Representation right_rep = Representation::FromType(right_type); | 7791 Representation right_rep = Representation::FromType(right_type); |
| 7792 |
| 7793 if (left_type->Is(Type::None()) || right_type->Is(Type::None())) { |
| 7794 if (left_type->Is(Type::None())) { |
| 7795 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", |
| 7796 Deoptimizer::SOFT); |
| 7797 // TODO(rossberg): we should be able to get rid of non-continuous |
| 7798 // defaults. |
| 7799 left_type = handle(Type::Any(), isolate()); |
| 7800 } else { |
| 7801 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", |
| 7802 Deoptimizer::SOFT); |
| 7803 right_type = handle(Type::Any(), isolate()); |
| 7804 } |
| 7805 } else { |
| 7806 bool maybe_string_add = op == Token::ADD && |
| 7807 (left_type->Maybe(Type::String()) || |
| 7808 right_type->Maybe(Type::String())); |
| 7809 |
| 7810 if (!maybe_string_add) { |
| 7811 left = TruncateToNumber(left, &left_type); |
| 7812 right = TruncateToNumber(right, &right_type); |
| 7813 } |
| 7814 if (is_stub) { |
| 7815 left = EnforceNumberType(left, left_type); |
| 7816 right = EnforceNumberType(right, right_type); |
| 7817 } |
| 7818 |
| 7819 left_rep = Representation::FromType(left_type); |
| 7820 right_rep = Representation::FromType(right_type); |
| 7821 } |
| 7822 |
| 7705 Representation result_rep = Representation::FromType(result_type); | 7823 Representation result_rep = Representation::FromType(result_type); |
| 7706 | 7824 |
| 7707 if (expr->op() != Token::ADD || | 7825 bool is_tagged = left_rep.IsTagged() || right_rep.IsTagged(); |
| 7708 (left->type().IsNonString() && right->type().IsNonString())) { | 7826 bool is_string_add = op == Token::ADD && is_tagged && |
| 7709 // For addition we can only truncate the arguments to number if we can | 7827 (left_type->Is(Type::String()) || |
| 7710 // prove that we will not end up in string concatenation mode. | 7828 right_type->Is(Type::String())); |
| 7711 left = TruncateToNumber(left, &left_type); | |
| 7712 right = TruncateToNumber(right, &right_type); | |
| 7713 } | |
| 7714 | 7829 |
| 7715 if (left_type->Is(Type::None())) { | |
| 7716 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | |
| 7717 Deoptimizer::SOFT); | |
| 7718 // TODO(rossberg): we should be able to get rid of non-continuous defaults. | |
| 7719 left_type = handle(Type::Any(), isolate()); | |
| 7720 } | |
| 7721 if (right_type->Is(Type::None())) { | |
| 7722 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", | |
| 7723 Deoptimizer::SOFT); | |
| 7724 right_type = handle(Type::Any(), isolate()); | |
| 7725 } | |
| 7726 HInstruction* instr = NULL; | 7830 HInstruction* instr = NULL; |
| 7727 switch (expr->op()) { | 7831 // Only the stub is allowed to call into the runtime, since otherwise we would |
| 7728 case Token::ADD: | 7832 // inline several instructions (including the two pushes) for every tagged |
| 7729 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { | 7833 // operation in optimized code, which is more expensive, than a stub call. |
| 7730 BuildCheckHeapObject(left); | 7834 if (is_stub && is_tagged && !is_string_add) { |
| 7731 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 7835 HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op)); |
| 7732 BuildCheckHeapObject(right); | 7836 Add<HPushArgument>(left); |
| 7733 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 7837 Add<HPushArgument>(right); |
| 7734 instr = HStringAdd::New(zone(), context, left, right); | 7838 instr = HInvokeFunction::New(zone(), context, function, 2); |
| 7735 } else { | 7839 } else { |
| 7736 instr = HAdd::New(zone(), context, left, right); | 7840 switch (op) { |
| 7841 case Token::ADD: |
| 7842 if (is_string_add) { |
| 7843 StringAddFlags flags = STRING_ADD_CHECK_BOTH; |
| 7844 if (left_type->Is(Type::String())) { |
| 7845 BuildCheckHeapObject(left); |
| 7846 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
| 7847 flags = STRING_ADD_CHECK_RIGHT; |
| 7848 } |
| 7849 if (right_type->Is(Type::String())) { |
| 7850 BuildCheckHeapObject(right); |
| 7851 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
| 7852 flags = (flags == STRING_ADD_CHECK_BOTH) |
| 7853 ? STRING_ADD_CHECK_LEFT : STRING_ADD_CHECK_NONE; |
| 7854 } |
| 7855 instr = HStringAdd::New(zone(), context, left, right, flags); |
| 7856 } else { |
| 7857 instr = HAdd::New(zone(), context, left, right); |
| 7858 } |
| 7859 break; |
| 7860 case Token::SUB: |
| 7861 instr = HSub::New(zone(), context, left, right); |
| 7862 break; |
| 7863 case Token::MUL: |
| 7864 instr = HMul::New(zone(), context, left, right); |
| 7865 break; |
| 7866 case Token::MOD: |
| 7867 instr = HMod::New(zone(), context, left, right, fixed_right_arg); |
| 7868 break; |
| 7869 case Token::DIV: |
| 7870 instr = HDiv::New(zone(), context, left, right); |
| 7871 break; |
| 7872 case Token::BIT_XOR: |
| 7873 case Token::BIT_AND: |
| 7874 instr = NewUncasted<HBitwise>(op, left, right); |
| 7875 break; |
| 7876 case Token::BIT_OR: { |
| 7877 HValue* operand, *shift_amount; |
| 7878 if (left_type->Is(Type::Signed32()) && |
| 7879 right_type->Is(Type::Signed32()) && |
| 7880 MatchRotateRight(left, right, &operand, &shift_amount)) { |
| 7881 instr = new(zone()) HRor(context, operand, shift_amount); |
| 7882 } else { |
| 7883 instr = NewUncasted<HBitwise>(op, left, right); |
| 7884 } |
| 7885 break; |
| 7737 } | 7886 } |
| 7738 break; | 7887 case Token::SAR: |
| 7739 case Token::SUB: | 7888 instr = HSar::New(zone(), context, left, right); |
| 7740 instr = HSub::New(zone(), context, left, right); | 7889 break; |
| 7741 break; | 7890 case Token::SHR: |
| 7742 case Token::MUL: | 7891 instr = HShr::New(zone(), context, left, right); |
| 7743 instr = HMul::New(zone(), context, left, right); | 7892 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && |
| 7744 break; | 7893 CanBeZero(right)) { |
| 7745 case Token::MOD: | 7894 graph()->RecordUint32Instruction(instr); |
| 7746 instr = HMod::New(zone(), context, left, right, fixed_right_arg); | 7895 } |
| 7747 break; | 7896 break; |
| 7748 case Token::DIV: | 7897 case Token::SHL: |
| 7749 instr = HDiv::New(zone(), context, left, right); | 7898 instr = HShl::New(zone(), context, left, right); |
| 7750 break; | 7899 break; |
| 7751 case Token::BIT_XOR: | 7900 default: |
| 7752 case Token::BIT_AND: | 7901 UNREACHABLE(); |
| 7753 instr = NewUncasted<HBitwise>(expr->op(), left, right); | |
| 7754 break; | |
| 7755 case Token::BIT_OR: { | |
| 7756 HValue* operand, *shift_amount; | |
| 7757 if (left_type->Is(Type::Signed32()) && | |
| 7758 right_type->Is(Type::Signed32()) && | |
| 7759 MatchRotateRight(left, right, &operand, &shift_amount)) { | |
| 7760 instr = new(zone()) HRor(context, operand, shift_amount); | |
| 7761 } else { | |
| 7762 instr = NewUncasted<HBitwise>(expr->op(), left, right); | |
| 7763 } | |
| 7764 break; | |
| 7765 } | 7902 } |
| 7766 case Token::SAR: | |
| 7767 instr = HSar::New(zone(), context, left, right); | |
| 7768 break; | |
| 7769 case Token::SHR: | |
| 7770 instr = HShr::New(zone(), context, left, right); | |
| 7771 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && | |
| 7772 CanBeZero(right)) { | |
| 7773 graph()->RecordUint32Instruction(instr); | |
| 7774 } | |
| 7775 break; | |
| 7776 case Token::SHL: | |
| 7777 instr = HShl::New(zone(), context, left, right); | |
| 7778 break; | |
| 7779 default: | |
| 7780 UNREACHABLE(); | |
| 7781 } | 7903 } |
| 7782 | 7904 |
| 7783 if (instr->IsBinaryOperation()) { | 7905 if (instr->IsBinaryOperation()) { |
| 7784 HBinaryOperation* binop = HBinaryOperation::cast(instr); | 7906 HBinaryOperation* binop = HBinaryOperation::cast(instr); |
| 7785 binop->set_observed_input_representation(1, left_rep); | 7907 binop->set_observed_input_representation(1, left_rep); |
| 7786 binop->set_observed_input_representation(2, right_rep); | 7908 binop->set_observed_input_representation(2, right_rep); |
| 7787 binop->initialize_output_representation(result_rep); | 7909 binop->initialize_output_representation(result_rep); |
| 7910 // Stub should not call into stub. |
| 7911 if (is_stub) instr->SetFlag(HValue::kCannotBeTagged); |
| 7788 } | 7912 } |
| 7789 return instr; | 7913 return instr; |
| 7790 } | 7914 } |
| 7791 | 7915 |
| 7792 | 7916 |
| 7793 // Check for the form (%_ClassOf(foo) === 'BarClass'). | 7917 // Check for the form (%_ClassOf(foo) === 'BarClass'). |
| 7794 static bool IsClassOfTest(CompareOperation* expr) { | 7918 static bool IsClassOfTest(CompareOperation* expr) { |
| 7795 if (expr->op() != Token::EQ_STRICT) return false; | 7919 if (expr->op() != Token::EQ_STRICT) return false; |
| 7796 CallRuntime* call = expr->left()->AsCallRuntime(); | 7920 CallRuntime* call = expr->left()->AsCallRuntime(); |
| 7797 if (call == NULL) return false; | 7921 if (call == NULL) return false; |
| (...skipping 1892 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9690 if (ShouldProduceTraceOutput()) { | 9814 if (ShouldProduceTraceOutput()) { |
| 9691 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9815 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 9692 } | 9816 } |
| 9693 | 9817 |
| 9694 #ifdef DEBUG | 9818 #ifdef DEBUG |
| 9695 graph_->Verify(false); // No full verify. | 9819 graph_->Verify(false); // No full verify. |
| 9696 #endif | 9820 #endif |
| 9697 } | 9821 } |
| 9698 | 9822 |
| 9699 } } // namespace v8::internal | 9823 } } // namespace v8::internal |
| OLD | NEW |