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