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

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: 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
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 2790 matching lines...) Expand 10 before | Expand all | Expand 10 after
2801 void EffectGraphVisitor::VisitStaticSetterNode(StaticSetterNode* node) { 2801 void EffectGraphVisitor::VisitStaticSetterNode(StaticSetterNode* node) {
2802 BuildStaticSetter(node, false); // Result not needed. 2802 BuildStaticSetter(node, false); // Result not needed.
2803 } 2803 }
2804 2804
2805 2805
2806 void ValueGraphVisitor::VisitStaticSetterNode(StaticSetterNode* node) { 2806 void ValueGraphVisitor::VisitStaticSetterNode(StaticSetterNode* node) {
2807 BuildStaticSetter(node, true); // Result needed. 2807 BuildStaticSetter(node, true); // Result needed.
2808 } 2808 }
2809 2809
2810 2810
2811 static intptr_t OffsetForLengthGetter(MethodRecognizer::Kind kind) {
srdjan 2013/08/12 21:49:47 Can we share this with the one in FlowGraphOptimiz
Florian Schneider 2013/08/14 12:30:24 The one in the FlowGraphOptimizer is gone with thi
2812 switch (kind) {
2813 case MethodRecognizer::kObjectArrayLength:
2814 case MethodRecognizer::kImmutableArrayLength:
2815 return Array::length_offset();
2816 case MethodRecognizer::kTypedDataLength:
2817 // .length is defined in _TypedList which is the base class for internal
2818 // and external typed data.
2819 ASSERT(TypedData::length_offset() == ExternalTypedData::length_offset());
2820 return TypedData::length_offset();
2821 case MethodRecognizer::kGrowableArrayLength:
2822 return GrowableObjectArray::length_offset();
2823 default:
2824 UNREACHABLE();
2825 return 0;
2826 }
2827 }
2828
2829
2811 void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) { 2830 void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) {
2831 const Function& function = owner()->parsed_function()->function();
2832 if (!function.IsClosureFunction()) {
2833 MethodRecognizer::Kind kind =
2834 MethodRecognizer::RecognizeKind(function);
Kevin Millikin (Google) 2013/08/13 11:47:40 Fits on the previous line.
Florian Schneider 2013/08/14 12:30:24 Done.
2835 switch (kind) {
2836 case MethodRecognizer::kStringBaseLength: {
2837 LocalVariable* receiver_var =
2838 node->scope()->LookupVariable(Symbols::This(),
2839 true); // Test only.
2840 Value* receiver = Bind(new LoadLocalInstr(*receiver_var));
2841 // Treat length loads as mutable (i.e. affected by side effects) to
2842 // avoid hoisting them since we can't hoist the preceding class-check.
2843 // This is because of externalization of strings that affects their
2844 // class-id.
2845 const bool is_immutable = false;
2846 LoadFieldInstr* load = new LoadFieldInstr(
2847 receiver,
2848 String::length_offset(),
2849 Type::ZoneHandle(Type::SmiType()),
2850 is_immutable);
2851 load->set_result_cid(kSmiCid);
2852 load->set_recognized_kind(MethodRecognizer::kStringBaseLength);
2853 return ReturnDefinition(load);
2854 }
2855 case MethodRecognizer::kGrowableArrayLength:
2856 case MethodRecognizer::kObjectArrayLength:
2857 case MethodRecognizer::kImmutableArrayLength:
2858 case MethodRecognizer::kTypedDataLength: {
2859 LocalVariable* receiver_var =
2860 node->scope()->LookupVariable(Symbols::This(),
2861 true); // Test only.
2862 Value* receiver = Bind(new LoadLocalInstr(*receiver_var));
2863 const bool is_immutable =
2864 (kind != MethodRecognizer::kGrowableArrayLength);
2865 LoadFieldInstr* load = new LoadFieldInstr(
2866 receiver,
2867 OffsetForLengthGetter(kind),
2868 Type::ZoneHandle(Type::SmiType()),
2869 is_immutable);
2870 load->set_result_cid(kSmiCid);
2871 load->set_recognized_kind(kind);
2872 return ReturnDefinition(load);
2873 }
2874 default:
2875 break;
2876 }
2877 }
2812 InlineBailout("EffectGraphVisitor::VisitNativeBodyNode"); 2878 InlineBailout("EffectGraphVisitor::VisitNativeBodyNode");
2879 function.set_is_optimizable(false);
2813 NativeCallInstr* native_call = new NativeCallInstr(node); 2880 NativeCallInstr* native_call = new NativeCallInstr(node);
2814 ReturnDefinition(native_call); 2881 ReturnDefinition(native_call);
2815 } 2882 }
2816 2883
2817 2884
2818 void EffectGraphVisitor::VisitPrimaryNode(PrimaryNode* node) { 2885 void EffectGraphVisitor::VisitPrimaryNode(PrimaryNode* node) {
2819 // PrimaryNodes are temporary during parsing. 2886 // PrimaryNodes are temporary during parsing.
2820 UNREACHABLE(); 2887 UNREACHABLE();
2821 } 2888 }
2822 2889
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
3161 Bind(new AllocateContextInstr(node->token_pos(), 3228 Bind(new AllocateContextInstr(node->token_pos(),
3162 num_context_variables)); 3229 num_context_variables));
3163 { LocalVariable* tmp_var = EnterTempLocalScope(allocated_context); 3230 { LocalVariable* tmp_var = EnterTempLocalScope(allocated_context);
3164 // If this node_sequence is the body of the function being compiled, and 3231 // If this node_sequence is the body of the function being compiled, and
3165 // if this function allocates context variables, but none of its enclosing 3232 // if this function allocates context variables, but none of its enclosing
3166 // functions do, the context on entry is not linked as parent of the 3233 // functions do, the context on entry is not linked as parent of the
3167 // allocated context but saved on entry and restored on exit as to prevent 3234 // allocated context but saved on entry and restored on exit as to prevent
3168 // memory leaks. 3235 // memory leaks.
3169 // In this case, the parser pre-allocates a variable to save the context. 3236 // In this case, the parser pre-allocates a variable to save the context.
3170 if (MustSaveRestoreContext(node)) { 3237 if (MustSaveRestoreContext(node)) {
3171 Value* current_context = Bind(new CurrentContextInstr()); 3238 BuildSaveContext(
Florian Schneider 2013/08/12 15:48:14 Unrelated refactoring.
3172 Do(BuildStoreTemp( 3239 *owner()->parsed_function()->saved_entry_context_var());
3173 *owner()->parsed_function()->saved_entry_context_var(),
3174 current_context));
3175 Value* null_context = Bind(new ConstantInstr(Object::ZoneHandle())); 3240 Value* null_context = Bind(new ConstantInstr(Object::ZoneHandle()));
3176 AddInstruction(new StoreContextInstr(null_context)); 3241 AddInstruction(new StoreContextInstr(null_context));
3177 } 3242 }
3178 Value* current_context = Bind(new CurrentContextInstr()); 3243 Value* current_context = Bind(new CurrentContextInstr());
3179 Value* tmp_val = Bind(new LoadLocalInstr(*tmp_var)); 3244 Value* tmp_val = Bind(new LoadLocalInstr(*tmp_var));
3180 Do(new StoreVMFieldInstr(tmp_val, 3245 Do(new StoreVMFieldInstr(tmp_val,
3181 Context::parent_offset(), 3246 Context::parent_offset(),
3182 current_context, 3247 current_context,
3183 Type::ZoneHandle())); 3248 Type::ZoneHandle()));
3184 AddInstruction( 3249 AddInstruction(
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
3579 // Print the function ast before IL generation. 3644 // Print the function ast before IL generation.
3580 AstPrinter::PrintFunctionNodes(*parsed_function()); 3645 AstPrinter::PrintFunctionNodes(*parsed_function());
3581 } 3646 }
3582 const Function& function = parsed_function()->function(); 3647 const Function& function = parsed_function()->function();
3583 TargetEntryInstr* normal_entry = 3648 TargetEntryInstr* normal_entry =
3584 new TargetEntryInstr(AllocateBlockId(), 3649 new TargetEntryInstr(AllocateBlockId(),
3585 CatchClauseNode::kInvalidTryIndex); 3650 CatchClauseNode::kInvalidTryIndex);
3586 graph_entry_ = new GraphEntryInstr(*parsed_function(), normal_entry, osr_id_); 3651 graph_entry_ = new GraphEntryInstr(*parsed_function(), normal_entry, osr_id_);
3587 EffectGraphVisitor for_effect(this, 0); 3652 EffectGraphVisitor for_effect(this, 0);
3588 // This check may be deleted if the generated code is leaf. 3653 // This check may be deleted if the generated code is leaf.
3589 CheckStackOverflowInstr* check = 3654 // Native functions don't need a stack check at entry.
3590 new CheckStackOverflowInstr(function.token_pos(), 0); 3655 if (!function.is_native()) {
3591 // If we are inlining don't actually attach the stack check. We must still 3656 CheckStackOverflowInstr* check =
3592 // create the stack check in order to allocate a deopt id. 3657 new CheckStackOverflowInstr(function.token_pos(), 0);
3593 if (!IsInlining()) for_effect.AddInstruction(check); 3658 // If we are inlining don't actually attach the stack check. We must still
3659 // create the stack check in order to allocate a deopt id.
3660 if (!IsInlining()) for_effect.AddInstruction(check);
3661 }
3594 parsed_function()->node_sequence()->Visit(&for_effect); 3662 parsed_function()->node_sequence()->Visit(&for_effect);
3595 AppendFragment(normal_entry, for_effect); 3663 AppendFragment(normal_entry, for_effect);
3596 // Check that the graph is properly terminated. 3664 // Check that the graph is properly terminated.
3597 ASSERT(!for_effect.is_open()); 3665 ASSERT(!for_effect.is_open());
3598 3666
3599 // When compiling for OSR, use a depth first search to prune instructions 3667 // When compiling for OSR, use a depth first search to prune instructions
3600 // unreachable from the OSR entry. Catch entries are not (yet) properly 3668 // unreachable from the OSR entry. Catch entries are not (yet) properly
3601 // recognized as reachable. 3669 // recognized as reachable.
3602 if (osr_id_ != Isolate::kNoDeoptId) { 3670 if (osr_id_ != Isolate::kNoDeoptId) {
3603 if (graph_entry_->SuccessorCount() > 1) { 3671 if (graph_entry_->SuccessorCount() > 1) {
(...skipping 22 matching lines...) Expand all
3626 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; 3694 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
3627 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 3695 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
3628 OS::SNPrint(chars, len, kFormat, function_name, reason); 3696 OS::SNPrint(chars, len, kFormat, function_name, reason);
3629 const Error& error = Error::Handle( 3697 const Error& error = Error::Handle(
3630 LanguageError::New(String::Handle(String::New(chars)))); 3698 LanguageError::New(String::Handle(String::New(chars))));
3631 Isolate::Current()->long_jump_base()->Jump(1, error); 3699 Isolate::Current()->long_jump_base()->Jump(1, error);
3632 } 3700 }
3633 3701
3634 3702
3635 } // namespace dart 3703 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698