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 7505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7516 CreateJoin(materialize_false, materialize_true, expr->id()); | 7516 CreateJoin(materialize_false, materialize_true, expr->id()); |
7517 set_current_block(join); | 7517 set_current_block(join); |
7518 if (join != NULL) return ast_context()->ReturnValue(Pop()); | 7518 if (join != NULL) return ast_context()->ReturnValue(Pop()); |
7519 } | 7519 } |
7520 | 7520 |
7521 | 7521 |
7522 HInstruction* HOptimizedGraphBuilder::BuildIncrement( | 7522 HInstruction* HOptimizedGraphBuilder::BuildIncrement( |
7523 bool returns_original_input, | 7523 bool returns_original_input, |
7524 CountOperation* expr) { | 7524 CountOperation* expr) { |
7525 // The input to the count operation is on top of the expression stack. | 7525 // The input to the count operation is on top of the expression stack. |
7526 TypeInfo info = expr->type(); | 7526 Handle<Type> info = expr->type(); |
7527 Representation rep = Representation::FromType(info); | 7527 Representation rep = Representation::FromType(info); |
7528 if (rep.IsNone() || rep.IsTagged()) { | 7528 if (rep.IsNone() || rep.IsTagged()) { |
7529 rep = Representation::Smi(); | 7529 rep = Representation::Smi(); |
7530 } | 7530 } |
7531 | 7531 |
7532 if (returns_original_input) { | 7532 if (returns_original_input) { |
7533 // We need an explicit HValue representing ToNumber(input). The | 7533 // We need an explicit HValue representing ToNumber(input). The |
7534 // actual HChange instruction we need is (sometimes) added in a later | 7534 // actual HChange instruction we need is (sometimes) added in a later |
7535 // phase, so it is not available now to be used as an input to HAdd and | 7535 // phase, so it is not available now to be used as an input to HAdd and |
7536 // as the return value. | 7536 // as the return value. |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7820 return value; | 7820 return value; |
7821 } | 7821 } |
7822 | 7822 |
7823 if (expected_obj->Is(Type::Undefined())) { | 7823 if (expected_obj->Is(Type::Undefined())) { |
7824 // This is already done by HChange. | 7824 // This is already done by HChange. |
7825 *expected = handle(Type::Union( | 7825 *expected = handle(Type::Union( |
7826 expected_number, handle(Type::Double(), isolate())), isolate()); | 7826 expected_number, handle(Type::Double(), isolate())), isolate()); |
7827 return value; | 7827 return value; |
7828 } | 7828 } |
7829 | 7829 |
7830 if (expected_obj->Is(Type::Null())) { | |
7831 *expected = handle(Type::Union( | |
7832 expected_number, handle(Type::Smi(), isolate())), isolate()); | |
7833 IfBuilder if_null(this); | |
7834 if_null.If<HCompareObjectEqAndBranch>(value, | |
7835 graph()->GetConstantNull()); | |
7836 if_null.Then(); | |
7837 Push(graph()->GetConstant0()); | |
7838 if_null.Else(); | |
7839 Push(value); | |
7840 if_null.End(); | |
7841 return Pop(); | |
7842 } | |
7843 | |
7844 if (expected_obj->Is(Type::Boolean())) { | |
7845 *expected = handle(Type::Union( | |
7846 expected_number, handle(Type::Smi(), isolate())), isolate()); | |
7847 IfBuilder if_true(this); | |
7848 if_true.If<HCompareObjectEqAndBranch>(value, | |
7849 graph()->GetConstantTrue()); | |
7850 if_true.Then(); | |
7851 Push(graph()->GetConstant1()); | |
7852 if_true.Else(); | |
7853 IfBuilder if_false(this); | |
7854 if_false.If<HCompareObjectEqAndBranch>(value, | |
7855 graph()->GetConstantFalse()); | |
7856 if_false.Then(); | |
7857 Push(graph()->GetConstant0()); | |
7858 if_false.Else(); | |
7859 Push(value); | |
7860 if_false.End(); | |
7861 if_true.End(); | |
7862 return Pop(); | |
7863 } | |
7864 | |
7865 return value; | 7830 return value; |
7866 } | 7831 } |
7867 | 7832 |
7868 | 7833 |
7869 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( | 7834 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( |
7870 BinaryOperation* expr, | 7835 BinaryOperation* expr, |
7871 HValue* left, | 7836 HValue* left, |
7872 HValue* right) { | 7837 HValue* right) { |
7873 Handle<Type> left_type = expr->left()->bounds().lower; | 7838 Handle<Type> left_type = expr->left()->bounds().lower; |
7874 Handle<Type> right_type = expr->right()->bounds().lower; | 7839 Handle<Type> right_type = expr->right()->bounds().lower; |
7875 Handle<Type> result_type = expr->bounds().lower; | 7840 Handle<Type> result_type = expr->bounds().lower; |
7876 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 7841 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
7877 | 7842 |
7878 return HGraphBuilder::BuildBinaryOperation(expr->op(), left, right, | 7843 return HGraphBuilder::BuildBinaryOperation(expr->op(), left, right, |
7879 left_type, right_type, result_type, fixed_right_arg); | 7844 left_type, right_type, result_type, fixed_right_arg); |
7880 } | 7845 } |
7881 | 7846 |
7882 | 7847 |
7883 HInstruction* HGraphBuilder::BuildBinaryOperation( | 7848 HInstruction* HGraphBuilder::BuildBinaryOperation( |
7884 Token::Value op, | 7849 Token::Value op, |
7885 HValue* left, | 7850 HValue* left, |
7886 HValue* right, | 7851 HValue* right, |
7887 Handle<Type> left_type, | 7852 Handle<Type> left_type, |
7888 Handle<Type> right_type, | 7853 Handle<Type> right_type, |
7889 Handle<Type> result_type, | 7854 Handle<Type> result_type, |
7890 Maybe<int> fixed_right_arg) { | 7855 Maybe<int> fixed_right_arg, |
| 7856 bool binop_stub) { |
7891 | 7857 |
7892 Representation left_rep = Representation::FromType(left_type); | 7858 Representation left_rep = Representation::FromType(left_type); |
7893 Representation right_rep = Representation::FromType(right_type); | 7859 Representation right_rep = Representation::FromType(right_type); |
7894 | 7860 |
7895 bool maybe_string_add = op == Token::ADD && | 7861 bool maybe_string_add = op == Token::ADD && |
7896 (left_type->Maybe(Type::String()) || | 7862 (left_type->Maybe(Type::String()) || |
7897 right_type->Maybe(Type::String())); | 7863 right_type->Maybe(Type::String())); |
7898 | 7864 |
7899 if (left_type->Is(Type::None())) { | 7865 if (left_type->Is(Type::None())) { |
7900 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | 7866 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", |
7901 Deoptimizer::SOFT); | 7867 Deoptimizer::SOFT); |
7902 // TODO(rossberg): we should be able to get rid of non-continuous | 7868 // TODO(rossberg): we should be able to get rid of non-continuous |
7903 // defaults. | 7869 // defaults. |
7904 left_type = handle(Type::Any(), isolate()); | 7870 left_type = handle(Type::Any(), isolate()); |
7905 } else { | 7871 } else { |
7906 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); | 7872 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); |
7907 left_rep = Representation::FromType(left_type); | 7873 left_rep = Representation::FromType(left_type); |
7908 } | 7874 } |
7909 | 7875 |
7910 if (right_type->Is(Type::None())) { | 7876 if (right_type->Is(Type::None())) { |
7911 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", | 7877 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", |
7912 Deoptimizer::SOFT); | 7878 Deoptimizer::SOFT); |
7913 right_type = handle(Type::Any(), isolate()); | 7879 right_type = handle(Type::Any(), isolate()); |
7914 } else { | 7880 } else { |
7915 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); | 7881 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); |
7916 right_rep = Representation::FromType(right_type); | 7882 right_rep = Representation::FromType(right_type); |
7917 } | 7883 } |
7918 | 7884 |
| 7885 if (binop_stub) { |
| 7886 left = EnforceNumberType(left, left_type); |
| 7887 right = EnforceNumberType(right, right_type); |
| 7888 } |
| 7889 |
7919 Representation result_rep = Representation::FromType(result_type); | 7890 Representation result_rep = Representation::FromType(result_type); |
7920 | 7891 |
7921 bool is_string_add = op == Token::ADD && | 7892 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || |
7922 (left_type->Is(Type::String()) || | 7893 (right_rep.IsTagged() && !right_rep.IsSmi()); |
7923 right_type->Is(Type::String())); | 7894 bool is_string_add = op == Token::ADD && |
| 7895 (left_type->Is(Type::String()) || |
| 7896 right_type->Is(Type::String())); |
7924 | 7897 |
7925 HInstruction* instr = NULL; | 7898 HInstruction* instr = NULL; |
7926 switch (op) { | 7899 // Only the stub is allowed to call into the runtime, since otherwise we would |
7927 case Token::ADD: | 7900 // inline several instructions (including the two pushes) for every tagged |
7928 if (is_string_add) { | 7901 // operation in optimized code, which is more expensive, than a stub call. |
7929 StringAddFlags flags = STRING_ADD_CHECK_BOTH; | 7902 if (binop_stub && is_non_primitive && !is_string_add) { |
7930 if (left_type->Is(Type::String())) { | 7903 HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op)); |
7931 BuildCheckHeapObject(left); | 7904 Add<HPushArgument>(left); |
7932 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 7905 Add<HPushArgument>(right); |
7933 flags = STRING_ADD_CHECK_RIGHT; | 7906 instr = NewUncasted<HInvokeFunction>(function, 2); |
| 7907 } else { |
| 7908 switch (op) { |
| 7909 case Token::ADD: |
| 7910 if (is_string_add) { |
| 7911 StringAddFlags flags = STRING_ADD_CHECK_BOTH; |
| 7912 if (left_type->Is(Type::String())) { |
| 7913 BuildCheckHeapObject(left); |
| 7914 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
| 7915 flags = STRING_ADD_CHECK_RIGHT; |
| 7916 } |
| 7917 if (right_type->Is(Type::String())) { |
| 7918 BuildCheckHeapObject(right); |
| 7919 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
| 7920 flags = (flags == STRING_ADD_CHECK_BOTH) |
| 7921 ? STRING_ADD_CHECK_LEFT : STRING_ADD_CHECK_NONE; |
| 7922 } |
| 7923 instr = NewUncasted<HStringAdd>(left, right, flags); |
| 7924 } else { |
| 7925 instr = NewUncasted<HAdd>(left, right); |
7934 } | 7926 } |
7935 if (right_type->Is(Type::String())) { | 7927 break; |
7936 BuildCheckHeapObject(right); | 7928 case Token::SUB: |
7937 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 7929 instr = NewUncasted<HSub>(left, right); |
7938 flags = (flags == STRING_ADD_CHECK_BOTH) | 7930 break; |
7939 ? STRING_ADD_CHECK_LEFT : STRING_ADD_CHECK_NONE; | 7931 case Token::MUL: |
| 7932 instr = NewUncasted<HMul>(left, right); |
| 7933 break; |
| 7934 case Token::MOD: |
| 7935 instr = NewUncasted<HMod>(left, right, fixed_right_arg); |
| 7936 break; |
| 7937 case Token::DIV: |
| 7938 instr = NewUncasted<HDiv>(left, right); |
| 7939 break; |
| 7940 case Token::BIT_XOR: |
| 7941 case Token::BIT_AND: |
| 7942 instr = NewUncasted<HBitwise>(op, left, right); |
| 7943 break; |
| 7944 case Token::BIT_OR: { |
| 7945 HValue* operand, *shift_amount; |
| 7946 if (left_type->Is(Type::Signed32()) && |
| 7947 right_type->Is(Type::Signed32()) && |
| 7948 MatchRotateRight(left, right, &operand, &shift_amount)) { |
| 7949 instr = NewUncasted<HRor>(operand, shift_amount); |
| 7950 } else { |
| 7951 instr = NewUncasted<HBitwise>(op, left, right); |
7940 } | 7952 } |
7941 instr = NewUncasted<HStringAdd>(left, right, flags); | 7953 break; |
7942 } else { | |
7943 instr = NewUncasted<HAdd>(left, right); | |
7944 } | 7954 } |
7945 break; | 7955 case Token::SAR: |
7946 case Token::SUB: | 7956 instr = NewUncasted<HSar>(left, right); |
7947 instr = NewUncasted<HSub>(left, right); | 7957 break; |
7948 break; | 7958 case Token::SHR: |
7949 case Token::MUL: | 7959 instr = NewUncasted<HShr>(left, right); |
7950 instr = NewUncasted<HMul>(left, right); | 7960 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && |
7951 break; | 7961 CanBeZero(right)) { |
7952 case Token::MOD: | 7962 graph()->RecordUint32Instruction(instr); |
7953 instr = NewUncasted<HMod>(left, right, fixed_right_arg); | 7963 } |
7954 break; | 7964 break; |
7955 case Token::DIV: | 7965 case Token::SHL: |
7956 instr = NewUncasted<HDiv>(left, right); | 7966 instr = NewUncasted<HShl>(left, right); |
7957 break; | 7967 break; |
7958 case Token::BIT_XOR: | 7968 default: |
7959 case Token::BIT_AND: | 7969 UNREACHABLE(); |
7960 instr = NewUncasted<HBitwise>(op, left, right); | |
7961 break; | |
7962 case Token::BIT_OR: { | |
7963 HValue* operand, *shift_amount; | |
7964 if (left_type->Is(Type::Signed32()) && | |
7965 right_type->Is(Type::Signed32()) && | |
7966 MatchRotateRight(left, right, &operand, &shift_amount)) { | |
7967 instr = NewUncasted<HRor>(operand, shift_amount); | |
7968 } else { | |
7969 instr = NewUncasted<HBitwise>(op, left, right); | |
7970 } | |
7971 break; | |
7972 } | 7970 } |
7973 case Token::SAR: | |
7974 instr = NewUncasted<HSar>(left, right); | |
7975 break; | |
7976 case Token::SHR: | |
7977 instr = NewUncasted<HShr>(left, right); | |
7978 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && | |
7979 CanBeZero(right)) { | |
7980 graph()->RecordUint32Instruction(instr); | |
7981 } | |
7982 break; | |
7983 case Token::SHL: | |
7984 instr = NewUncasted<HShl>(left, right); | |
7985 break; | |
7986 default: | |
7987 UNREACHABLE(); | |
7988 } | 7971 } |
7989 | 7972 |
7990 if (instr->IsBinaryOperation()) { | 7973 if (instr->IsBinaryOperation()) { |
7991 HBinaryOperation* binop = HBinaryOperation::cast(instr); | 7974 HBinaryOperation* binop = HBinaryOperation::cast(instr); |
7992 binop->set_observed_input_representation(1, left_rep); | 7975 binop->set_observed_input_representation(1, left_rep); |
7993 binop->set_observed_input_representation(2, right_rep); | 7976 binop->set_observed_input_representation(2, right_rep); |
7994 binop->initialize_output_representation(result_rep); | 7977 binop->initialize_output_representation(result_rep); |
| 7978 if (binop_stub) { |
| 7979 // Stub should not call into stub. |
| 7980 instr->SetFlag(HValue::kCannotBeTagged); |
| 7981 // And should truncate on HForceRepresentation already. |
| 7982 if (left->IsForceRepresentation()) { |
| 7983 left->CopyFlag(HValue::kTruncatingToSmi, instr); |
| 7984 left->CopyFlag(HValue::kTruncatingToInt32, instr); |
| 7985 } |
| 7986 if (right->IsForceRepresentation()) { |
| 7987 right->CopyFlag(HValue::kTruncatingToSmi, instr); |
| 7988 right->CopyFlag(HValue::kTruncatingToInt32, instr); |
| 7989 } |
| 7990 } |
7995 } | 7991 } |
7996 return instr; | 7992 return instr; |
7997 } | 7993 } |
7998 | 7994 |
7999 | 7995 |
8000 // Check for the form (%_ClassOf(foo) === 'BarClass'). | 7996 // Check for the form (%_ClassOf(foo) === 'BarClass'). |
8001 static bool IsClassOfTest(CompareOperation* expr) { | 7997 static bool IsClassOfTest(CompareOperation* expr) { |
8002 if (expr->op() != Token::EQ_STRICT) return false; | 7998 if (expr->op() != Token::EQ_STRICT) return false; |
8003 CallRuntime* call = expr->left()->AsCallRuntime(); | 7999 CallRuntime* call = expr->left()->AsCallRuntime(); |
8004 if (call == NULL) return false; | 8000 if (call == NULL) return false; |
(...skipping 1846 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9851 if (ShouldProduceTraceOutput()) { | 9847 if (ShouldProduceTraceOutput()) { |
9852 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9848 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9853 } | 9849 } |
9854 | 9850 |
9855 #ifdef DEBUG | 9851 #ifdef DEBUG |
9856 graph_->Verify(false); // No full verify. | 9852 graph_->Verify(false); // No full verify. |
9857 #endif | 9853 #endif |
9858 } | 9854 } |
9859 | 9855 |
9860 } } // namespace v8::internal | 9856 } } // namespace v8::internal |
OLD | NEW |