| 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 Handle<Type> info = expr->type(); | 7527 TypeInfo 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 |
| 7831 return value; | 7866 return value; |
| 7832 } | 7867 } |
| 7833 | 7868 |
| 7834 | 7869 |
| 7835 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( | 7870 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( |
| 7836 BinaryOperation* expr, | 7871 BinaryOperation* expr, |
| 7837 HValue* left, | 7872 HValue* left, |
| 7838 HValue* right) { | 7873 HValue* right) { |
| 7839 Handle<Type> left_type = expr->left()->bounds().lower; | 7874 Handle<Type> left_type = expr->left()->bounds().lower; |
| 7840 Handle<Type> right_type = expr->right()->bounds().lower; | 7875 Handle<Type> right_type = expr->right()->bounds().lower; |
| 7841 Handle<Type> result_type = expr->bounds().lower; | 7876 Handle<Type> result_type = expr->bounds().lower; |
| 7842 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 7877 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
| 7843 | 7878 |
| 7844 return HGraphBuilder::BuildBinaryOperation(expr->op(), left, right, | 7879 return HGraphBuilder::BuildBinaryOperation(expr->op(), left, right, |
| 7845 left_type, right_type, result_type, fixed_right_arg); | 7880 left_type, right_type, result_type, fixed_right_arg); |
| 7846 } | 7881 } |
| 7847 | 7882 |
| 7848 | 7883 |
| 7849 HInstruction* HGraphBuilder::BuildBinaryOperation( | 7884 HInstruction* HGraphBuilder::BuildBinaryOperation( |
| 7850 Token::Value op, | 7885 Token::Value op, |
| 7851 HValue* left, | 7886 HValue* left, |
| 7852 HValue* right, | 7887 HValue* right, |
| 7853 Handle<Type> left_type, | 7888 Handle<Type> left_type, |
| 7854 Handle<Type> right_type, | 7889 Handle<Type> right_type, |
| 7855 Handle<Type> result_type, | 7890 Handle<Type> result_type, |
| 7856 Maybe<int> fixed_right_arg, | 7891 Maybe<int> fixed_right_arg) { |
| 7857 bool binop_stub) { | |
| 7858 | 7892 |
| 7859 Representation left_rep = Representation::FromType(left_type); | 7893 Representation left_rep = Representation::FromType(left_type); |
| 7860 Representation right_rep = Representation::FromType(right_type); | 7894 Representation right_rep = Representation::FromType(right_type); |
| 7861 | 7895 |
| 7862 bool maybe_string_add = op == Token::ADD && | 7896 bool maybe_string_add = op == Token::ADD && |
| 7863 (left_type->Maybe(Type::String()) || | 7897 (left_type->Maybe(Type::String()) || |
| 7864 right_type->Maybe(Type::String())); | 7898 right_type->Maybe(Type::String())); |
| 7865 | 7899 |
| 7866 if (left_type->Is(Type::None())) { | 7900 if (left_type->Is(Type::None())) { |
| 7867 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | 7901 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", |
| 7868 Deoptimizer::SOFT); | 7902 Deoptimizer::SOFT); |
| 7869 // TODO(rossberg): we should be able to get rid of non-continuous | 7903 // TODO(rossberg): we should be able to get rid of non-continuous |
| 7870 // defaults. | 7904 // defaults. |
| 7871 left_type = handle(Type::Any(), isolate()); | 7905 left_type = handle(Type::Any(), isolate()); |
| 7872 } else { | 7906 } else { |
| 7873 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); | 7907 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); |
| 7874 left_rep = Representation::FromType(left_type); | 7908 left_rep = Representation::FromType(left_type); |
| 7875 } | 7909 } |
| 7876 | 7910 |
| 7877 if (right_type->Is(Type::None())) { | 7911 if (right_type->Is(Type::None())) { |
| 7878 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", | 7912 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", |
| 7879 Deoptimizer::SOFT); | 7913 Deoptimizer::SOFT); |
| 7880 right_type = handle(Type::Any(), isolate()); | 7914 right_type = handle(Type::Any(), isolate()); |
| 7881 } else { | 7915 } else { |
| 7882 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); | 7916 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); |
| 7883 right_rep = Representation::FromType(right_type); | 7917 right_rep = Representation::FromType(right_type); |
| 7884 } | 7918 } |
| 7885 | 7919 |
| 7886 if (binop_stub) { | |
| 7887 left = EnforceNumberType(left, left_type); | |
| 7888 right = EnforceNumberType(right, right_type); | |
| 7889 } | |
| 7890 | |
| 7891 Representation result_rep = Representation::FromType(result_type); | 7920 Representation result_rep = Representation::FromType(result_type); |
| 7892 | 7921 |
| 7893 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || | 7922 bool is_string_add = op == Token::ADD && |
| 7894 (right_rep.IsTagged() && !right_rep.IsSmi()); | 7923 (left_type->Is(Type::String()) || |
| 7895 bool is_string_add = op == Token::ADD && | 7924 right_type->Is(Type::String())); |
| 7896 (left_type->Is(Type::String()) || | |
| 7897 right_type->Is(Type::String())); | |
| 7898 | 7925 |
| 7899 HInstruction* instr = NULL; | 7926 HInstruction* instr = NULL; |
| 7900 // Only the stub is allowed to call into the runtime, since otherwise we would | 7927 switch (op) { |
| 7901 // inline several instructions (including the two pushes) for every tagged | 7928 case Token::ADD: |
| 7902 // operation in optimized code, which is more expensive, than a stub call. | 7929 if (is_string_add) { |
| 7903 if (binop_stub && is_non_primitive && !is_string_add) { | 7930 StringAddFlags flags = STRING_ADD_CHECK_BOTH; |
| 7904 HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op)); | 7931 if (left_type->Is(Type::String())) { |
| 7905 Add<HPushArgument>(left); | 7932 BuildCheckHeapObject(left); |
| 7906 Add<HPushArgument>(right); | 7933 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
| 7907 instr = NewUncasted<HInvokeFunction>(function, 2); | 7934 flags = STRING_ADD_CHECK_RIGHT; |
| 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); | |
| 7927 } | 7935 } |
| 7928 break; | 7936 if (right_type->Is(Type::String())) { |
| 7929 case Token::SUB: | 7937 BuildCheckHeapObject(right); |
| 7930 instr = NewUncasted<HSub>(left, right); | 7938 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
| 7931 break; | 7939 flags = (flags == STRING_ADD_CHECK_BOTH) |
| 7932 case Token::MUL: | 7940 ? STRING_ADD_CHECK_LEFT : STRING_ADD_CHECK_NONE; |
| 7933 instr = NewUncasted<HMul>(left, right); | 7941 } |
| 7934 break; | 7942 instr = NewUncasted<HStringAdd>(left, right, flags); |
| 7935 case Token::MOD: | 7943 } else { |
| 7936 instr = NewUncasted<HMod>(left, right, fixed_right_arg); | 7944 instr = NewUncasted<HAdd>(left, right); |
| 7937 break; | 7945 } |
| 7938 case Token::DIV: | 7946 break; |
| 7939 instr = NewUncasted<HDiv>(left, right); | 7947 case Token::SUB: |
| 7940 break; | 7948 instr = NewUncasted<HSub>(left, right); |
| 7941 case Token::BIT_XOR: | 7949 break; |
| 7942 case Token::BIT_AND: | 7950 case Token::MUL: |
| 7951 instr = NewUncasted<HMul>(left, right); |
| 7952 break; |
| 7953 case Token::MOD: |
| 7954 instr = NewUncasted<HMod>(left, right, fixed_right_arg); |
| 7955 break; |
| 7956 case Token::DIV: |
| 7957 instr = NewUncasted<HDiv>(left, right); |
| 7958 break; |
| 7959 case Token::BIT_XOR: |
| 7960 case Token::BIT_AND: |
| 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 { |
| 7943 instr = NewUncasted<HBitwise>(op, left, right); | 7970 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); | |
| 7953 } | |
| 7954 break; | |
| 7955 } | 7971 } |
| 7956 case Token::SAR: | 7972 break; |
| 7957 instr = NewUncasted<HSar>(left, right); | |
| 7958 break; | |
| 7959 case Token::SHR: | |
| 7960 instr = NewUncasted<HShr>(left, right); | |
| 7961 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && | |
| 7962 CanBeZero(right)) { | |
| 7963 graph()->RecordUint32Instruction(instr); | |
| 7964 } | |
| 7965 break; | |
| 7966 case Token::SHL: | |
| 7967 instr = NewUncasted<HShl>(left, right); | |
| 7968 break; | |
| 7969 default: | |
| 7970 UNREACHABLE(); | |
| 7971 } | 7973 } |
| 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(); |
| 7972 } | 7989 } |
| 7973 | 7990 |
| 7974 if (instr->IsBinaryOperation()) { | 7991 if (instr->IsBinaryOperation()) { |
| 7975 HBinaryOperation* binop = HBinaryOperation::cast(instr); | 7992 HBinaryOperation* binop = HBinaryOperation::cast(instr); |
| 7976 binop->set_observed_input_representation(1, left_rep); | 7993 binop->set_observed_input_representation(1, left_rep); |
| 7977 binop->set_observed_input_representation(2, right_rep); | 7994 binop->set_observed_input_representation(2, right_rep); |
| 7978 binop->initialize_output_representation(result_rep); | 7995 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 } | |
| 7992 } | 7996 } |
| 7993 return instr; | 7997 return instr; |
| 7994 } | 7998 } |
| 7995 | 7999 |
| 7996 | 8000 |
| 7997 // Check for the form (%_ClassOf(foo) === 'BarClass'). | 8001 // Check for the form (%_ClassOf(foo) === 'BarClass'). |
| 7998 static bool IsClassOfTest(CompareOperation* expr) { | 8002 static bool IsClassOfTest(CompareOperation* expr) { |
| 7999 if (expr->op() != Token::EQ_STRICT) return false; | 8003 if (expr->op() != Token::EQ_STRICT) return false; |
| 8000 CallRuntime* call = expr->left()->AsCallRuntime(); | 8004 CallRuntime* call = expr->left()->AsCallRuntime(); |
| 8001 if (call == NULL) return false; | 8005 if (call == NULL) return false; |
| (...skipping 1873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9875 if (ShouldProduceTraceOutput()) { | 9879 if (ShouldProduceTraceOutput()) { |
| 9876 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9880 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 9877 } | 9881 } |
| 9878 | 9882 |
| 9879 #ifdef DEBUG | 9883 #ifdef DEBUG |
| 9880 graph_->Verify(false); // No full verify. | 9884 graph_->Verify(false); // No full verify. |
| 9881 #endif | 9885 #endif |
| 9882 } | 9886 } |
| 9883 | 9887 |
| 9884 } } // namespace v8::internal | 9888 } } // namespace v8::internal |
| OLD | NEW |