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

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: Comments 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
« no previous file with comments | « src/hydrogen.h ('k') | src/ic.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) ||
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().Current());
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 3277 matching lines...) Expand 10 before | Expand all | Expand 10 after
5021 // Generate a compare and branch. 5017 // Generate a compare and branch.
5022 CHECK_ALIVE(VisitForValue(clause->label())); 5018 CHECK_ALIVE(VisitForValue(clause->label()));
5023 HValue* label_value = Pop(); 5019 HValue* label_value = Pop();
5024 5020
5025 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); 5021 HBasicBlock* next_test_block = graph()->CreateBasicBlock();
5026 HBasicBlock* body_block = graph()->CreateBasicBlock(); 5022 HBasicBlock* body_block = graph()->CreateBasicBlock();
5027 5023
5028 HControlInstruction* compare; 5024 HControlInstruction* compare;
5029 5025
5030 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { 5026 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) {
5031 if (!clause->IsSmiCompare()) { 5027 if (!clause->compare_type()->Is(Type::Integer31())) {
5032 AddSoftDeoptimize(); 5028 AddSoftDeoptimize();
5033 } 5029 }
5034 5030
5035 HCompareIDAndBranch* compare_ = 5031 HCompareIDAndBranch* compare_ =
5036 new(zone()) HCompareIDAndBranch(tag_value, 5032 new(zone()) HCompareIDAndBranch(tag_value,
5037 label_value, 5033 label_value,
5038 Token::EQ_STRICT); 5034 Token::EQ_STRICT);
5039 compare_->set_observed_input_representation( 5035 compare_->set_observed_input_representation(
5040 Representation::Integer32(), Representation::Integer32()); 5036 Representation::Integer32(), Representation::Integer32());
5041 compare = compare_; 5037 compare = compare_;
(...skipping 2953 matching lines...) Expand 10 before | Expand all | Expand 10 after
7995 &target_info, 7991 &target_info,
7996 target_shared); 7992 target_shared);
7997 } 7993 }
7998 7994
7999 // ---------------------------------------------------------------- 7995 // ----------------------------------------------------------------
8000 // After this point, we've made a decision to inline this function (so 7996 // After this point, we've made a decision to inline this function (so
8001 // TryInline should always return true). 7997 // TryInline should always return true).
8002 7998
8003 // Type-check the inlined function. 7999 // Type-check the inlined function.
8004 ASSERT(target_shared->has_deoptimization_support()); 8000 ASSERT(target_shared->has_deoptimization_support());
8005 AstTyper::Type(&target_info); 8001 AstTyper::Run(&target_info);
8006 8002
8007 // Save the pending call context. Set up new one for the inlined function. 8003 // Save the pending call context. Set up new one for the inlined function.
8008 // The function state is new-allocated because we need to delete it 8004 // The function state is new-allocated because we need to delete it
8009 // in two different places. 8005 // in two different places.
8010 FunctionState* target_state = new FunctionState( 8006 FunctionState* target_state = new FunctionState(
8011 this, &target_info, inlining_kind); 8007 this, &target_info, inlining_kind);
8012 8008
8013 HConstant* undefined = graph()->GetConstantUndefined(); 8009 HConstant* undefined = graph()->GetConstantUndefined();
8014 bool undefined_receiver = HEnvironment::UseUndefinedReceiver( 8010 bool undefined_receiver = HEnvironment::UseUndefinedReceiver(
8015 target, function, call_kind, inlining_kind); 8011 target, function, call_kind, inlining_kind);
(...skipping 1662 matching lines...) Expand 10 before | Expand all | Expand 10 after
9678 CHECK_ALIVE(VisitForValue(expr->left())); 9674 CHECK_ALIVE(VisitForValue(expr->left()));
9679 CHECK_ALIVE(VisitForValue(expr->right())); 9675 CHECK_ALIVE(VisitForValue(expr->right()));
9680 HValue* right = Pop(); 9676 HValue* right = Pop();
9681 HValue* left = Pop(); 9677 HValue* left = Pop();
9682 HInstruction* instr = BuildBinaryOperation(expr, left, right); 9678 HInstruction* instr = BuildBinaryOperation(expr, left, right);
9683 instr->set_position(expr->position()); 9679 instr->set_position(expr->position());
9684 return ast_context()->ReturnInstruction(instr, expr->id()); 9680 return ast_context()->ReturnInstruction(instr, expr->id());
9685 } 9681 }
9686 9682
9687 9683
9684 // TODO(rossberg): this should die eventually.
9688 Representation HOptimizedGraphBuilder::ToRepresentation(TypeInfo info) { 9685 Representation HOptimizedGraphBuilder::ToRepresentation(TypeInfo info) {
9689 if (info.IsUninitialized()) return Representation::None(); 9686 if (info.IsUninitialized()) return Representation::None();
9690 if (info.IsSmi()) return Representation::Integer32(); 9687 if (info.IsSmi()) return Representation::Integer32();
9691 if (info.IsInteger32()) return Representation::Integer32(); 9688 if (info.IsInteger32()) return Representation::Integer32();
9692 if (info.IsDouble()) return Representation::Double(); 9689 if (info.IsDouble()) return Representation::Double();
9693 if (info.IsNumber()) return Representation::Double(); 9690 if (info.IsNumber()) return Representation::Double();
9694 return Representation::Tagged(); 9691 return Representation::Tagged();
9695 } 9692 }
9696 9693
9697 9694
9695 Representation HOptimizedGraphBuilder::ToRepresentation(Handle<Type> type) {
9696 if (type->Is(Type::None())) return Representation::None();
9697 if (type->Is(Type::Integer32())) return Representation::Integer32();
9698 if (type->Is(Type::Number())) return Representation::Double();
9699 return Representation::Tagged();
9700 }
9701
9702
9698 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, 9703 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
9699 HTypeof* typeof_expr, 9704 HTypeof* typeof_expr,
9700 Handle<String> check) { 9705 Handle<String> check) {
9701 // Note: The HTypeof itself is removed during canonicalization, if possible. 9706 // Note: The HTypeof itself is removed during canonicalization, if possible.
9702 HValue* value = typeof_expr->value(); 9707 HValue* value = typeof_expr->value();
9703 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); 9708 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check);
9704 instr->set_position(expr->position()); 9709 instr->set_position(expr->position());
9705 return ast_context()->ReturnControl(instr, expr->id()); 9710 return ast_context()->ReturnControl(instr, expr->id());
9706 } 9711 }
9707 9712
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
9777 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9782 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
9778 HValue* value = Pop(); 9783 HValue* value = Pop();
9779 Literal* literal = expr->right()->AsLiteral(); 9784 Literal* literal = expr->right()->AsLiteral();
9780 Handle<String> rhs = Handle<String>::cast(literal->handle()); 9785 Handle<String> rhs = Handle<String>::cast(literal->handle());
9781 HClassOfTestAndBranch* instr = 9786 HClassOfTestAndBranch* instr =
9782 new(zone()) HClassOfTestAndBranch(value, rhs); 9787 new(zone()) HClassOfTestAndBranch(value, rhs);
9783 instr->set_position(expr->position()); 9788 instr->set_position(expr->position());
9784 return ast_context()->ReturnControl(instr, expr->id()); 9789 return ast_context()->ReturnControl(instr, expr->id());
9785 } 9790 }
9786 9791
9787 TypeInfo left_type = expr->left_type(); 9792 Handle<Type> left_type = expr->left_type();
9788 TypeInfo right_type = expr->right_type(); 9793 Handle<Type> right_type = expr->right_type();
9789 TypeInfo overall_type = expr->overall_type(); 9794 Handle<Type> overall_type = expr->overall_type();
9790 Representation combined_rep = ToRepresentation(overall_type); 9795 Representation combined_rep = ToRepresentation(overall_type);
9791 Representation left_rep = ToRepresentation(left_type); 9796 Representation left_rep = ToRepresentation(left_type);
9792 Representation right_rep = ToRepresentation(right_type); 9797 Representation right_rep = ToRepresentation(right_type);
9793 // Check if this expression was ever executed according to type feedback. 9798 // Check if this expression was ever executed according to type feedback.
9794 // Note that for the special typeof/null/undefined cases we get unknown here. 9799 // Note that for the special typeof/null/undefined cases we get unknown here.
9795 if (overall_type.IsUninitialized()) { 9800 if (overall_type->Is(Type::None())) {
9796 AddSoftDeoptimize(); 9801 AddSoftDeoptimize();
9797 overall_type = left_type = right_type = TypeInfo::Unknown(); 9802 overall_type = left_type = right_type = handle(Type::Any(), isolate());
9798 } 9803 }
9799 9804
9800 CHECK_ALIVE(VisitForValue(expr->left())); 9805 CHECK_ALIVE(VisitForValue(expr->left()));
9801 CHECK_ALIVE(VisitForValue(expr->right())); 9806 CHECK_ALIVE(VisitForValue(expr->right()));
9802 9807
9803 HValue* context = environment()->LookupContext(); 9808 HValue* context = environment()->LookupContext();
9804 HValue* right = Pop(); 9809 HValue* right = Pop();
9805 HValue* left = Pop(); 9810 HValue* left = Pop();
9806 Token::Value op = expr->op(); 9811 Token::Value op = expr->op();
9807 9812
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
9859 AddInstruction(new(zone()) HCheckFunction(right, target)); 9864 AddInstruction(new(zone()) HCheckFunction(right, target));
9860 HInstanceOfKnownGlobal* result = 9865 HInstanceOfKnownGlobal* result =
9861 new(zone()) HInstanceOfKnownGlobal(context, left, target); 9866 new(zone()) HInstanceOfKnownGlobal(context, left, target);
9862 result->set_position(expr->position()); 9867 result->set_position(expr->position());
9863 return ast_context()->ReturnInstruction(result, expr->id()); 9868 return ast_context()->ReturnInstruction(result, expr->id());
9864 } 9869 }
9865 } else if (op == Token::IN) { 9870 } else if (op == Token::IN) {
9866 HIn* result = new(zone()) HIn(context, left, right); 9871 HIn* result = new(zone()) HIn(context, left, right);
9867 result->set_position(expr->position()); 9872 result->set_position(expr->position());
9868 return ast_context()->ReturnInstruction(result, expr->id()); 9873 return ast_context()->ReturnInstruction(result, expr->id());
9869 } else if (overall_type.IsNonPrimitive()) { 9874 } else if (overall_type->Is(Type::Receiver())) {
9870 switch (op) { 9875 switch (op) {
9871 case Token::EQ: 9876 case Token::EQ:
9872 case Token::EQ_STRICT: { 9877 case Token::EQ_STRICT: {
9873 // Can we get away with map check and not instance type check? 9878 // Can we get away with map check and not instance type check?
9874 Handle<Map> map = expr->map(); 9879 if (overall_type->IsClass()) {
9875 if (!map.is_null()) { 9880 Handle<Map> map = overall_type->AsClass();
9876 AddCheckMapsWithTransitions(left, map); 9881 AddCheckMapsWithTransitions(left, map);
9877 AddCheckMapsWithTransitions(right, map); 9882 AddCheckMapsWithTransitions(right, map);
9878 HCompareObjectEqAndBranch* result = 9883 HCompareObjectEqAndBranch* result =
9879 new(zone()) HCompareObjectEqAndBranch(left, right); 9884 new(zone()) HCompareObjectEqAndBranch(left, right);
9880 result->set_position(expr->position()); 9885 result->set_position(expr->position());
9881 return ast_context()->ReturnControl(result, expr->id()); 9886 return ast_context()->ReturnControl(result, expr->id());
9882 } else { 9887 } else {
9883 BuildCheckNonSmi(left); 9888 BuildCheckNonSmi(left);
9884 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); 9889 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone()));
9885 BuildCheckNonSmi(right); 9890 BuildCheckNonSmi(right);
9886 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); 9891 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone()));
9887 HCompareObjectEqAndBranch* result = 9892 HCompareObjectEqAndBranch* result =
9888 new(zone()) HCompareObjectEqAndBranch(left, right); 9893 new(zone()) HCompareObjectEqAndBranch(left, right);
9889 result->set_position(expr->position()); 9894 result->set_position(expr->position());
9890 return ast_context()->ReturnControl(result, expr->id()); 9895 return ast_context()->ReturnControl(result, expr->id());
9891 } 9896 }
9892 } 9897 }
9893 default: 9898 default:
9894 return Bailout("Unsupported non-primitive compare"); 9899 return Bailout("Unsupported non-primitive compare");
9895 } 9900 }
9896 } else if (overall_type.IsInternalizedString() && 9901 } else if (overall_type->Is(Type::InternalizedString()) &&
9897 Token::IsEqualityOp(op)) { 9902 Token::IsEqualityOp(op)) {
9898 BuildCheckNonSmi(left); 9903 BuildCheckNonSmi(left);
9899 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); 9904 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone()));
9900 BuildCheckNonSmi(right); 9905 BuildCheckNonSmi(right);
9901 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); 9906 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone()));
9902 HCompareObjectEqAndBranch* result = 9907 HCompareObjectEqAndBranch* result =
9903 new(zone()) HCompareObjectEqAndBranch(left, right); 9908 new(zone()) HCompareObjectEqAndBranch(left, right);
9904 result->set_position(expr->position()); 9909 result->set_position(expr->position());
9905 return ast_context()->ReturnControl(result, expr->id()); 9910 return ast_context()->ReturnControl(result, expr->id());
9906 } else { 9911 } else {
(...skipping 14 matching lines...) Expand all
9921 } 9926 }
9922 } 9927 }
9923 9928
9924 9929
9925 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, 9930 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
9926 HValue* value, 9931 HValue* value,
9927 NilValue nil) { 9932 NilValue nil) {
9928 ASSERT(!HasStackOverflow()); 9933 ASSERT(!HasStackOverflow());
9929 ASSERT(current_block() != NULL); 9934 ASSERT(current_block() != NULL);
9930 ASSERT(current_block()->HasPredecessor()); 9935 ASSERT(current_block()->HasPredecessor());
9936 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
9931 HIfContinuation continuation; 9937 HIfContinuation continuation;
9932 CompareNilICStub::Types types;
9933 if (expr->op() == Token::EQ_STRICT) { 9938 if (expr->op() == Token::EQ_STRICT) {
9934 IfBuilder if_nil(this); 9939 IfBuilder if_nil(this);
9935 if_nil.If<HCompareObjectEqAndBranch>( 9940 if_nil.If<HCompareObjectEqAndBranch>(
9936 value, (nil == kNullValue) ? graph()->GetConstantNull() 9941 value, (nil == kNullValue) ? graph()->GetConstantNull()
9937 : graph()->GetConstantUndefined()); 9942 : graph()->GetConstantUndefined());
9938 if_nil.Then(); 9943 if_nil.Then();
9939 if_nil.Else(); 9944 if_nil.Else();
9940 if_nil.CaptureContinuation(&continuation); 9945 if_nil.CaptureContinuation(&continuation);
9941 return ast_context()->ReturnContinuation(&continuation, expr->id()); 9946 return ast_context()->ReturnContinuation(&continuation, expr->id());
9942 } 9947 }
9943 types = CompareNilICStub::Types(expr->compare_nil_types()); 9948 Handle<Type> type = expr->compare_nil_type()->Is(Type::None())
9944 if (types.IsEmpty()) types = CompareNilICStub::Types::FullCompare(); 9949 ? handle(Type::Any(), isolate_) : expr->compare_nil_type();
9945 Handle<Map> map_handle = expr->map(); 9950 BuildCompareNil(value, type, expr->position(), &continuation);
9946 BuildCompareNil(value, types, map_handle,
9947 expr->position(), &continuation);
9948 return ast_context()->ReturnContinuation(&continuation, expr->id()); 9951 return ast_context()->ReturnContinuation(&continuation, expr->id());
9949 } 9952 }
9950 9953
9951 9954
9952 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { 9955 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
9953 // If we share optimized code between different closures, the 9956 // If we share optimized code between different closures, the
9954 // this-function is not a constant, except inside an inlined body. 9957 // this-function is not a constant, except inside an inlined body.
9955 if (function_state()->outer() != NULL) { 9958 if (function_state()->outer() != NULL) {
9956 return new(zone()) HConstant( 9959 return new(zone()) HConstant(
9957 function_state()->compilation_info()->closure(), 9960 function_state()->compilation_info()->closure(),
(...skipping 1653 matching lines...) Expand 10 before | Expand all | Expand 10 after
11611 } 11614 }
11612 } 11615 }
11613 11616
11614 #ifdef DEBUG 11617 #ifdef DEBUG
11615 if (graph_ != NULL) graph_->Verify(false); // No full verify. 11618 if (graph_ != NULL) graph_->Verify(false); // No full verify.
11616 if (allocator_ != NULL) allocator_->Verify(); 11619 if (allocator_ != NULL) allocator_->Verify();
11617 #endif 11620 #endif
11618 } 11621 }
11619 11622
11620 } } // namespace v8::internal 11623 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698