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 7478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7489 CreateJoin(materialize_false, materialize_true, expr->id()); | 7489 CreateJoin(materialize_false, materialize_true, expr->id()); |
7490 set_current_block(join); | 7490 set_current_block(join); |
7491 if (join != NULL) return ast_context()->ReturnValue(Pop()); | 7491 if (join != NULL) return ast_context()->ReturnValue(Pop()); |
7492 } | 7492 } |
7493 | 7493 |
7494 | 7494 |
7495 HInstruction* HOptimizedGraphBuilder::BuildIncrement( | 7495 HInstruction* HOptimizedGraphBuilder::BuildIncrement( |
7496 bool returns_original_input, | 7496 bool returns_original_input, |
7497 CountOperation* expr) { | 7497 CountOperation* expr) { |
7498 // The input to the count operation is on top of the expression stack. | 7498 // The input to the count operation is on top of the expression stack. |
7499 TypeInfo info = expr->type(); | 7499 Handle<Type> info = expr->type(); |
7500 Representation rep = Representation::FromType(info); | 7500 Representation rep = Representation::FromType(info); |
7501 if (rep.IsNone() || rep.IsTagged()) { | 7501 if (rep.IsNone() || rep.IsTagged()) { |
7502 rep = Representation::Smi(); | 7502 rep = Representation::Smi(); |
7503 } | 7503 } |
7504 | 7504 |
7505 if (returns_original_input) { | 7505 if (returns_original_input) { |
7506 // We need an explicit HValue representing ToNumber(input). The | 7506 // We need an explicit HValue representing ToNumber(input). The |
7507 // actual HChange instruction we need is (sometimes) added in a later | 7507 // actual HChange instruction we need is (sometimes) added in a later |
7508 // phase, so it is not available now to be used as an input to HAdd and | 7508 // phase, so it is not available now to be used as an input to HAdd and |
7509 // as the return value. | 7509 // as the return value. |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7853 } | 7853 } |
7854 | 7854 |
7855 | 7855 |
7856 HInstruction* HGraphBuilder::BuildBinaryOperation( | 7856 HInstruction* HGraphBuilder::BuildBinaryOperation( |
7857 Token::Value op, | 7857 Token::Value op, |
7858 HValue* left, | 7858 HValue* left, |
7859 HValue* right, | 7859 HValue* right, |
7860 Handle<Type> left_type, | 7860 Handle<Type> left_type, |
7861 Handle<Type> right_type, | 7861 Handle<Type> right_type, |
7862 Handle<Type> result_type, | 7862 Handle<Type> result_type, |
7863 Maybe<int> fixed_right_arg) { | 7863 Maybe<int> fixed_right_arg, |
| 7864 bool binop_stub) { |
7864 | 7865 |
7865 Representation left_rep = Representation::FromType(left_type); | 7866 Representation left_rep = Representation::FromType(left_type); |
7866 Representation right_rep = Representation::FromType(right_type); | 7867 Representation right_rep = Representation::FromType(right_type); |
7867 | 7868 |
7868 bool maybe_string_add = op == Token::ADD && | 7869 bool maybe_string_add = op == Token::ADD && |
7869 (left_type->Maybe(Type::String()) || | 7870 (left_type->Maybe(Type::String()) || |
7870 right_type->Maybe(Type::String())); | 7871 right_type->Maybe(Type::String())); |
7871 | 7872 |
7872 if (left_type->Is(Type::None())) { | 7873 if (left_type->Is(Type::None())) { |
7873 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | 7874 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", |
7874 Deoptimizer::SOFT); | 7875 Deoptimizer::SOFT); |
7875 // TODO(rossberg): we should be able to get rid of non-continuous | 7876 // TODO(rossberg): we should be able to get rid of non-continuous |
7876 // defaults. | 7877 // defaults. |
7877 left_type = handle(Type::Any(), isolate()); | 7878 left_type = handle(Type::Any(), isolate()); |
7878 } else { | 7879 } else { |
7879 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); | 7880 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); |
7880 left_rep = Representation::FromType(left_type); | 7881 left_rep = Representation::FromType(left_type); |
7881 } | 7882 } |
7882 | 7883 |
7883 if (right_type->Is(Type::None())) { | 7884 if (right_type->Is(Type::None())) { |
7884 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", | 7885 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", |
7885 Deoptimizer::SOFT); | 7886 Deoptimizer::SOFT); |
7886 right_type = handle(Type::Any(), isolate()); | 7887 right_type = handle(Type::Any(), isolate()); |
7887 } else { | 7888 } else { |
7888 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); | 7889 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); |
7889 right_rep = Representation::FromType(right_type); | 7890 right_rep = Representation::FromType(right_type); |
7890 } | 7891 } |
7891 | 7892 |
| 7893 if (binop_stub) { |
| 7894 left = EnforceNumberType(left, left_type); |
| 7895 right = EnforceNumberType(right, right_type); |
| 7896 } |
| 7897 |
7892 Representation result_rep = Representation::FromType(result_type); | 7898 Representation result_rep = Representation::FromType(result_type); |
7893 | 7899 |
7894 bool is_string_add = op == Token::ADD && | 7900 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || |
7895 (left_type->Is(Type::String()) || | 7901 (right_rep.IsTagged() && !right_rep.IsSmi()); |
7896 right_type->Is(Type::String())); | 7902 bool is_string_add = op == Token::ADD && |
| 7903 (left_type->Is(Type::String()) || |
| 7904 right_type->Is(Type::String())); |
7897 | 7905 |
7898 HInstruction* instr = NULL; | 7906 HInstruction* instr = NULL; |
7899 switch (op) { | 7907 // Only the stub is allowed to call into the runtime, since otherwise we would |
7900 case Token::ADD: | 7908 // inline several instructions (including the two pushes) for every tagged |
7901 if (is_string_add) { | 7909 // operation in optimized code, which is more expensive, than a stub call. |
7902 StringAddFlags flags = STRING_ADD_CHECK_BOTH; | 7910 if (binop_stub && is_non_primitive && !is_string_add) { |
7903 if (left_type->Is(Type::String())) { | 7911 HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op)); |
7904 BuildCheckHeapObject(left); | 7912 Add<HPushArgument>(left); |
7905 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 7913 Add<HPushArgument>(right); |
7906 flags = STRING_ADD_CHECK_RIGHT; | 7914 instr = NewUncasted<HInvokeFunction>(function, 2); |
| 7915 } else { |
| 7916 switch (op) { |
| 7917 case Token::ADD: |
| 7918 if (is_string_add) { |
| 7919 StringAddFlags flags = STRING_ADD_CHECK_BOTH; |
| 7920 if (left_type->Is(Type::String())) { |
| 7921 BuildCheckHeapObject(left); |
| 7922 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
| 7923 flags = STRING_ADD_CHECK_RIGHT; |
| 7924 } |
| 7925 if (right_type->Is(Type::String())) { |
| 7926 BuildCheckHeapObject(right); |
| 7927 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
| 7928 flags = (flags == STRING_ADD_CHECK_BOTH) |
| 7929 ? STRING_ADD_CHECK_LEFT : STRING_ADD_CHECK_NONE; |
| 7930 } |
| 7931 instr = NewUncasted<HStringAdd>(left, right, flags); |
| 7932 } else { |
| 7933 instr = NewUncasted<HAdd>(left, right); |
7907 } | 7934 } |
7908 if (right_type->Is(Type::String())) { | 7935 break; |
7909 BuildCheckHeapObject(right); | 7936 case Token::SUB: |
7910 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 7937 instr = NewUncasted<HSub>(left, right); |
7911 flags = (flags == STRING_ADD_CHECK_BOTH) | 7938 break; |
7912 ? STRING_ADD_CHECK_LEFT : STRING_ADD_CHECK_NONE; | 7939 case Token::MUL: |
| 7940 instr = NewUncasted<HMul>(left, right); |
| 7941 break; |
| 7942 case Token::MOD: |
| 7943 instr = NewUncasted<HMod>(left, right, fixed_right_arg); |
| 7944 break; |
| 7945 case Token::DIV: |
| 7946 instr = NewUncasted<HDiv>(left, right); |
| 7947 break; |
| 7948 case Token::BIT_XOR: |
| 7949 case Token::BIT_AND: |
| 7950 instr = NewUncasted<HBitwise>(op, left, right); |
| 7951 break; |
| 7952 case Token::BIT_OR: { |
| 7953 HValue* operand, *shift_amount; |
| 7954 if (left_type->Is(Type::Signed32()) && |
| 7955 right_type->Is(Type::Signed32()) && |
| 7956 MatchRotateRight(left, right, &operand, &shift_amount)) { |
| 7957 instr = NewUncasted<HRor>(operand, shift_amount); |
| 7958 } else { |
| 7959 instr = NewUncasted<HBitwise>(op, left, right); |
7913 } | 7960 } |
7914 instr = NewUncasted<HStringAdd>(left, right, flags); | 7961 break; |
7915 } else { | |
7916 instr = NewUncasted<HAdd>(left, right); | |
7917 } | 7962 } |
7918 break; | 7963 case Token::SAR: |
7919 case Token::SUB: | 7964 instr = NewUncasted<HSar>(left, right); |
7920 instr = NewUncasted<HSub>(left, right); | 7965 break; |
7921 break; | 7966 case Token::SHR: |
7922 case Token::MUL: | 7967 instr = NewUncasted<HShr>(left, right); |
7923 instr = NewUncasted<HMul>(left, right); | 7968 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && |
7924 break; | 7969 CanBeZero(right)) { |
7925 case Token::MOD: | 7970 graph()->RecordUint32Instruction(instr); |
7926 instr = NewUncasted<HMod>(left, right, fixed_right_arg); | 7971 } |
7927 break; | 7972 break; |
7928 case Token::DIV: | 7973 case Token::SHL: |
7929 instr = NewUncasted<HDiv>(left, right); | 7974 instr = NewUncasted<HShl>(left, right); |
7930 break; | 7975 break; |
7931 case Token::BIT_XOR: | 7976 default: |
7932 case Token::BIT_AND: | 7977 UNREACHABLE(); |
7933 instr = NewUncasted<HBitwise>(op, left, right); | |
7934 break; | |
7935 case Token::BIT_OR: { | |
7936 HValue* operand, *shift_amount; | |
7937 if (left_type->Is(Type::Signed32()) && | |
7938 right_type->Is(Type::Signed32()) && | |
7939 MatchRotateRight(left, right, &operand, &shift_amount)) { | |
7940 instr = NewUncasted<HRor>(operand, shift_amount); | |
7941 } else { | |
7942 instr = NewUncasted<HBitwise>(op, left, right); | |
7943 } | |
7944 break; | |
7945 } | 7978 } |
7946 case Token::SAR: | |
7947 instr = NewUncasted<HSar>(left, right); | |
7948 break; | |
7949 case Token::SHR: | |
7950 instr = NewUncasted<HShr>(left, right); | |
7951 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && | |
7952 CanBeZero(right)) { | |
7953 graph()->RecordUint32Instruction(instr); | |
7954 } | |
7955 break; | |
7956 case Token::SHL: | |
7957 instr = NewUncasted<HShl>(left, right); | |
7958 break; | |
7959 default: | |
7960 UNREACHABLE(); | |
7961 } | 7979 } |
7962 | 7980 |
7963 if (instr->IsBinaryOperation()) { | 7981 if (instr->IsBinaryOperation()) { |
7964 HBinaryOperation* binop = HBinaryOperation::cast(instr); | 7982 HBinaryOperation* binop = HBinaryOperation::cast(instr); |
7965 binop->set_observed_input_representation(1, left_rep); | 7983 binop->set_observed_input_representation(1, left_rep); |
7966 binop->set_observed_input_representation(2, right_rep); | 7984 binop->set_observed_input_representation(2, right_rep); |
7967 binop->initialize_output_representation(result_rep); | 7985 binop->initialize_output_representation(result_rep); |
| 7986 if (binop_stub) { |
| 7987 // Stub should not call into stub. |
| 7988 instr->SetFlag(HValue::kCannotBeTagged); |
| 7989 // And should truncate on HForceRepresentation already. |
| 7990 if (left->IsForceRepresentation()) { |
| 7991 left->CopyFlag(HValue::kTruncatingToSmi, instr); |
| 7992 left->CopyFlag(HValue::kTruncatingToInt32, instr); |
| 7993 } |
| 7994 if (right->IsForceRepresentation()) { |
| 7995 right->CopyFlag(HValue::kTruncatingToSmi, instr); |
| 7996 right->CopyFlag(HValue::kTruncatingToInt32, instr); |
| 7997 } |
| 7998 } |
7968 } | 7999 } |
7969 return instr; | 8000 return instr; |
7970 } | 8001 } |
7971 | 8002 |
7972 | 8003 |
7973 // Check for the form (%_ClassOf(foo) === 'BarClass'). | 8004 // Check for the form (%_ClassOf(foo) === 'BarClass'). |
7974 static bool IsClassOfTest(CompareOperation* expr) { | 8005 static bool IsClassOfTest(CompareOperation* expr) { |
7975 if (expr->op() != Token::EQ_STRICT) return false; | 8006 if (expr->op() != Token::EQ_STRICT) return false; |
7976 CallRuntime* call = expr->left()->AsCallRuntime(); | 8007 CallRuntime* call = expr->left()->AsCallRuntime(); |
7977 if (call == NULL) return false; | 8008 if (call == NULL) return false; |
(...skipping 1873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9851 if (ShouldProduceTraceOutput()) { | 9882 if (ShouldProduceTraceOutput()) { |
9852 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9883 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9853 } | 9884 } |
9854 | 9885 |
9855 #ifdef DEBUG | 9886 #ifdef DEBUG |
9856 graph_->Verify(false); // No full verify. | 9887 graph_->Verify(false); // No full verify. |
9857 #endif | 9888 #endif |
9858 } | 9889 } |
9859 | 9890 |
9860 } } // namespace v8::internal | 9891 } } // namespace v8::internal |
OLD | NEW |