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

Side by Side Diff: src/hydrogen.cc

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

Powered by Google App Engine
This is Rietveld 408576698