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

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

Issue 1714743002: VM: Separate precompilation-specific code, make flags const. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 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
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/branch_optimizer.h" 8 #include "vm/branch_optimizer.h"
9 #include "vm/cha.h" 9 #include "vm/cha.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
11 #include "vm/cpu.h" 11 #include "vm/cpu.h"
12 #include "vm/dart_entry.h" 12 #include "vm/dart_entry.h"
13 #include "vm/exceptions.h" 13 #include "vm/exceptions.h"
14 #include "vm/flow_graph_builder.h" 14 #include "vm/flow_graph_builder.h"
15 #include "vm/flow_graph_compiler.h" 15 #include "vm/flow_graph_compiler.h"
16 #include "vm/flow_graph_inliner.h" 16 #include "vm/flow_graph_inliner.h"
17 #include "vm/flow_graph_range_analysis.h" 17 #include "vm/flow_graph_range_analysis.h"
18 #include "vm/hash_map.h" 18 #include "vm/hash_map.h"
19 #include "vm/il_printer.h" 19 #include "vm/il_printer.h"
20 #include "vm/intermediate_language.h" 20 #include "vm/intermediate_language.h"
21 #include "vm/object_store.h" 21 #include "vm/object_store.h"
22 #include "vm/parser.h" 22 #include "vm/parser.h"
23 #include "vm/precompiler.h"
24 #include "vm/resolver.h" 23 #include "vm/resolver.h"
25 #include "vm/scopes.h" 24 #include "vm/scopes.h"
26 #include "vm/stack_frame.h" 25 #include "vm/stack_frame.h"
27 #include "vm/symbols.h" 26 #include "vm/symbols.h"
28 27
29 namespace dart { 28 namespace dart {
30 29
31 DEFINE_FLAG(int, getter_setter_ratio, 13, 30 DEFINE_FLAG(int, getter_setter_ratio, 13,
32 "Ratio of getter/setter usage used for double field unboxing heuristics"); 31 "Ratio of getter/setter usage used for double field unboxing heuristics");
33 DEFINE_FLAG(bool, guess_icdata_cid, true, 32 DEFINE_FLAG(bool, guess_icdata_cid, true,
34 "Artificially create type feedback for arithmetic etc. operations" 33 "Artificially create type feedback for arithmetic etc. operations"
35 " by guessing the other unknown argument cid"); 34 " by guessing the other unknown argument cid");
36 DEFINE_FLAG(int, max_polymorphic_checks, 4, 35 DEFINE_FLAG(int, max_polymorphic_checks, 4,
37 "Maximum number of polymorphic check, otherwise it is megamorphic."); 36 "Maximum number of polymorphic check, otherwise it is megamorphic.");
38 DEFINE_FLAG(int, max_equality_polymorphic_checks, 32, 37 DEFINE_FLAG(int, max_equality_polymorphic_checks, 32,
39 "Maximum number of polymorphic checks in equality operator," 38 "Maximum number of polymorphic checks in equality operator,"
40 " otherwise use megamorphic dispatch."); 39 " otherwise use megamorphic dispatch.");
41 DEFINE_FLAG(bool, merge_sin_cos, false, "Merge sin/cos into sincos"); 40 DEFINE_FLAG(bool, merge_sin_cos, false, "Merge sin/cos into sincos");
42 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); 41 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details.");
43 DEFINE_FLAG(bool, truncating_left_shift, true, 42 DEFINE_FLAG(bool, truncating_left_shift, true,
44 "Optimize left shift to truncate if possible"); 43 "Optimize left shift to truncate if possible");
45 DEFINE_FLAG(bool, use_cha_deopt, true, 44 DEFINE_FLAG(bool, use_cha_deopt, true,
46 "Use class hierarchy analysis even if it can cause deoptimization."); 45 "Use class hierarchy analysis even if it can cause deoptimization.");
47 46
48 DECLARE_FLAG(bool, precompilation);
49 DECLARE_FLAG(bool, polymorphic_with_deopt); 47 DECLARE_FLAG(bool, polymorphic_with_deopt);
50 DECLARE_FLAG(bool, trace_cha); 48 DECLARE_FLAG(bool, trace_cha);
51 DECLARE_FLAG(bool, trace_field_guards); 49 DECLARE_FLAG(bool, trace_field_guards);
52 50
53 // Quick access to the current isolate and zone. 51 // Quick access to the current isolate and zone.
54 #define I (isolate()) 52 #define I (isolate())
55 #define Z (zone()) 53 #define Z (zone())
56 54
57 static bool ShouldInlineSimd() { 55 static bool ShouldInlineSimd() {
58 return FlowGraphCompiler::SupportsUnboxedSimd128(); 56 return FlowGraphCompiler::SupportsUnboxedSimd128();
59 } 57 }
60 58
61 59
62 static bool CanUnboxDouble() { 60 static bool CanUnboxDouble() {
63 return FlowGraphCompiler::SupportsUnboxedDoubles(); 61 return FlowGraphCompiler::SupportsUnboxedDoubles();
64 } 62 }
65 63
66 64
67 static bool CanConvertUnboxedMintToDouble() { 65 static bool CanConvertUnboxedMintToDouble() {
68 return FlowGraphCompiler::CanConvertUnboxedMintToDouble(); 66 return FlowGraphCompiler::CanConvertUnboxedMintToDouble();
69 } 67 }
70 68
71 69
72 // Optimize instance calls using ICData. 70 // Optimize instance calls using ICData.
73 void FlowGraphOptimizer::ApplyICData() { 71 void FlowGraphOptimizer::ApplyICData() {
74 VisitBlocks(); 72 VisitBlocks();
75 } 73 }
76 74
77 75
78 void FlowGraphOptimizer::PopulateWithICData() {
79 ASSERT(current_iterator_ == NULL);
80 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
81 !block_it.Done();
82 block_it.Advance()) {
83 ForwardInstructionIterator it(block_it.Current());
84 for (; !it.Done(); it.Advance()) {
85 Instruction* instr = it.Current();
86 if (instr->IsInstanceCall()) {
87 InstanceCallInstr* call = instr->AsInstanceCall();
88 if (!call->HasICData()) {
89 const Array& arguments_descriptor =
90 Array::Handle(zone(),
91 ArgumentsDescriptor::New(call->ArgumentCount(),
92 call->argument_names()));
93 const ICData& ic_data = ICData::ZoneHandle(zone(), ICData::New(
94 function(), call->function_name(),
95 arguments_descriptor, call->deopt_id(),
96 call->checked_argument_count()));
97 call->set_ic_data(&ic_data);
98 }
99 }
100 }
101 current_iterator_ = NULL;
102 }
103 }
104
105
106 // Optimize instance calls using cid. This is called after optimizer 76 // Optimize instance calls using cid. This is called after optimizer
107 // converted instance calls to instructions. Any remaining 77 // converted instance calls to instructions. Any remaining
108 // instance calls are either megamorphic calls, cannot be optimized or 78 // instance calls are either megamorphic calls, cannot be optimized or
109 // have no runtime type feedback collected. 79 // have no runtime type feedback collected.
110 // Attempts to convert an instance call (IC call) using propagated class-ids, 80 // Attempts to convert an instance call (IC call) using propagated class-ids,
111 // e.g., receiver class id, guarded-cid, or by guessing cid-s. 81 // e.g., receiver class id, guarded-cid, or by guessing cid-s.
112 void FlowGraphOptimizer::ApplyClassIds() { 82 void FlowGraphOptimizer::ApplyClassIds() {
113 ASSERT(current_iterator_ == NULL); 83 ASSERT(current_iterator_ == NULL);
114 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); 84 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
115 !block_it.Done(); 85 !block_it.Done();
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 if (class_ids.length() > 1) { 180 if (class_ids.length() > 1) {
211 ic_data.AddCheck(class_ids, function); 181 ic_data.AddCheck(class_ids, function);
212 } else { 182 } else {
213 ASSERT(class_ids.length() == 1); 183 ASSERT(class_ids.length() == 1);
214 ic_data.AddReceiverCheck(class_ids[0], function); 184 ic_data.AddReceiverCheck(class_ids[0], function);
215 } 185 }
216 call->set_ic_data(&ic_data); 186 call->set_ic_data(&ic_data);
217 return true; 187 return true;
218 } 188 }
219 189
220 #ifdef DART_PRECOMPILER
221 if (FLAG_precompilation &&
222 (isolate()->object_store()->unique_dynamic_targets() != Array::null())) {
223 // Check if the target is unique.
224 Function& target_function = Function::Handle(Z);
225 Precompiler::GetUniqueDynamicTarget(
226 isolate(), call->function_name(), &target_function);
227 // Calls with named arguments must be resolved/checked at runtime.
228 String& error_message = String::Handle(Z);
229 if (!target_function.IsNull() &&
230 !target_function.HasOptionalNamedParameters() &&
231 target_function.AreValidArgumentCounts(call->ArgumentCount(), 0,
232 &error_message)) {
233 const intptr_t cid = Class::Handle(Z, target_function.Owner()).id();
234 const ICData& ic_data = ICData::ZoneHandle(Z,
235 ICData::NewFrom(*call->ic_data(), 1));
236 ic_data.AddReceiverCheck(cid, target_function);
237 call->set_ic_data(&ic_data);
238 return true;
239 }
240 }
241 #endif
242
243 // Check if getter or setter in function's class and class is currently leaf. 190 // Check if getter or setter in function's class and class is currently leaf.
244 if (FLAG_guess_icdata_cid && 191 if (FLAG_guess_icdata_cid &&
245 ((call->token_kind() == Token::kGET) || 192 ((call->token_kind() == Token::kGET) ||
246 (call->token_kind() == Token::kSET))) { 193 (call->token_kind() == Token::kSET))) {
247 const Class& owner_class = Class::Handle(Z, function().Owner()); 194 const Class& owner_class = Class::Handle(Z, function().Owner());
248 if (!owner_class.is_abstract() && 195 if (!owner_class.is_abstract() &&
249 !CHA::HasSubclasses(owner_class) && 196 !CHA::HasSubclasses(owner_class) &&
250 !CHA::IsImplemented(owner_class)) { 197 !CHA::IsImplemented(owner_class)) {
251 const Array& args_desc_array = Array::Handle(Z, 198 const Array& args_desc_array = Array::Handle(Z,
252 ArgumentsDescriptor::New(call->ArgumentCount(), 199 ArgumentsDescriptor::New(call->ArgumentCount(),
(...skipping 1796 matching lines...) Expand 10 before | Expand all | Expand 10 after
2049 return true; 1996 return true;
2050 } 1997 }
2051 } 1998 }
2052 return false; 1999 return false;
2053 } 2000 }
2054 2001
2055 2002
2056 bool FlowGraphOptimizer::TryInlineFloat32x4Constructor( 2003 bool FlowGraphOptimizer::TryInlineFloat32x4Constructor(
2057 StaticCallInstr* call, 2004 StaticCallInstr* call,
2058 MethodRecognizer::Kind recognized_kind) { 2005 MethodRecognizer::Kind recognized_kind) {
2059 if (FLAG_precompilation) {
2060 // Cannot handle unboxed instructions.
2061 return false;
2062 }
2063 if (!ShouldInlineSimd()) { 2006 if (!ShouldInlineSimd()) {
2064 return false; 2007 return false;
2065 } 2008 }
2066 if (recognized_kind == MethodRecognizer::kFloat32x4Zero) { 2009 if (recognized_kind == MethodRecognizer::kFloat32x4Zero) {
2067 Float32x4ZeroInstr* zero = new(Z) Float32x4ZeroInstr(); 2010 Float32x4ZeroInstr* zero = new(Z) Float32x4ZeroInstr();
2068 ReplaceCall(call, zero); 2011 ReplaceCall(call, zero);
2069 return true; 2012 return true;
2070 } else if (recognized_kind == MethodRecognizer::kFloat32x4Splat) { 2013 } else if (recognized_kind == MethodRecognizer::kFloat32x4Splat) {
2071 Float32x4SplatInstr* splat = 2014 Float32x4SplatInstr* splat =
2072 new(Z) Float32x4SplatInstr( 2015 new(Z) Float32x4SplatInstr(
(...skipping 23 matching lines...) Expand all
2096 ReplaceCall(call, cast); 2039 ReplaceCall(call, cast);
2097 return true; 2040 return true;
2098 } 2041 }
2099 return false; 2042 return false;
2100 } 2043 }
2101 2044
2102 2045
2103 bool FlowGraphOptimizer::TryInlineFloat64x2Constructor( 2046 bool FlowGraphOptimizer::TryInlineFloat64x2Constructor(
2104 StaticCallInstr* call, 2047 StaticCallInstr* call,
2105 MethodRecognizer::Kind recognized_kind) { 2048 MethodRecognizer::Kind recognized_kind) {
2106 if (FLAG_precompilation) {
2107 // Cannot handle unboxed instructions.
2108 return false;
2109 }
2110 if (!ShouldInlineSimd()) { 2049 if (!ShouldInlineSimd()) {
2111 return false; 2050 return false;
2112 } 2051 }
2113 if (recognized_kind == MethodRecognizer::kFloat64x2Zero) { 2052 if (recognized_kind == MethodRecognizer::kFloat64x2Zero) {
2114 Float64x2ZeroInstr* zero = new(Z) Float64x2ZeroInstr(); 2053 Float64x2ZeroInstr* zero = new(Z) Float64x2ZeroInstr();
2115 ReplaceCall(call, zero); 2054 ReplaceCall(call, zero);
2116 return true; 2055 return true;
2117 } else if (recognized_kind == MethodRecognizer::kFloat64x2Splat) { 2056 } else if (recognized_kind == MethodRecognizer::kFloat64x2Splat) {
2118 Float64x2SplatInstr* splat = 2057 Float64x2SplatInstr* splat =
2119 new(Z) Float64x2SplatInstr( 2058 new(Z) Float64x2SplatInstr(
(...skipping 15 matching lines...) Expand all
2135 ReplaceCall(call, cast); 2074 ReplaceCall(call, cast);
2136 return true; 2075 return true;
2137 } 2076 }
2138 return false; 2077 return false;
2139 } 2078 }
2140 2079
2141 2080
2142 bool FlowGraphOptimizer::TryInlineInt32x4Constructor( 2081 bool FlowGraphOptimizer::TryInlineInt32x4Constructor(
2143 StaticCallInstr* call, 2082 StaticCallInstr* call,
2144 MethodRecognizer::Kind recognized_kind) { 2083 MethodRecognizer::Kind recognized_kind) {
2145 if (FLAG_precompilation) {
2146 // Cannot handle unboxed instructions.
2147 return false;
2148 }
2149 if (!ShouldInlineSimd()) { 2084 if (!ShouldInlineSimd()) {
2150 return false; 2085 return false;
2151 } 2086 }
2152 if (recognized_kind == MethodRecognizer::kInt32x4BoolConstructor) { 2087 if (recognized_kind == MethodRecognizer::kInt32x4BoolConstructor) {
2153 Int32x4BoolConstructorInstr* con = 2088 Int32x4BoolConstructorInstr* con =
2154 new(Z) Int32x4BoolConstructorInstr( 2089 new(Z) Int32x4BoolConstructorInstr(
2155 new(Z) Value(call->ArgumentAt(1)), 2090 new(Z) Value(call->ArgumentAt(1)),
2156 new(Z) Value(call->ArgumentAt(2)), 2091 new(Z) Value(call->ArgumentAt(2)),
2157 new(Z) Value(call->ArgumentAt(3)), 2092 new(Z) Value(call->ArgumentAt(3)),
2158 new(Z) Value(call->ArgumentAt(4)), 2093 new(Z) Value(call->ArgumentAt(4)),
(...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after
2929 /* with_checks = */ false); 2864 /* with_checks = */ false);
2930 instr->ReplaceWith(call, current_iterator()); 2865 instr->ReplaceWith(call, current_iterator());
2931 return; 2866 return;
2932 } 2867 }
2933 } 2868 }
2934 2869
2935 2870
2936 // Tries to optimize instance call by replacing it with a faster instruction 2871 // Tries to optimize instance call by replacing it with a faster instruction
2937 // (e.g, binary op, field load, ..). 2872 // (e.g, binary op, field load, ..).
2938 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { 2873 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
2939 if (FLAG_precompilation) {
2940 InstanceCallNoopt(instr);
2941 return;
2942 }
2943
2944 if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) { 2874 if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) {
2945 return; 2875 return;
2946 } 2876 }
2947 const Token::Kind op_kind = instr->token_kind(); 2877 const Token::Kind op_kind = instr->token_kind();
2948 2878
2949 // Type test is special as it always gets converted into inlined code. 2879 // Type test is special as it always gets converted into inlined code.
2950 if (Token::IsTypeTestOperator(op_kind)) { 2880 if (Token::IsTypeTestOperator(op_kind)) {
2951 ReplaceWithInstanceOf(instr); 2881 ReplaceWithInstanceOf(instr);
2952 return; 2882 return;
2953 } 2883 }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
3061 unary_kind = MathUnaryInstr::kSin; 2991 unary_kind = MathUnaryInstr::kSin;
3062 break; 2992 break;
3063 case MethodRecognizer::kMathCos: 2993 case MethodRecognizer::kMathCos:
3064 unary_kind = MathUnaryInstr::kCos; 2994 unary_kind = MathUnaryInstr::kCos;
3065 break; 2995 break;
3066 default: 2996 default:
3067 unary_kind = MathUnaryInstr::kIllegal; 2997 unary_kind = MathUnaryInstr::kIllegal;
3068 break; 2998 break;
3069 } 2999 }
3070 if (unary_kind != MathUnaryInstr::kIllegal) { 3000 if (unary_kind != MathUnaryInstr::kIllegal) {
3071 if (FLAG_precompilation) {
3072 // TODO(srdjan): Adapt MathUnaryInstr to allow tagged inputs as well.
3073 return;
3074 }
3075 MathUnaryInstr* math_unary = 3001 MathUnaryInstr* math_unary =
3076 new(Z) MathUnaryInstr(unary_kind, 3002 new(Z) MathUnaryInstr(unary_kind,
3077 new(Z) Value(call->ArgumentAt(0)), 3003 new(Z) Value(call->ArgumentAt(0)),
3078 call->deopt_id()); 3004 call->deopt_id());
3079 ReplaceCall(call, math_unary); 3005 ReplaceCall(call, math_unary);
3080 return; 3006 return;
3081 } 3007 }
3082 switch (recognized_kind) { 3008 switch (recognized_kind) {
3083 case MethodRecognizer::kFloat32x4Zero: 3009 case MethodRecognizer::kFloat32x4Zero:
3084 case MethodRecognizer::kFloat32x4Splat: 3010 case MethodRecognizer::kFloat32x4Splat:
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
3147 } 3073 }
3148 } 3074 }
3149 break; 3075 break;
3150 } 3076 }
3151 case MethodRecognizer::kMathDoublePow: 3077 case MethodRecognizer::kMathDoublePow:
3152 case MethodRecognizer::kMathTan: 3078 case MethodRecognizer::kMathTan:
3153 case MethodRecognizer::kMathAsin: 3079 case MethodRecognizer::kMathAsin:
3154 case MethodRecognizer::kMathAcos: 3080 case MethodRecognizer::kMathAcos:
3155 case MethodRecognizer::kMathAtan: 3081 case MethodRecognizer::kMathAtan:
3156 case MethodRecognizer::kMathAtan2: { 3082 case MethodRecognizer::kMathAtan2: {
3157 if (FLAG_precompilation) {
3158 // No UnboxDouble instructons allowed.
3159 return;
3160 }
3161 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble 3083 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble
3162 // instructions contain type checks and conversions to double. 3084 // instructions contain type checks and conversions to double.
3163 ZoneGrowableArray<Value*>* args = 3085 ZoneGrowableArray<Value*>* args =
3164 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount()); 3086 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount());
3165 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { 3087 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
3166 args->Add(new(Z) Value(call->ArgumentAt(i))); 3088 args->Add(new(Z) Value(call->ArgumentAt(i)));
3167 } 3089 }
3168 InvokeMathCFunctionInstr* invoke = 3090 InvokeMathCFunctionInstr* invoke =
3169 new(Z) InvokeMathCFunctionInstr(args, 3091 new(Z) InvokeMathCFunctionInstr(args,
3170 call->deopt_id(), 3092 call->deopt_id(),
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
3406 3328
3407 // Discard the environment from the original instruction because the store 3329 // Discard the environment from the original instruction because the store
3408 // can't deoptimize. 3330 // can't deoptimize.
3409 instr->RemoveEnvironment(); 3331 instr->RemoveEnvironment();
3410 ReplaceCall(instr, store); 3332 ReplaceCall(instr, store);
3411 return true; 3333 return true;
3412 } 3334 }
3413 3335
3414 3336
3415 } // namespace dart 3337 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698