| OLD | NEW |
| 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 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 689 | 689 |
| 690 HGraph::HGraph(CompilationInfo* info) | 690 HGraph::HGraph(CompilationInfo* info) |
| 691 : isolate_(info->isolate()), | 691 : isolate_(info->isolate()), |
| 692 next_block_id_(0), | 692 next_block_id_(0), |
| 693 entry_block_(NULL), | 693 entry_block_(NULL), |
| 694 blocks_(8, info->zone()), | 694 blocks_(8, info->zone()), |
| 695 values_(16, info->zone()), | 695 values_(16, info->zone()), |
| 696 phi_list_(NULL), | 696 phi_list_(NULL), |
| 697 info_(info), | 697 info_(info), |
| 698 zone_(info->zone()), | 698 zone_(info->zone()), |
| 699 is_recursive_(false) { | 699 is_recursive_(false), |
| 700 use_optimistic_licm_(false), |
| 701 type_change_checksum_(0) { |
| 700 start_environment_ = | 702 start_environment_ = |
| 701 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); | 703 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); |
| 702 start_environment_->set_ast_id(BailoutId::FunctionEntry()); | 704 start_environment_->set_ast_id(BailoutId::FunctionEntry()); |
| 703 entry_block_ = CreateBasicBlock(); | 705 entry_block_ = CreateBasicBlock(); |
| 704 entry_block_->SetInitialEnvironment(start_environment_); | 706 entry_block_->SetInitialEnvironment(start_environment_); |
| 705 } | 707 } |
| 706 | 708 |
| 707 | 709 |
| 708 HBasicBlock* HGraph::CreateBasicBlock() { | 710 HBasicBlock* HGraph::CreateBasicBlock() { |
| 709 HBasicBlock* result = new(zone()) HBasicBlock(this); | 711 HBasicBlock* result = new(zone()) HBasicBlock(this); |
| (...skipping 1182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1892 #endif | 1894 #endif |
| 1893 size_t string_len = strlen(underlying_buffer) + 1; | 1895 size_t string_len = strlen(underlying_buffer) + 1; |
| 1894 ASSERT(string_len <= sizeof(underlying_buffer)); | 1896 ASSERT(string_len <= sizeof(underlying_buffer)); |
| 1895 char* result = new char[strlen(underlying_buffer) + 1]; | 1897 char* result = new char[strlen(underlying_buffer) + 1]; |
| 1896 memcpy(result, underlying_buffer, string_len); | 1898 memcpy(result, underlying_buffer, string_len); |
| 1897 return SmartArrayPointer<char>(result); | 1899 return SmartArrayPointer<char>(result); |
| 1898 } | 1900 } |
| 1899 | 1901 |
| 1900 | 1902 |
| 1901 void HGlobalValueNumberer::LoopInvariantCodeMotion() { | 1903 void HGlobalValueNumberer::LoopInvariantCodeMotion() { |
| 1904 TRACE_GVN_1("Using optimistic loop invariant code motion: %s\n", |
| 1905 graph_->use_optimistic_licm() ? "yes" : "no"); |
| 1902 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { | 1906 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { |
| 1903 HBasicBlock* block = graph_->blocks()->at(i); | 1907 HBasicBlock* block = graph_->blocks()->at(i); |
| 1904 if (block->IsLoopHeader()) { | 1908 if (block->IsLoopHeader()) { |
| 1905 GVNFlagSet side_effects = loop_side_effects_[block->block_id()]; | 1909 GVNFlagSet side_effects = loop_side_effects_[block->block_id()]; |
| 1906 TRACE_GVN_2("Try loop invariant motion for block B%d %s\n", | 1910 TRACE_GVN_2("Try loop invariant motion for block B%d %s\n", |
| 1907 block->block_id(), | 1911 block->block_id(), |
| 1908 *GetGVNFlagsString(side_effects)); | 1912 *GetGVNFlagsString(side_effects)); |
| 1909 | 1913 |
| 1910 GVNFlagSet accumulated_first_time_depends; | 1914 GVNFlagSet accumulated_first_time_depends; |
| 1911 GVNFlagSet accumulated_first_time_changes; | 1915 GVNFlagSet accumulated_first_time_changes; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1935 while (instr != NULL) { | 1939 while (instr != NULL) { |
| 1936 HInstruction* next = instr->next(); | 1940 HInstruction* next = instr->next(); |
| 1937 bool hoisted = false; | 1941 bool hoisted = false; |
| 1938 if (instr->CheckFlag(HValue::kUseGVN)) { | 1942 if (instr->CheckFlag(HValue::kUseGVN)) { |
| 1939 TRACE_GVN_4("Checking instruction %d (%s) %s. Loop %s\n", | 1943 TRACE_GVN_4("Checking instruction %d (%s) %s. Loop %s\n", |
| 1940 instr->id(), | 1944 instr->id(), |
| 1941 instr->Mnemonic(), | 1945 instr->Mnemonic(), |
| 1942 *GetGVNFlagsString(instr->gvn_flags()), | 1946 *GetGVNFlagsString(instr->gvn_flags()), |
| 1943 *GetGVNFlagsString(loop_kills)); | 1947 *GetGVNFlagsString(loop_kills)); |
| 1944 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags); | 1948 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags); |
| 1949 if (can_hoist && !graph()->use_optimistic_licm()) { |
| 1950 can_hoist = block->IsLoopSuccessorDominator(); |
| 1951 } |
| 1945 if (instr->IsTransitionElementsKind()) { | 1952 if (instr->IsTransitionElementsKind()) { |
| 1946 // It's possible to hoist transitions out of a loop as long as the | 1953 // It's possible to hoist transitions out of a loop as long as the |
| 1947 // hoisting wouldn't move the transition past an instruction that has a | 1954 // hoisting wouldn't move the transition past an instruction that has a |
| 1948 // DependsOn flag for anything it changes. | 1955 // DependsOn flag for anything it changes. |
| 1949 GVNFlagSet hoist_depends_blockers = | 1956 GVNFlagSet hoist_depends_blockers = |
| 1950 HValue::ConvertChangesToDependsFlags(instr->ChangesFlags()); | 1957 HValue::ConvertChangesToDependsFlags(instr->ChangesFlags()); |
| 1951 | 1958 |
| 1952 // In addition, the transition must not be hoisted above elements kind | 1959 // In addition, the transition must not be hoisted above elements kind |
| 1953 // changes, or if the transition is destructive to the elements buffer, | 1960 // changes, or if the transition is destructive to the elements buffer, |
| 1954 // changes to array pointer or array contents. | 1961 // changes to array pointer or array contents. |
| (...skipping 1124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3079 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry)); | 3086 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry)); |
| 3080 | 3087 |
| 3081 VisitStatements(info()->function()->body()); | 3088 VisitStatements(info()->function()->body()); |
| 3082 if (HasStackOverflow()) return NULL; | 3089 if (HasStackOverflow()) return NULL; |
| 3083 | 3090 |
| 3084 if (current_block() != NULL) { | 3091 if (current_block() != NULL) { |
| 3085 HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined()); | 3092 HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined()); |
| 3086 current_block()->FinishExit(instr); | 3093 current_block()->FinishExit(instr); |
| 3087 set_current_block(NULL); | 3094 set_current_block(NULL); |
| 3088 } | 3095 } |
| 3096 |
| 3097 // If the checksum of the number of type info changes is the same as the |
| 3098 // last time this function was compiled, then this recompile is likely not |
| 3099 // due to missing/inadequate type feedback, but rather too aggressive |
| 3100 // optimization. Disable optimistic LICM in that case. |
| 3101 Handle<Code> unoptimized_code(info()->shared_info()->code()); |
| 3102 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
| 3103 Handle<Object> maybe_type_info(unoptimized_code->type_feedback_info()); |
| 3104 Handle<TypeFeedbackInfo> type_info( |
| 3105 Handle<TypeFeedbackInfo>::cast(maybe_type_info)); |
| 3106 int checksum = type_info->own_type_change_checksum(); |
| 3107 int composite_checksum = graph()->update_type_change_checksum(checksum); |
| 3108 graph()->set_use_optimistic_licm( |
| 3109 !type_info->matches_inlined_type_change_checksum(composite_checksum)); |
| 3110 type_info->set_inlined_type_change_checksum(composite_checksum); |
| 3089 } | 3111 } |
| 3090 | 3112 |
| 3091 return graph(); | 3113 return graph(); |
| 3092 } | 3114 } |
| 3093 | 3115 |
| 3094 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { | 3116 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { |
| 3095 *bailout_reason = SmartArrayPointer<char>(); | 3117 *bailout_reason = SmartArrayPointer<char>(); |
| 3096 OrderBlocks(); | 3118 OrderBlocks(); |
| 3097 AssignDominators(); | 3119 AssignDominators(); |
| 3098 | 3120 |
| (...skipping 3715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6814 target_shared); | 6836 target_shared); |
| 6815 } | 6837 } |
| 6816 | 6838 |
| 6817 // ---------------------------------------------------------------- | 6839 // ---------------------------------------------------------------- |
| 6818 // After this point, we've made a decision to inline this function (so | 6840 // After this point, we've made a decision to inline this function (so |
| 6819 // TryInline should always return true). | 6841 // TryInline should always return true). |
| 6820 | 6842 |
| 6821 // Save the pending call context and type feedback oracle. Set up new ones | 6843 // Save the pending call context and type feedback oracle. Set up new ones |
| 6822 // for the inlined function. | 6844 // for the inlined function. |
| 6823 ASSERT(target_shared->has_deoptimization_support()); | 6845 ASSERT(target_shared->has_deoptimization_support()); |
| 6846 Handle<Code> unoptimized_code(target_shared->code()); |
| 6824 TypeFeedbackOracle target_oracle( | 6847 TypeFeedbackOracle target_oracle( |
| 6825 Handle<Code>(target_shared->code()), | 6848 unoptimized_code, |
| 6826 Handle<Context>(target->context()->native_context()), | 6849 Handle<Context>(target->context()->native_context()), |
| 6827 isolate(), | 6850 isolate(), |
| 6828 zone()); | 6851 zone()); |
| 6829 // The function state is new-allocated because we need to delete it | 6852 // The function state is new-allocated because we need to delete it |
| 6830 // in two different places. | 6853 // in two different places. |
| 6831 FunctionState* target_state = new FunctionState( | 6854 FunctionState* target_state = new FunctionState( |
| 6832 this, &target_info, &target_oracle, inlining_kind); | 6855 this, &target_info, &target_oracle, inlining_kind); |
| 6833 | 6856 |
| 6834 HConstant* undefined = graph()->GetConstantUndefined(); | 6857 HConstant* undefined = graph()->GetConstantUndefined(); |
| 6835 HEnvironment* inner_env = | 6858 HEnvironment* inner_env = |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6895 TraceInline(target, caller, "inline graph construction failed"); | 6918 TraceInline(target, caller, "inline graph construction failed"); |
| 6896 target_shared->DisableOptimization(); | 6919 target_shared->DisableOptimization(); |
| 6897 inline_bailout_ = true; | 6920 inline_bailout_ = true; |
| 6898 delete target_state; | 6921 delete target_state; |
| 6899 return true; | 6922 return true; |
| 6900 } | 6923 } |
| 6901 | 6924 |
| 6902 // Update inlined nodes count. | 6925 // Update inlined nodes count. |
| 6903 inlined_count_ += nodes_added; | 6926 inlined_count_ += nodes_added; |
| 6904 | 6927 |
| 6928 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
| 6929 Handle<Object> maybe_type_info(unoptimized_code->type_feedback_info()); |
| 6930 Handle<TypeFeedbackInfo> type_info( |
| 6931 Handle<TypeFeedbackInfo>::cast(maybe_type_info)); |
| 6932 graph()->update_type_change_checksum(type_info->own_type_change_checksum()); |
| 6933 |
| 6905 TraceInline(target, caller, NULL); | 6934 TraceInline(target, caller, NULL); |
| 6906 | 6935 |
| 6907 if (current_block() != NULL) { | 6936 if (current_block() != NULL) { |
| 6908 FunctionState* state = function_state(); | 6937 FunctionState* state = function_state(); |
| 6909 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { | 6938 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { |
| 6910 // Falling off the end of an inlined construct call. In a test context the | 6939 // Falling off the end of an inlined construct call. In a test context the |
| 6911 // return value will always evaluate to true, in a value context the | 6940 // return value will always evaluate to true, in a value context the |
| 6912 // return value is the newly allocated receiver. | 6941 // return value is the newly allocated receiver. |
| 6913 if (call_context()->IsTest()) { | 6942 if (call_context()->IsTest()) { |
| 6914 current_block()->Goto(inlined_test_context()->if_true(), state); | 6943 current_block()->Goto(inlined_test_context()->if_true(), state); |
| (...skipping 2782 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9697 } | 9726 } |
| 9698 } | 9727 } |
| 9699 | 9728 |
| 9700 #ifdef DEBUG | 9729 #ifdef DEBUG |
| 9701 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 9730 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 9702 if (allocator_ != NULL) allocator_->Verify(); | 9731 if (allocator_ != NULL) allocator_->Verify(); |
| 9703 #endif | 9732 #endif |
| 9704 } | 9733 } |
| 9705 | 9734 |
| 9706 } } // namespace v8::internal | 9735 } } // namespace v8::internal |
| OLD | NEW |