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

Side by Side Diff: src/hydrogen.cc

Issue 23618002: Hydrogenisation of binops (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: rebase Created 7 years, 3 months 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698