Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |