Chromium Code Reviews| 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand all 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...) Expand 10 before | Expand all | Expand 10 after 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 |