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