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

Side by Side Diff: runtime/vm/flow_graph_builder.cc

Issue 22839003: Polymorphic inlining for some recognized methods in the optimizing compiler. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: fixed modulo performance regression Created 7 years, 4 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 | « runtime/vm/compiler.cc ('k') | runtime/vm/flow_graph_compiler.cc » ('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 (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/flow_graph_builder.h" 5 #include "vm/flow_graph_builder.h"
6 6
7 #include "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "vm/ast_printer.h" 8 #include "vm/ast_printer.h"
9 #include "vm/bit_vector.h" 9 #include "vm/bit_vector.h"
10 #include "vm/code_descriptors.h" 10 #include "vm/code_descriptors.h"
(...skipping 2832 matching lines...) Expand 10 before | Expand all | Expand 10 after
2843 void EffectGraphVisitor::VisitStaticSetterNode(StaticSetterNode* node) { 2843 void EffectGraphVisitor::VisitStaticSetterNode(StaticSetterNode* node) {
2844 BuildStaticSetter(node, false); // Result not needed. 2844 BuildStaticSetter(node, false); // Result not needed.
2845 } 2845 }
2846 2846
2847 2847
2848 void ValueGraphVisitor::VisitStaticSetterNode(StaticSetterNode* node) { 2848 void ValueGraphVisitor::VisitStaticSetterNode(StaticSetterNode* node) {
2849 BuildStaticSetter(node, true); // Result needed. 2849 BuildStaticSetter(node, true); // Result needed.
2850 } 2850 }
2851 2851
2852 2852
2853 static intptr_t OffsetForLengthGetter(MethodRecognizer::Kind kind) {
2854 switch (kind) {
2855 case MethodRecognizer::kObjectArrayLength:
2856 case MethodRecognizer::kImmutableArrayLength:
2857 return Array::length_offset();
2858 case MethodRecognizer::kTypedDataLength:
2859 // .length is defined in _TypedList which is the base class for internal
2860 // and external typed data.
2861 ASSERT(TypedData::length_offset() == ExternalTypedData::length_offset());
2862 return TypedData::length_offset();
2863 case MethodRecognizer::kGrowableArrayLength:
2864 return GrowableObjectArray::length_offset();
2865 default:
2866 UNREACHABLE();
2867 return 0;
2868 }
2869 }
2870
2871
2853 void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) { 2872 void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) {
2873 const Function& function = owner()->parsed_function()->function();
2874 if (!function.IsClosureFunction()) {
2875 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
2876 switch (kind) {
2877 case MethodRecognizer::kStringBaseLength: {
2878 LocalVariable* receiver_var =
2879 node->scope()->LookupVariable(Symbols::This(),
2880 true); // Test only.
2881 Value* receiver = Bind(new LoadLocalInstr(*receiver_var));
2882 // Treat length loads as mutable (i.e. affected by side effects) to
2883 // avoid hoisting them since we can't hoist the preceding class-check.
2884 // This is because of externalization of strings that affects their
2885 // class-id.
2886 const bool is_immutable = false;
2887 LoadFieldInstr* load = new LoadFieldInstr(
2888 receiver,
2889 String::length_offset(),
2890 Type::ZoneHandle(Type::SmiType()),
2891 is_immutable);
2892 load->set_result_cid(kSmiCid);
2893 load->set_recognized_kind(MethodRecognizer::kStringBaseLength);
2894 return ReturnDefinition(load);
2895 }
2896 case MethodRecognizer::kGrowableArrayLength:
2897 case MethodRecognizer::kObjectArrayLength:
2898 case MethodRecognizer::kImmutableArrayLength:
2899 case MethodRecognizer::kTypedDataLength: {
2900 LocalVariable* receiver_var =
2901 node->scope()->LookupVariable(Symbols::This(),
2902 true); // Test only.
2903 Value* receiver = Bind(new LoadLocalInstr(*receiver_var));
2904 const bool is_immutable =
2905 (kind != MethodRecognizer::kGrowableArrayLength);
2906 LoadFieldInstr* load = new LoadFieldInstr(
2907 receiver,
2908 OffsetForLengthGetter(kind),
2909 Type::ZoneHandle(Type::SmiType()),
2910 is_immutable);
2911 load->set_result_cid(kSmiCid);
2912 load->set_recognized_kind(kind);
2913 return ReturnDefinition(load);
2914 }
2915 default:
2916 break;
2917 }
2918 }
2854 InlineBailout("EffectGraphVisitor::VisitNativeBodyNode"); 2919 InlineBailout("EffectGraphVisitor::VisitNativeBodyNode");
2920 function.set_is_optimizable(false);
2855 NativeCallInstr* native_call = new NativeCallInstr(node); 2921 NativeCallInstr* native_call = new NativeCallInstr(node);
2856 ReturnDefinition(native_call); 2922 ReturnDefinition(native_call);
2857 } 2923 }
2858 2924
2859 2925
2860 void EffectGraphVisitor::VisitPrimaryNode(PrimaryNode* node) { 2926 void EffectGraphVisitor::VisitPrimaryNode(PrimaryNode* node) {
2861 // PrimaryNodes are temporary during parsing. 2927 // PrimaryNodes are temporary during parsing.
2862 UNREACHABLE(); 2928 UNREACHABLE();
2863 } 2929 }
2864 2930
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
3203 Bind(new AllocateContextInstr(node->token_pos(), 3269 Bind(new AllocateContextInstr(node->token_pos(),
3204 num_context_variables)); 3270 num_context_variables));
3205 { LocalVariable* tmp_var = EnterTempLocalScope(allocated_context); 3271 { LocalVariable* tmp_var = EnterTempLocalScope(allocated_context);
3206 // If this node_sequence is the body of the function being compiled, and 3272 // If this node_sequence is the body of the function being compiled, and
3207 // if this function allocates context variables, but none of its enclosing 3273 // if this function allocates context variables, but none of its enclosing
3208 // functions do, the context on entry is not linked as parent of the 3274 // functions do, the context on entry is not linked as parent of the
3209 // allocated context but saved on entry and restored on exit as to prevent 3275 // allocated context but saved on entry and restored on exit as to prevent
3210 // memory leaks. 3276 // memory leaks.
3211 // In this case, the parser pre-allocates a variable to save the context. 3277 // In this case, the parser pre-allocates a variable to save the context.
3212 if (MustSaveRestoreContext(node)) { 3278 if (MustSaveRestoreContext(node)) {
3213 Value* current_context = Bind(new CurrentContextInstr()); 3279 BuildSaveContext(
3214 Do(BuildStoreTemp( 3280 *owner()->parsed_function()->saved_entry_context_var());
3215 *owner()->parsed_function()->saved_entry_context_var(),
3216 current_context));
3217 Value* null_context = Bind(new ConstantInstr(Object::ZoneHandle())); 3281 Value* null_context = Bind(new ConstantInstr(Object::ZoneHandle()));
3218 AddInstruction(new StoreContextInstr(null_context)); 3282 AddInstruction(new StoreContextInstr(null_context));
3219 } 3283 }
3220 Value* current_context = Bind(new CurrentContextInstr()); 3284 Value* current_context = Bind(new CurrentContextInstr());
3221 Value* tmp_val = Bind(new LoadLocalInstr(*tmp_var)); 3285 Value* tmp_val = Bind(new LoadLocalInstr(*tmp_var));
3222 Do(new StoreVMFieldInstr(tmp_val, 3286 Do(new StoreVMFieldInstr(tmp_val,
3223 Context::parent_offset(), 3287 Context::parent_offset(),
3224 current_context, 3288 current_context,
3225 Type::ZoneHandle())); 3289 Type::ZoneHandle()));
3226 AddInstruction( 3290 AddInstruction(
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
3623 // Print the function ast before IL generation. 3687 // Print the function ast before IL generation.
3624 AstPrinter::PrintFunctionNodes(*parsed_function()); 3688 AstPrinter::PrintFunctionNodes(*parsed_function());
3625 } 3689 }
3626 const Function& function = parsed_function()->function(); 3690 const Function& function = parsed_function()->function();
3627 TargetEntryInstr* normal_entry = 3691 TargetEntryInstr* normal_entry =
3628 new TargetEntryInstr(AllocateBlockId(), 3692 new TargetEntryInstr(AllocateBlockId(),
3629 CatchClauseNode::kInvalidTryIndex); 3693 CatchClauseNode::kInvalidTryIndex);
3630 graph_entry_ = new GraphEntryInstr(*parsed_function(), normal_entry, osr_id_); 3694 graph_entry_ = new GraphEntryInstr(*parsed_function(), normal_entry, osr_id_);
3631 EffectGraphVisitor for_effect(this, 0); 3695 EffectGraphVisitor for_effect(this, 0);
3632 // This check may be deleted if the generated code is leaf. 3696 // This check may be deleted if the generated code is leaf.
3633 CheckStackOverflowInstr* check = 3697 // Native functions don't need a stack check at entry.
3634 new CheckStackOverflowInstr(function.token_pos(), 0); 3698 if (!function.is_native()) {
3635 // If we are inlining don't actually attach the stack check. We must still 3699 CheckStackOverflowInstr* check =
3636 // create the stack check in order to allocate a deopt id. 3700 new CheckStackOverflowInstr(function.token_pos(), 0);
3637 if (!IsInlining()) for_effect.AddInstruction(check); 3701 // If we are inlining don't actually attach the stack check. We must still
3702 // create the stack check in order to allocate a deopt id.
3703 if (!IsInlining()) for_effect.AddInstruction(check);
3704 }
3638 parsed_function()->node_sequence()->Visit(&for_effect); 3705 parsed_function()->node_sequence()->Visit(&for_effect);
3639 AppendFragment(normal_entry, for_effect); 3706 AppendFragment(normal_entry, for_effect);
3640 // Check that the graph is properly terminated. 3707 // Check that the graph is properly terminated.
3641 ASSERT(!for_effect.is_open()); 3708 ASSERT(!for_effect.is_open());
3642 3709
3643 // When compiling for OSR, use a depth first search to prune instructions 3710 // When compiling for OSR, use a depth first search to prune instructions
3644 // unreachable from the OSR entry. Catch entries are not (yet) properly 3711 // unreachable from the OSR entry. Catch entries are not (yet) properly
3645 // recognized as reachable. 3712 // recognized as reachable.
3646 if (osr_id_ != Isolate::kNoDeoptId) { 3713 if (osr_id_ != Isolate::kNoDeoptId) {
3647 if (graph_entry_->SuccessorCount() > 1) { 3714 if (graph_entry_->SuccessorCount() > 1) {
(...skipping 22 matching lines...) Expand all
3670 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; 3737 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
3671 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 3738 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
3672 OS::SNPrint(chars, len, kFormat, function_name, reason); 3739 OS::SNPrint(chars, len, kFormat, function_name, reason);
3673 const Error& error = Error::Handle( 3740 const Error& error = Error::Handle(
3674 LanguageError::New(String::Handle(String::New(chars)))); 3741 LanguageError::New(String::Handle(String::New(chars))));
3675 Isolate::Current()->long_jump_base()->Jump(1, error); 3742 Isolate::Current()->long_jump_base()->Jump(1, error);
3676 } 3743 }
3677 3744
3678 3745
3679 } // namespace dart 3746 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/compiler.cc ('k') | runtime/vm/flow_graph_compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698