Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(417)

Side by Side Diff: src/hydrogen.cc

Issue 24072013: Hydrogenisation of binops (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: fix overwrite mode & better result typefeedback Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698