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

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

Issue 12529008: Collect type feedback for fields. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 9 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/compiler.h" 5 #include "vm/compiler.h"
6 6
7 #include "vm/assembler.h" 7 #include "vm/assembler.h"
8 8
9 #include "vm/ast_printer.h" 9 #include "vm/ast_printer.h"
10 #include "vm/code_generator.h" 10 #include "vm/code_generator.h"
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 Code::Handle(function.CurrentCode()).EntryPoint()); 105 Code::Handle(function.CurrentCode()).EntryPoint());
106 } 106 }
107 function.SwitchToUnoptimizedCode(); 107 function.SwitchToUnoptimizedCode();
108 if (FLAG_trace_compiler) { 108 if (FLAG_trace_compiler) {
109 OS::Print("--> restoring entry at %#"Px"\n", 109 OS::Print("--> restoring entry at %#"Px"\n",
110 Code::Handle(function.unoptimized_code()).EntryPoint()); 110 Code::Handle(function.unoptimized_code()).EntryPoint());
111 } 111 }
112 } 112 }
113 113
114 114
115 static ZoneGrowableArray<Field*>* CollectGuardedFieldLoads(
116 FlowGraph* flow_graph) {
117 ZoneGrowableArray<Field*>* result =
118 new ZoneGrowableArray<Field*>(10);
119
120 for (intptr_t i = 1; i < flow_graph->reverse_postorder().length(); i++) {
121 BlockEntryInstr* entry = flow_graph->reverse_postorder()[i];
122 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
123 LoadFieldInstr* load_field = it.Current()->AsLoadField();
124 if (load_field == NULL || load_field->field() == NULL) continue;
125
126 Field* field = load_field->field();
127 if (field->guarded_cid() == kDynamicCid) continue;
Kevin Millikin (Google) 2013/03/12 12:14:56 It's slightly nicer to write: if (load_field == N
Vyacheslav Egorov (Google) 2013/03/12 16:54:40 Done.
128
129 bool found = false;
130 for (intptr_t j = 0; j < result->length(); j++) {
131 if ((*result)[j]->raw() == field->raw()) {
132 found = true;
133 break;
134 }
135 }
136
137 if (!found) {
Kevin Millikin (Google) 2013/03/12 12:14:56 if (!found) result->Add(field); to match the styl
Vyacheslav Egorov (Google) 2013/03/12 16:54:40 Aligned all conditions here to use the same line b
138 result->Add(field);
139 }
140 }
141 }
142
143 return result;
144 }
145
146
115 // Return false if bailed out. 147 // Return false if bailed out.
116 static bool CompileParsedFunctionHelper(const ParsedFunction& parsed_function, 148 static bool CompileParsedFunctionHelper(const ParsedFunction& parsed_function,
117 bool optimized) { 149 bool optimized) {
118 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); 150 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer);
119 bool is_compiled = false; 151 bool is_compiled = false;
120 Isolate* isolate = Isolate::Current(); 152 Isolate* isolate = Isolate::Current();
121 HANDLESCOPE(isolate); 153 HANDLESCOPE(isolate);
122 ASSERT(isolate->ic_data_array() == Array::null()); // Must be reset to null. 154 ASSERT(isolate->ic_data_array() == Array::null()); // Must be reset to null.
123 const intptr_t prev_deopt_id = isolate->deopt_id(); 155 const intptr_t prev_deopt_id = isolate->deopt_id();
124 isolate->set_deopt_id(0); 156 isolate->set_deopt_id(0);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 // Transform to SSA (virtual register 0 and no inlining arguments). 192 // Transform to SSA (virtual register 0 and no inlining arguments).
161 flow_graph->ComputeSSA(0, NULL); 193 flow_graph->ComputeSSA(0, NULL);
162 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 194 DEBUG_ASSERT(flow_graph->VerifyUseLists());
163 } 195 }
164 196
165 if (FLAG_print_flow_graph || 197 if (FLAG_print_flow_graph ||
166 (optimized && FLAG_print_flow_graph_optimized)) { 198 (optimized && FLAG_print_flow_graph_optimized)) {
167 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); 199 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph);
168 } 200 }
169 201
202 ZoneGrowableArray<Field*>* guarded_fields = NULL;
203
170 if (optimized) { 204 if (optimized) {
171 TimerScope timer(FLAG_compiler_stats, 205 TimerScope timer(FLAG_compiler_stats,
172 &CompilerStats::graphoptimizer_timer, 206 &CompilerStats::graphoptimizer_timer,
173 isolate); 207 isolate);
174 208
175 FlowGraphOptimizer optimizer(flow_graph); 209 FlowGraphOptimizer optimizer(flow_graph);
176 optimizer.ApplyICData(); 210 optimizer.ApplyICData();
177 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 211 DEBUG_ASSERT(flow_graph->VerifyUseLists());
178 212
179 // Optimize (a << b) & c patterns. Must occur before 213 // Optimize (a << b) & c patterns. Must occur before
180 // 'SelectRepresentations' which inserts conversion nodes. 214 // 'SelectRepresentations' which inserts conversion nodes.
181 // TODO(srdjan): Moved before inlining until environment use list can 215 // TODO(srdjan): Moved before inlining until environment use list can
182 // be used to detect when shift-left is outside the scope of bit-and. 216 // be used to detect when shift-left is outside the scope of bit-and.
183 optimizer.TryOptimizeLeftShiftWithBitAndPattern(); 217 optimizer.TryOptimizeLeftShiftWithBitAndPattern();
184 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 218 DEBUG_ASSERT(flow_graph->VerifyUseLists());
185 219
186 // Inlining (mutates the flow graph) 220 // Inlining (mutates the flow graph)
187 if (FLAG_use_inlining) { 221 if (FLAG_use_inlining) {
188 TimerScope timer(FLAG_compiler_stats, 222 TimerScope timer(FLAG_compiler_stats,
189 &CompilerStats::graphinliner_timer); 223 &CompilerStats::graphinliner_timer);
190 FlowGraphInliner inliner(flow_graph); 224 FlowGraphInliner inliner(flow_graph);
191 inliner.Inline(); 225 inliner.Inline();
192 // Use lists are maintained and validated by the inliner. 226 // Use lists are maintained and validated by the inliner.
193 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 227 DEBUG_ASSERT(flow_graph->VerifyUseLists());
194 } 228 }
195 229
230 guarded_fields = CollectGuardedFieldLoads(flow_graph);
Kevin Millikin (Google) 2013/03/12 12:14:56 CollectGuardedFieldLoads might be better as a memb
Vyacheslav Egorov (Google) 2013/03/12 16:54:40 Moved to FlowGraph.
231
196 // Propagate types and eliminate more type tests. 232 // Propagate types and eliminate more type tests.
197 if (FLAG_propagate_types) { 233 if (FLAG_propagate_types) {
198 FlowGraphTypePropagator propagator(flow_graph); 234 FlowGraphTypePropagator propagator(flow_graph);
199 propagator.Propagate(); 235 propagator.Propagate();
200 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 236 DEBUG_ASSERT(flow_graph->VerifyUseLists());
201 } 237 }
202 238
203 // Use propagated class-ids to optimize further. 239 // Use propagated class-ids to optimize further.
204 optimizer.ApplyClassIds(); 240 optimizer.ApplyClassIds();
205 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 241 DEBUG_ASSERT(flow_graph->VerifyUseLists());
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 288
253 if (FLAG_range_analysis) { 289 if (FLAG_range_analysis) {
254 // We have to perform range analysis after LICM because it 290 // We have to perform range analysis after LICM because it
255 // optimistically moves CheckSmi through phis into loop preheaders 291 // optimistically moves CheckSmi through phis into loop preheaders
256 // making some phis smi. 292 // making some phis smi.
257 optimizer.InferSmiRanges(); 293 optimizer.InferSmiRanges();
258 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 294 DEBUG_ASSERT(flow_graph->VerifyUseLists());
259 } 295 }
260 296
261 // The final canonicalization pass before the code generation. 297 // The final canonicalization pass before the code generation.
298 if (FLAG_propagate_types) {
Kevin Millikin (Google) 2013/03/12 12:14:56 I think this (and also the other site) needs a com
299 FlowGraphTypePropagator propagator(flow_graph);
300 propagator.Propagate();
301 DEBUG_ASSERT(flow_graph->VerifyUseLists());
302 }
262 optimizer.Canonicalize(); 303 optimizer.Canonicalize();
263 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 304 DEBUG_ASSERT(flow_graph->VerifyUseLists());
264 305
265 // Perform register allocation on the SSA graph. 306 // Perform register allocation on the SSA graph.
266 FlowGraphAllocator allocator(*flow_graph); 307 FlowGraphAllocator allocator(*flow_graph);
267 allocator.AllocateRegisters(); 308 allocator.AllocateRegisters();
268 309
269 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) { 310 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) {
270 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); 311 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph);
271 } 312 }
(...skipping 17 matching lines...) Expand all
289 const Code& code = Code::Handle( 330 const Code& code = Code::Handle(
290 Code::FinalizeCode(function, &assembler, optimized)); 331 Code::FinalizeCode(function, &assembler, optimized));
291 code.set_is_optimized(optimized); 332 code.set_is_optimized(optimized);
292 graph_compiler.FinalizePcDescriptors(code); 333 graph_compiler.FinalizePcDescriptors(code);
293 graph_compiler.FinalizeDeoptInfo(code); 334 graph_compiler.FinalizeDeoptInfo(code);
294 graph_compiler.FinalizeStackmaps(code); 335 graph_compiler.FinalizeStackmaps(code);
295 graph_compiler.FinalizeVarDescriptors(code); 336 graph_compiler.FinalizeVarDescriptors(code);
296 graph_compiler.FinalizeExceptionHandlers(code); 337 graph_compiler.FinalizeExceptionHandlers(code);
297 graph_compiler.FinalizeComments(code); 338 graph_compiler.FinalizeComments(code);
298 graph_compiler.FinalizeStaticCallTargetsTable(code); 339 graph_compiler.FinalizeStaticCallTargetsTable(code);
340
299 if (optimized) { 341 if (optimized) {
300 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode())); 342 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode()));
301 function.SetCode(code); 343 function.SetCode(code);
302 if (FLAG_trace_compiler) { 344 if (FLAG_trace_compiler) {
303 OS::Print("--> patching entry %#"Px"\n", 345 OS::Print("--> patching entry %#"Px"\n",
304 Code::Handle(function.unoptimized_code()).EntryPoint()); 346 Code::Handle(function.unoptimized_code()).EntryPoint());
305 } 347 }
348
349 const Array& guarded_fields_arr = Array::Handle(
350 Array::New(guarded_fields->length(), Heap::kOld));
Kevin Millikin (Google) 2013/03/12 12:14:56 To fit the pattern, this should be a FinalizeGuard
Vyacheslav Egorov (Google) 2013/03/12 16:54:40 It does not set anything on the code itself now, s
351 for (intptr_t i = 0; i < guarded_fields->length(); i++) {
352 const Field& field = *(*guarded_fields)[i];
353 guarded_fields_arr.SetAt(i, field);
354 field.RegisterDependentCode(code);
355 }
356 code.set_guarded_fields(guarded_fields_arr);
306 } else { 357 } else {
307 function.set_unoptimized_code(code); 358 function.set_unoptimized_code(code);
308 function.SetCode(code); 359 function.SetCode(code);
309 ASSERT(CodePatcher::CodeIsPatchable(code)); 360 ASSERT(CodePatcher::CodeIsPatchable(code));
310 } 361 }
311 } 362 }
312 is_compiled = true; 363 is_compiled = true;
313 } else { 364 } else {
314 // We bailed out. 365 // We bailed out.
315 Error& bailout_error = Error::Handle( 366 Error& bailout_error = Error::Handle(
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 Object::Handle(isolate->object_store()->sticky_error()); 712 Object::Handle(isolate->object_store()->sticky_error());
662 isolate->object_store()->clear_sticky_error(); 713 isolate->object_store()->clear_sticky_error();
663 isolate->set_long_jump_base(base); 714 isolate->set_long_jump_base(base);
664 return result.raw(); 715 return result.raw();
665 } 716 }
666 UNREACHABLE(); 717 UNREACHABLE();
667 return Object::null(); 718 return Object::null();
668 } 719 }
669 720
670 } // namespace dart 721 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698