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

Side by Side Diff: src/hydrogen.cc

Issue 16361015: Migrate Compare ICs to new type rep (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebased Created 7 years, 6 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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 1680 matching lines...) Expand 10 before | Expand all | Expand 10 after
1691 kind)); 1691 kind));
1692 } 1692 }
1693 } 1693 }
1694 1694
1695 return object; 1695 return object;
1696 } 1696 }
1697 1697
1698 1698
1699 void HGraphBuilder::BuildCompareNil( 1699 void HGraphBuilder::BuildCompareNil(
1700 HValue* value, 1700 HValue* value,
1701 CompareNilICStub::Types types, 1701 Handle<Type> type,
1702 Handle<Map> map,
1703 int position, 1702 int position,
1704 HIfContinuation* continuation) { 1703 HIfContinuation* continuation) {
1705 IfBuilder if_nil(this, position); 1704 IfBuilder if_nil(this, position);
1706 bool needs_or = false; 1705 bool needs_or = false;
1707 if (types.Contains(CompareNilICStub::NULL_TYPE)) { 1706 if (type->Maybe(Type::Null())) {
1708 if (needs_or) if_nil.Or(); 1707 if (needs_or) if_nil.Or();
1709 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); 1708 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull());
1710 needs_or = true; 1709 needs_or = true;
1711 } 1710 }
1712 if (types.Contains(CompareNilICStub::UNDEFINED)) { 1711 if (type->Maybe(Type::Undefined())) {
1713 if (needs_or) if_nil.Or(); 1712 if (needs_or) if_nil.Or();
1714 if_nil.If<HCompareObjectEqAndBranch>(value, 1713 if_nil.If<HCompareObjectEqAndBranch>(value,
1715 graph()->GetConstantUndefined()); 1714 graph()->GetConstantUndefined());
1716 needs_or = true; 1715 needs_or = true;
1717 } 1716 }
1718 // Handle either undetectable or monomorphic, not both. 1717 if (type->Maybe(Type::Undetectable())) {
1719 ASSERT(!types.Contains(CompareNilICStub::UNDETECTABLE) ||
Jakob Kummerow 2013/06/11 17:58:07 I think you could preserve this ASSERT: if (typ
rossberg 2013/06/12 17:21:32 No, as discussed offline, this would no longer be
1720 !types.Contains(CompareNilICStub::MONOMORPHIC_MAP));
1721 if (types.Contains(CompareNilICStub::UNDETECTABLE)) {
1722 if (needs_or) if_nil.Or(); 1718 if (needs_or) if_nil.Or();
1723 if_nil.If<HIsUndetectableAndBranch>(value); 1719 if_nil.If<HIsUndetectableAndBranch>(value);
1724 } else { 1720 } else {
1725 if_nil.Then(); 1721 if_nil.Then();
1726 if_nil.Else(); 1722 if_nil.Else();
1727 if (!map.is_null() && types.Contains(CompareNilICStub::MONOMORPHIC_MAP)) { 1723 if (type->NumClasses() == 1) {
1728 BuildCheckNonSmi(value); 1724 BuildCheckNonSmi(value);
1729 // For ICs, the map checked below is a sentinel map that gets replaced by 1725 // For ICs, the map checked below is a sentinel map that gets replaced by
1730 // the monomorphic map when the code is used as a template to generate a 1726 // the monomorphic map when the code is used as a template to generate a
1731 // new IC. For optimized functions, there is no sentinel map, the map 1727 // new IC. For optimized functions, there is no sentinel map, the map
1732 // emitted below is the actual monomorphic map. 1728 // emitted below is the actual monomorphic map.
1733 BuildCheckMap(value, map); 1729 BuildCheckMap(value, type->Classes().Get());
1734 } else { 1730 } else {
1735 if_nil.Deopt(); 1731 if_nil.Deopt();
1736 } 1732 }
1737 } 1733 }
1738 1734
1739 if_nil.CaptureContinuation(continuation); 1735 if_nil.CaptureContinuation(continuation);
1740 } 1736 }
1741 1737
1742 1738
1743 HValue* HGraphBuilder::BuildCreateAllocationSiteInfo(HValue* previous_object, 1739 HValue* HGraphBuilder::BuildCreateAllocationSiteInfo(HValue* previous_object,
(...skipping 3276 matching lines...) Expand 10 before | Expand all | Expand 10 after
5020 // Generate a compare and branch. 5016 // Generate a compare and branch.
5021 CHECK_ALIVE(VisitForValue(clause->label())); 5017 CHECK_ALIVE(VisitForValue(clause->label()));
5022 HValue* label_value = Pop(); 5018 HValue* label_value = Pop();
5023 5019
5024 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); 5020 HBasicBlock* next_test_block = graph()->CreateBasicBlock();
5025 HBasicBlock* body_block = graph()->CreateBasicBlock(); 5021 HBasicBlock* body_block = graph()->CreateBasicBlock();
5026 5022
5027 HControlInstruction* compare; 5023 HControlInstruction* compare;
5028 5024
5029 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { 5025 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) {
5030 if (!clause->IsSmiCompare()) { 5026 if (!clause->compare_type()->Is(Type::Integer31())) {
5031 AddSoftDeoptimize(); 5027 AddSoftDeoptimize();
5032 } 5028 }
5033 5029
5034 HCompareIDAndBranch* compare_ = 5030 HCompareIDAndBranch* compare_ =
5035 new(zone()) HCompareIDAndBranch(tag_value, 5031 new(zone()) HCompareIDAndBranch(tag_value,
5036 label_value, 5032 label_value,
5037 Token::EQ_STRICT); 5033 Token::EQ_STRICT);
5038 compare_->set_observed_input_representation( 5034 compare_->set_observed_input_representation(
5039 Representation::Integer32(), Representation::Integer32()); 5035 Representation::Integer32(), Representation::Integer32());
5040 compare = compare_; 5036 compare = compare_;
(...skipping 2950 matching lines...) Expand 10 before | Expand all | Expand 10 after
7991 &target_info, 7987 &target_info,
7992 target_shared); 7988 target_shared);
7993 } 7989 }
7994 7990
7995 // ---------------------------------------------------------------- 7991 // ----------------------------------------------------------------
7996 // After this point, we've made a decision to inline this function (so 7992 // After this point, we've made a decision to inline this function (so
7997 // TryInline should always return true). 7993 // TryInline should always return true).
7998 7994
7999 // Type-check the inlined function. 7995 // Type-check the inlined function.
8000 ASSERT(target_shared->has_deoptimization_support()); 7996 ASSERT(target_shared->has_deoptimization_support());
8001 AstTyper::Type(&target_info); 7997 AstTyper::Run(&target_info);
8002 7998
8003 // Save the pending call context. Set up new one for the inlined function. 7999 // Save the pending call context. Set up new one for the inlined function.
8004 // The function state is new-allocated because we need to delete it 8000 // The function state is new-allocated because we need to delete it
8005 // in two different places. 8001 // in two different places.
8006 FunctionState* target_state = new FunctionState( 8002 FunctionState* target_state = new FunctionState(
8007 this, &target_info, inlining_kind); 8003 this, &target_info, inlining_kind);
8008 8004
8009 HConstant* undefined = graph()->GetConstantUndefined(); 8005 HConstant* undefined = graph()->GetConstantUndefined();
8010 bool undefined_receiver = HEnvironment::UseUndefinedReceiver( 8006 bool undefined_receiver = HEnvironment::UseUndefinedReceiver(
8011 target, function, call_kind, inlining_kind); 8007 target, function, call_kind, inlining_kind);
(...skipping 1669 matching lines...) Expand 10 before | Expand all | Expand 10 after
9681 CHECK_ALIVE(VisitForValue(expr->left())); 9677 CHECK_ALIVE(VisitForValue(expr->left()));
9682 CHECK_ALIVE(VisitForValue(expr->right())); 9678 CHECK_ALIVE(VisitForValue(expr->right()));
9683 HValue* right = Pop(); 9679 HValue* right = Pop();
9684 HValue* left = Pop(); 9680 HValue* left = Pop();
9685 HInstruction* instr = BuildBinaryOperation(expr, left, right); 9681 HInstruction* instr = BuildBinaryOperation(expr, left, right);
9686 instr->set_position(expr->position()); 9682 instr->set_position(expr->position());
9687 return ast_context()->ReturnInstruction(instr, expr->id()); 9683 return ast_context()->ReturnInstruction(instr, expr->id());
9688 } 9684 }
9689 9685
9690 9686
9687 // TODO(rossberg): this should die eventually.
9691 Representation HOptimizedGraphBuilder::ToRepresentation(TypeInfo info) { 9688 Representation HOptimizedGraphBuilder::ToRepresentation(TypeInfo info) {
9692 if (info.IsUninitialized()) return Representation::None(); 9689 if (info.IsUninitialized()) return Representation::None();
9693 if (info.IsSmi()) return Representation::Integer32(); 9690 if (info.IsSmi()) return Representation::Integer32();
9694 if (info.IsInteger32()) return Representation::Integer32(); 9691 if (info.IsInteger32()) return Representation::Integer32();
9695 if (info.IsDouble()) return Representation::Double(); 9692 if (info.IsDouble()) return Representation::Double();
9696 if (info.IsNumber()) return Representation::Double(); 9693 if (info.IsNumber()) return Representation::Double();
9697 return Representation::Tagged(); 9694 return Representation::Tagged();
9698 } 9695 }
9699 9696
9700 9697
9698 Representation HOptimizedGraphBuilder::ToRepresentation(Handle<Type> type) {
9699 if (type->Is(Type::None())) return Representation::None();
9700 if (type->Is(Type::Integer32())) return Representation::Integer32();
9701 if (type->Is(Type::Number())) return Representation::Double();
9702 return Representation::Tagged();
9703 }
9704
9705
9701 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, 9706 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
9702 HTypeof* typeof_expr, 9707 HTypeof* typeof_expr,
9703 Handle<String> check) { 9708 Handle<String> check) {
9704 // Note: The HTypeof itself is removed during canonicalization, if possible. 9709 // Note: The HTypeof itself is removed during canonicalization, if possible.
9705 HValue* value = typeof_expr->value(); 9710 HValue* value = typeof_expr->value();
9706 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); 9711 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check);
9707 instr->set_position(expr->position()); 9712 instr->set_position(expr->position());
9708 return ast_context()->ReturnControl(instr, expr->id()); 9713 return ast_context()->ReturnControl(instr, expr->id());
9709 } 9714 }
9710 9715
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
9780 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9785 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9781 HValue* value = Pop(); 9786 HValue* value = Pop();
9782 Literal* literal = expr->right()->AsLiteral(); 9787 Literal* literal = expr->right()->AsLiteral();
9783 Handle<String> rhs = Handle<String>::cast(literal->handle()); 9788 Handle<String> rhs = Handle<String>::cast(literal->handle());
9784 HClassOfTestAndBranch* instr = 9789 HClassOfTestAndBranch* instr =
9785 new(zone()) HClassOfTestAndBranch(value, rhs); 9790 new(zone()) HClassOfTestAndBranch(value, rhs);
9786 instr->set_position(expr->position()); 9791 instr->set_position(expr->position());
9787 return ast_context()->ReturnControl(instr, expr->id()); 9792 return ast_context()->ReturnControl(instr, expr->id());
9788 } 9793 }
9789 9794
9790 TypeInfo left_type = expr->left_type(); 9795 Handle<Type> left_type = expr->left_type();
9791 TypeInfo right_type = expr->right_type(); 9796 Handle<Type> right_type = expr->right_type();
9792 TypeInfo overall_type = expr->overall_type(); 9797 Handle<Type> overall_type = expr->overall_type();
9793 Representation combined_rep = ToRepresentation(overall_type); 9798 Representation combined_rep = ToRepresentation(overall_type);
9794 Representation left_rep = ToRepresentation(left_type); 9799 Representation left_rep = ToRepresentation(left_type);
9795 Representation right_rep = ToRepresentation(right_type); 9800 Representation right_rep = ToRepresentation(right_type);
9796 // Check if this expression was ever executed according to type feedback. 9801 // Check if this expression was ever executed according to type feedback.
9797 // Note that for the special typeof/null/undefined cases we get unknown here. 9802 // Note that for the special typeof/null/undefined cases we get unknown here.
9798 if (overall_type.IsUninitialized()) { 9803 if (overall_type->Is(Type::None())) {
9799 AddSoftDeoptimize(); 9804 AddSoftDeoptimize();
9800 overall_type = left_type = right_type = TypeInfo::Unknown(); 9805 overall_type = left_type = right_type = handle(Type::Any(), isolate());
9801 } 9806 }
9802 9807
9803 CHECK_ALIVE(VisitForValue(expr->left())); 9808 CHECK_ALIVE(VisitForValue(expr->left()));
9804 CHECK_ALIVE(VisitForValue(expr->right())); 9809 CHECK_ALIVE(VisitForValue(expr->right()));
9805 9810
9806 HValue* context = environment()->LookupContext(); 9811 HValue* context = environment()->LookupContext();
9807 HValue* right = Pop(); 9812 HValue* right = Pop();
9808 HValue* left = Pop(); 9813 HValue* left = Pop();
9809 Token::Value op = expr->op(); 9814 Token::Value op = expr->op();
9810 9815
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
9862 AddInstruction(new(zone()) HCheckFunction(right, target)); 9867 AddInstruction(new(zone()) HCheckFunction(right, target));
9863 HInstanceOfKnownGlobal* result = 9868 HInstanceOfKnownGlobal* result =
9864 new(zone()) HInstanceOfKnownGlobal(context, left, target); 9869 new(zone()) HInstanceOfKnownGlobal(context, left, target);
9865 result->set_position(expr->position()); 9870 result->set_position(expr->position());
9866 return ast_context()->ReturnInstruction(result, expr->id()); 9871 return ast_context()->ReturnInstruction(result, expr->id());
9867 } 9872 }
9868 } else if (op == Token::IN) { 9873 } else if (op == Token::IN) {
9869 HIn* result = new(zone()) HIn(context, left, right); 9874 HIn* result = new(zone()) HIn(context, left, right);
9870 result->set_position(expr->position()); 9875 result->set_position(expr->position());
9871 return ast_context()->ReturnInstruction(result, expr->id()); 9876 return ast_context()->ReturnInstruction(result, expr->id());
9872 } else if (overall_type.IsNonPrimitive()) { 9877 } else if (overall_type->Is(Type::Receiver())) {
9873 switch (op) { 9878 switch (op) {
9874 case Token::EQ: 9879 case Token::EQ:
9875 case Token::EQ_STRICT: { 9880 case Token::EQ_STRICT: {
9876 // Can we get away with map check and not instance type check? 9881 // Can we get away with map check and not instance type check?
9877 Handle<Map> map = expr->map(); 9882 if (overall_type->IsClass()) {
9878 if (!map.is_null()) { 9883 Handle<Map> map = overall_type->AsClass();
9879 AddCheckMapsWithTransitions(left, map); 9884 AddCheckMapsWithTransitions(left, map);
9880 AddCheckMapsWithTransitions(right, map); 9885 AddCheckMapsWithTransitions(right, map);
9881 HCompareObjectEqAndBranch* result = 9886 HCompareObjectEqAndBranch* result =
9882 new(zone()) HCompareObjectEqAndBranch(left, right); 9887 new(zone()) HCompareObjectEqAndBranch(left, right);
9883 result->set_position(expr->position()); 9888 result->set_position(expr->position());
9884 return ast_context()->ReturnControl(result, expr->id()); 9889 return ast_context()->ReturnControl(result, expr->id());
9885 } else { 9890 } else {
9886 BuildCheckNonSmi(left); 9891 BuildCheckNonSmi(left);
9887 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); 9892 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone()));
9888 BuildCheckNonSmi(right); 9893 BuildCheckNonSmi(right);
9889 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); 9894 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone()));
9890 HCompareObjectEqAndBranch* result = 9895 HCompareObjectEqAndBranch* result =
9891 new(zone()) HCompareObjectEqAndBranch(left, right); 9896 new(zone()) HCompareObjectEqAndBranch(left, right);
9892 result->set_position(expr->position()); 9897 result->set_position(expr->position());
9893 return ast_context()->ReturnControl(result, expr->id()); 9898 return ast_context()->ReturnControl(result, expr->id());
9894 } 9899 }
9895 } 9900 }
9896 default: 9901 default:
9897 return Bailout("Unsupported non-primitive compare"); 9902 return Bailout("Unsupported non-primitive compare");
9898 } 9903 }
9899 } else if (overall_type.IsInternalizedString() && 9904 } else if (overall_type->Is(Type::InternalizedString()) &&
9900 Token::IsEqualityOp(op)) { 9905 Token::IsEqualityOp(op)) {
9901 BuildCheckNonSmi(left); 9906 BuildCheckNonSmi(left);
9902 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); 9907 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone()));
9903 BuildCheckNonSmi(right); 9908 BuildCheckNonSmi(right);
9904 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); 9909 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone()));
9905 HCompareObjectEqAndBranch* result = 9910 HCompareObjectEqAndBranch* result =
9906 new(zone()) HCompareObjectEqAndBranch(left, right); 9911 new(zone()) HCompareObjectEqAndBranch(left, right);
9907 result->set_position(expr->position()); 9912 result->set_position(expr->position());
9908 return ast_context()->ReturnControl(result, expr->id()); 9913 return ast_context()->ReturnControl(result, expr->id());
9909 } else { 9914 } else {
(...skipping 14 matching lines...) Expand all
9924 } 9929 }
9925 } 9930 }
9926 9931
9927 9932
9928 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, 9933 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
9929 HValue* value, 9934 HValue* value,
9930 NilValue nil) { 9935 NilValue nil) {
9931 ASSERT(!HasStackOverflow()); 9936 ASSERT(!HasStackOverflow());
9932 ASSERT(current_block() != NULL); 9937 ASSERT(current_block() != NULL);
9933 ASSERT(current_block()->HasPredecessor()); 9938 ASSERT(current_block()->HasPredecessor());
9939 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
9934 HIfContinuation continuation; 9940 HIfContinuation continuation;
9935 CompareNilICStub::Types types;
9936 if (expr->op() == Token::EQ_STRICT) { 9941 if (expr->op() == Token::EQ_STRICT) {
9937 IfBuilder if_nil(this); 9942 IfBuilder if_nil(this);
9938 if_nil.If<HCompareObjectEqAndBranch>( 9943 if_nil.If<HCompareObjectEqAndBranch>(
9939 value, (nil == kNullValue) ? graph()->GetConstantNull() 9944 value, (nil == kNullValue) ? graph()->GetConstantNull()
9940 : graph()->GetConstantUndefined()); 9945 : graph()->GetConstantUndefined());
9941 if_nil.Then(); 9946 if_nil.Then();
9942 if_nil.Else(); 9947 if_nil.Else();
9943 if_nil.CaptureContinuation(&continuation); 9948 if_nil.CaptureContinuation(&continuation);
9944 return ast_context()->ReturnContinuation(&continuation, expr->id()); 9949 return ast_context()->ReturnContinuation(&continuation, expr->id());
9945 } 9950 }
9946 types = CompareNilICStub::Types(expr->compare_nil_types()); 9951 Handle<Type> type = expr->compare_nil_type()->Is(Type::None())
9947 if (types.IsEmpty()) types = CompareNilICStub::Types::FullCompare(); 9952 ? handle(Type::Any(), isolate_) : expr->compare_nil_type();
9948 Handle<Map> map_handle = expr->map(); 9953 BuildCompareNil(value, type, expr->position(), &continuation);
9949 BuildCompareNil(value, types, map_handle,
9950 expr->position(), &continuation);
9951 return ast_context()->ReturnContinuation(&continuation, expr->id()); 9954 return ast_context()->ReturnContinuation(&continuation, expr->id());
9952 } 9955 }
9953 9956
9954 9957
9955 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { 9958 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
9956 // If we share optimized code between different closures, the 9959 // If we share optimized code between different closures, the
9957 // this-function is not a constant, except inside an inlined body. 9960 // this-function is not a constant, except inside an inlined body.
9958 if (function_state()->outer() != NULL) { 9961 if (function_state()->outer() != NULL) {
9959 return new(zone()) HConstant( 9962 return new(zone()) HConstant(
9960 function_state()->compilation_info()->closure(), 9963 function_state()->compilation_info()->closure(),
(...skipping 1652 matching lines...) Expand 10 before | Expand all | Expand 10 after
11613 } 11616 }
11614 } 11617 }
11615 11618
11616 #ifdef DEBUG 11619 #ifdef DEBUG
11617 if (graph_ != NULL) graph_->Verify(false); // No full verify. 11620 if (graph_ != NULL) graph_->Verify(false); // No full verify.
11618 if (allocator_ != NULL) allocator_->Verify(); 11621 if (allocator_ != NULL) allocator_->Verify();
11619 #endif 11622 #endif
11620 } 11623 }
11621 11624
11622 } } // namespace v8::internal 11625 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698