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 7634 matching lines...) Loading... | |
7645 return false; | 7645 return false; |
7646 } | 7646 } |
7647 return (sub->right() == sa); | 7647 return (sub->right() == sa); |
7648 } | 7648 } |
7649 | 7649 |
7650 | 7650 |
7651 // Checks if the left and the right are shift instructions with the oposite | 7651 // Checks if the left and the right are shift instructions with the oposite |
7652 // directions that can be replaced by one rotate right instruction or not. | 7652 // directions that can be replaced by one rotate right instruction or not. |
7653 // Returns the operand and the shift amount for the rotate instruction in the | 7653 // Returns the operand and the shift amount for the rotate instruction in the |
7654 // former case. | 7654 // former case. |
7655 bool HOptimizedGraphBuilder::MatchRotateRight(HValue* left, | 7655 bool HGraphBuilder::MatchRotateRight(HValue* left, |
7656 HValue* right, | 7656 HValue* right, |
7657 HValue** operand, | 7657 HValue** operand, |
7658 HValue** shift_amount) { | 7658 HValue** shift_amount) { |
7659 HShl* shl; | 7659 HShl* shl; |
7660 HShr* shr; | 7660 HShr* shr; |
7661 if (left->IsShl() && right->IsShr()) { | 7661 if (left->IsShl() && right->IsShr()) { |
7662 shl = HShl::cast(left); | 7662 shl = HShl::cast(left); |
7663 shr = HShr::cast(right); | 7663 shr = HShr::cast(right); |
7664 } else if (left->IsShr() && right->IsShl()) { | 7664 } else if (left->IsShr() && right->IsShl()) { |
7665 shl = HShl::cast(right); | 7665 shl = HShl::cast(right); |
7666 shr = HShr::cast(left); | 7666 shr = HShr::cast(left); |
7667 } else { | 7667 } else { |
7668 return false; | 7668 return false; |
(...skipping 15 matching lines...) Loading... | |
7684 HConstant* right_const = HConstant::cast(right); | 7684 HConstant* right_const = HConstant::cast(right); |
7685 if (right_const->HasInteger32Value() && | 7685 if (right_const->HasInteger32Value() && |
7686 (right_const->Integer32Value() & 0x1f) != 0) { | 7686 (right_const->Integer32Value() & 0x1f) != 0) { |
7687 return false; | 7687 return false; |
7688 } | 7688 } |
7689 } | 7689 } |
7690 return true; | 7690 return true; |
7691 } | 7691 } |
7692 | 7692 |
7693 | 7693 |
7694 HValue* HGraphBuilder::EnforceNumberType(HValue* number, | |
7695 Handle<Type> expected) { | |
7696 if (expected->Is(Type::Smi())) { | |
7697 return Add<HForceRepresentation>(number, Representation::Smi()); | |
7698 } else if (expected->Is(Type::Signed32())) { | |
Sven Panne
2013/09/16 13:38:09
Just drop the "else", it's cleaner... :-)
| |
7699 return Add<HForceRepresentation>(number, Representation::Integer32()); | |
7700 } | |
7701 | |
7702 return number; | |
7703 } | |
7704 | |
7705 | |
7694 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { | 7706 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { |
7695 if (value->IsConstant()) { | 7707 if (value->IsConstant()) { |
7696 HConstant* constant = HConstant::cast(value); | 7708 HConstant* constant = HConstant::cast(value); |
7697 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); | 7709 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); |
7698 if (number.has_value) { | 7710 if (number.has_value) { |
7699 *expected = handle(Type::Number(), isolate()); | 7711 *expected = handle(Type::Number(), isolate()); |
7700 return AddInstruction(number.value); | 7712 return AddInstruction(number.value); |
7701 } | 7713 } |
7702 } | 7714 } |
7703 | 7715 |
7716 NoObservableSideEffectsScope no_effects(this); | |
7717 Handle<Type> expected_type = *expected; | |
7718 | |
7719 // Separate the number type from the rest. | |
7720 Handle<Type> expected_obj = handle(Type::Intersect( | |
7721 expected_type, handle(Type::NonNumber(), isolate())), isolate()); | |
7722 Handle<Type> expected_number = handle(Type::Intersect( | |
7723 expected_type, handle(Type::Number(), isolate())), isolate()); | |
7724 | |
7725 // We expect to get a number. | |
7726 // (We need to check first, since Type::None->Is(Type::Any()) == true. | |
7727 if (expected_obj->Is(Type::None())) { | |
7728 ASSERT(!expected_number->Is(Type::None())); | |
7729 return value; | |
7730 } | |
7731 | |
7732 if (expected_obj->Is(Type::Undefined())) { | |
7733 // This is already done by HChange. | |
7734 *expected = handle(Type::Union( | |
7735 expected_number, handle(Type::Double(), isolate())), isolate()); | |
7736 return value; | |
7737 } | |
7738 | |
7739 if (expected_obj->Is(Type::Null())) { | |
7740 *expected = handle(Type::Union( | |
7741 expected_number, handle(Type::Smi(), isolate())), isolate()); | |
7742 IfBuilder if_null(this); | |
7743 if_null.If<HCompareObjectEqAndBranch>(value, | |
7744 graph()->GetConstantNull()); | |
7745 if_null.Then(); | |
7746 Push(graph()->GetConstant0()); | |
7747 if_null.Else(); | |
7748 Push(value); | |
7749 if_null.End(); | |
7750 return Pop(); | |
7751 } | |
7752 | |
7753 if (expected_obj->Is(Type::Boolean())) { | |
7754 *expected = handle(Type::Union( | |
7755 expected_number, handle(Type::Smi(), isolate())), isolate()); | |
7756 IfBuilder if_true(this); | |
7757 if_true.If<HCompareObjectEqAndBranch>(value, | |
7758 graph()->GetConstantTrue()); | |
7759 if_true.Then(); | |
7760 Push(graph()->GetConstant1()); | |
7761 if_true.Else(); | |
7762 IfBuilder if_false(this); | |
7763 if_false.If<HCompareObjectEqAndBranch>(value, | |
7764 graph()->GetConstantFalse()); | |
7765 if_false.Then(); | |
7766 Push(graph()->GetConstant0()); | |
7767 if_false.Else(); | |
7768 Push(value); | |
7769 if_false.End(); | |
7770 if_true.End(); | |
7771 return Pop(); | |
7772 } | |
7773 | |
7704 return value; | 7774 return value; |
7705 } | 7775 } |
7706 | 7776 |
7707 | 7777 |
7708 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( | 7778 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( |
7709 BinaryOperation* expr, | 7779 BinaryOperation* expr, |
7710 HValue* left, | 7780 HValue* left, |
7711 HValue* right) { | 7781 HValue* right) { |
7712 HValue* context = environment()->context(); | 7782 HValue* context = environment()->context(); |
7713 Handle<Type> left_type = expr->left()->bounds().lower; | 7783 Handle<Type> left_type = expr->left()->bounds().lower; |
7714 Handle<Type> right_type = expr->right()->bounds().lower; | 7784 Handle<Type> right_type = expr->right()->bounds().lower; |
7715 Handle<Type> result_type = expr->bounds().lower; | 7785 Handle<Type> result_type = expr->bounds().lower; |
7716 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 7786 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
7787 | |
7788 return HGraphBuilder::BuildBinaryOperation(expr->op(), left, right, | |
7789 left_type, right_type, result_type, fixed_right_arg, context); | |
7790 } | |
7791 | |
7792 | |
7793 HInstruction* HGraphBuilder::BuildBinaryOperation( | |
7794 Token::Value op, | |
7795 HValue* left, | |
7796 HValue* right, | |
7797 Handle<Type> left_type, | |
7798 Handle<Type> right_type, | |
7799 Handle<Type> result_type, | |
7800 Maybe<int> fixed_right_arg, | |
7801 HValue* context) { | |
7802 | |
7717 Representation left_rep = Representation::FromType(left_type); | 7803 Representation left_rep = Representation::FromType(left_type); |
7718 Representation right_rep = Representation::FromType(right_type); | 7804 Representation right_rep = Representation::FromType(right_type); |
7805 | |
7806 if (left_type->Is(Type::None()) || right_type->Is(Type::None())) { | |
7807 if (left_type->Is(Type::None())) { | |
7808 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | |
7809 Deoptimizer::SOFT); | |
7810 // TODO(rossberg): we should be able to get rid of non-continuous | |
7811 // defaults. | |
7812 left_type = handle(Type::Any(), isolate()); | |
7813 } else { | |
7814 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", | |
7815 Deoptimizer::SOFT); | |
7816 right_type = handle(Type::Any(), isolate()); | |
7817 } | |
7818 } else { | |
7819 bool maybe_string_add = op == Token::ADD && | |
7820 (left_type->Maybe(Type::String()) || | |
7821 right_type->Maybe(Type::String())); | |
7822 | |
7823 if (!maybe_string_add) { | |
7824 left = TruncateToNumber(left, &left_type); | |
7825 right = TruncateToNumber(right, &right_type); | |
7826 } | |
7827 | |
7828 left_rep = Representation::FromType(left_type); | |
7829 right_rep = Representation::FromType(right_type); | |
7830 } | |
7831 | |
7719 Representation result_rep = Representation::FromType(result_type); | 7832 Representation result_rep = Representation::FromType(result_type); |
7720 | 7833 |
7721 if (expr->op() != Token::ADD || | 7834 bool is_tagged = left_rep.IsTagged() || right_rep.IsTagged(); |
7722 (left->type().IsNonString() && right->type().IsNonString())) { | 7835 bool is_string_add = op == Token::ADD && is_tagged && |
7723 // For addition we can only truncate the arguments to number if we can | 7836 (left_type->Is(Type::String()) || |
7724 // prove that we will not end up in string concatenation mode. | 7837 right_type->Is(Type::String())); |
7725 left = TruncateToNumber(left, &left_type); | |
7726 right = TruncateToNumber(right, &right_type); | |
7727 } | |
7728 | 7838 |
7729 if (left_type->Is(Type::None())) { | |
7730 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | |
7731 Deoptimizer::SOFT); | |
7732 // TODO(rossberg): we should be able to get rid of non-continuous defaults. | |
7733 left_type = handle(Type::Any(), isolate()); | |
7734 } | |
7735 if (right_type->Is(Type::None())) { | |
7736 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", | |
7737 Deoptimizer::SOFT); | |
7738 right_type = handle(Type::Any(), isolate()); | |
7739 } | |
7740 HInstruction* instr = NULL; | 7839 HInstruction* instr = NULL; |
7741 switch (expr->op()) { | 7840 switch (op) { |
7742 case Token::ADD: | 7841 case Token::ADD: |
7743 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { | 7842 if (is_string_add) { |
7744 BuildCheckHeapObject(left); | 7843 StringAddFlags flags = STRING_ADD_CHECK_BOTH; |
7745 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 7844 if (left_type->Is(Type::String())) { |
7746 BuildCheckHeapObject(right); | 7845 BuildCheckHeapObject(left); |
7747 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 7846 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
7748 instr = HStringAdd::New(zone(), context, left, right); | 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); | |
7749 } else { | 7856 } else { |
7750 instr = HAdd::New(zone(), context, left, right); | 7857 instr = HAdd::New(zone(), context, left, right); |
7751 } | 7858 } |
7752 break; | 7859 break; |
7753 case Token::SUB: | 7860 case Token::SUB: |
7754 instr = HSub::New(zone(), context, left, right); | 7861 instr = HSub::New(zone(), context, left, right); |
7755 break; | 7862 break; |
7756 case Token::MUL: | 7863 case Token::MUL: |
7757 instr = HMul::New(zone(), context, left, right); | 7864 instr = HMul::New(zone(), context, left, right); |
7758 break; | 7865 break; |
7759 case Token::MOD: | 7866 case Token::MOD: |
7760 instr = HMod::New(zone(), context, left, right, fixed_right_arg); | 7867 instr = HMod::New(zone(), context, left, right, fixed_right_arg); |
7761 break; | 7868 break; |
7762 case Token::DIV: | 7869 case Token::DIV: |
7763 instr = HDiv::New(zone(), context, left, right); | 7870 instr = HDiv::New(zone(), context, left, right); |
7764 break; | 7871 break; |
7765 case Token::BIT_XOR: | 7872 case Token::BIT_XOR: |
7766 case Token::BIT_AND: | 7873 case Token::BIT_AND: |
7767 instr = NewUncasted<HBitwise>(expr->op(), left, right); | 7874 instr = NewUncasted<HBitwise>(op, left, right); |
7768 break; | 7875 break; |
7769 case Token::BIT_OR: { | 7876 case Token::BIT_OR: { |
7770 HValue* operand, *shift_amount; | 7877 HValue* operand, *shift_amount; |
7771 if (left_type->Is(Type::Signed32()) && | 7878 if (left_type->Is(Type::Signed32()) && |
7772 right_type->Is(Type::Signed32()) && | 7879 right_type->Is(Type::Signed32()) && |
7773 MatchRotateRight(left, right, &operand, &shift_amount)) { | 7880 MatchRotateRight(left, right, &operand, &shift_amount)) { |
7774 instr = new(zone()) HRor(context, operand, shift_amount); | 7881 instr = new(zone()) HRor(context, operand, shift_amount); |
7775 } else { | 7882 } else { |
7776 instr = NewUncasted<HBitwise>(expr->op(), left, right); | 7883 instr = NewUncasted<HBitwise>(op, left, right); |
7777 } | 7884 } |
7778 break; | 7885 break; |
7779 } | 7886 } |
7780 case Token::SAR: | 7887 case Token::SAR: |
7781 instr = HSar::New(zone(), context, left, right); | 7888 instr = HSar::New(zone(), context, left, right); |
7782 break; | 7889 break; |
7783 case Token::SHR: | 7890 case Token::SHR: |
7784 instr = HShr::New(zone(), context, left, right); | 7891 instr = HShr::New(zone(), context, left, right); |
7785 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && | 7892 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && |
7786 CanBeZero(right)) { | 7893 CanBeZero(right)) { |
(...skipping 1917 matching lines...) Loading... | |
9704 if (ShouldProduceTraceOutput()) { | 9811 if (ShouldProduceTraceOutput()) { |
9705 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9812 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9706 } | 9813 } |
9707 | 9814 |
9708 #ifdef DEBUG | 9815 #ifdef DEBUG |
9709 graph_->Verify(false); // No full verify. | 9816 graph_->Verify(false); // No full verify. |
9710 #endif | 9817 #endif |
9711 } | 9818 } |
9712 | 9819 |
9713 } } // namespace v8::internal | 9820 } } // namespace v8::internal |
OLD | NEW |