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/block_scheduler.h" | 10 #include "vm/block_scheduler.h" |
11 #include "vm/cha.h" | |
11 #include "vm/code_generator.h" | 12 #include "vm/code_generator.h" |
12 #include "vm/code_patcher.h" | 13 #include "vm/code_patcher.h" |
13 #include "vm/dart_entry.h" | 14 #include "vm/dart_entry.h" |
14 #include "vm/debugger.h" | 15 #include "vm/debugger.h" |
15 #include "vm/deopt_instructions.h" | 16 #include "vm/deopt_instructions.h" |
16 #include "vm/exceptions.h" | 17 #include "vm/exceptions.h" |
17 #include "vm/flags.h" | 18 #include "vm/flags.h" |
18 #include "vm/flow_graph.h" | 19 #include "vm/flow_graph.h" |
19 #include "vm/flow_graph_allocator.h" | 20 #include "vm/flow_graph_allocator.h" |
20 #include "vm/flow_graph_builder.h" | 21 #include "vm/flow_graph_builder.h" |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
245 bool optimized, | 246 bool optimized, |
246 intptr_t osr_id) { | 247 intptr_t osr_id) { |
247 const Function& function = parsed_function->function(); | 248 const Function& function = parsed_function->function(); |
248 if (optimized && !function.IsOptimizable()) { | 249 if (optimized && !function.IsOptimizable()) { |
249 return false; | 250 return false; |
250 } | 251 } |
251 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); | 252 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); |
252 bool is_compiled = false; | 253 bool is_compiled = false; |
253 Isolate* isolate = Isolate::Current(); | 254 Isolate* isolate = Isolate::Current(); |
254 HANDLESCOPE(isolate); | 255 HANDLESCOPE(isolate); |
255 isolate->set_cha_used(false); | |
256 | 256 |
257 // We may reattempt compilation if the function needs to be assembled using | 257 // We may reattempt compilation if the function needs to be assembled using |
258 // far branches on ARM and MIPS. In the else branch of the setjmp call, | 258 // far branches on ARM and MIPS. In the else branch of the setjmp call, |
259 // done is set to false, and use_far_branches is set to true if there is a | 259 // done is set to false, and use_far_branches is set to true if there is a |
260 // longjmp from the ARM or MIPS assemblers. In all other paths through this | 260 // longjmp from the ARM or MIPS assemblers. In all other paths through this |
261 // while loop, done is set to true. use_far_branches is always false on ia32 | 261 // while loop, done is set to true. use_far_branches is always false on ia32 |
262 // and x64. | 262 // and x64. |
263 bool done = false; | 263 bool done = false; |
264 // volatile because the variable may be clobbered by a longjmp. | 264 // volatile because the variable may be clobbered by a longjmp. |
265 volatile bool use_far_branches = false; | 265 volatile bool use_far_branches = false; |
266 while (!done) { | 266 while (!done) { |
267 const intptr_t prev_deopt_id = isolate->deopt_id(); | 267 const intptr_t prev_deopt_id = isolate->deopt_id(); |
268 isolate->set_deopt_id(0); | 268 isolate->set_deopt_id(0); |
269 LongJumpScope jump; | 269 LongJumpScope jump; |
270 if (setjmp(*jump.Set()) == 0) { | 270 if (setjmp(*jump.Set()) == 0) { |
271 FlowGraph* flow_graph = NULL; | 271 FlowGraph* flow_graph = NULL; |
272 | |
273 // Class hierarchy analysis is registered with the isolate in the | |
274 // constructor and unregisters itself upon destruction. | |
275 CHA cha(isolate); | |
276 | |
272 // TimerScope needs an isolate to be properly terminated in case of a | 277 // TimerScope needs an isolate to be properly terminated in case of a |
273 // LongJump. | 278 // LongJump. |
274 { | 279 { |
275 TimerScope timer(FLAG_compiler_stats, | 280 TimerScope timer(FLAG_compiler_stats, |
276 &CompilerStats::graphbuilder_timer, | 281 &CompilerStats::graphbuilder_timer, |
277 isolate); | 282 isolate); |
278 ZoneGrowableArray<const ICData*>* ic_data_array = | 283 ZoneGrowableArray<const ICData*>* ic_data_array = |
279 new(isolate) ZoneGrowableArray<const ICData*>(); | 284 new(isolate) ZoneGrowableArray<const ICData*>(); |
280 if (optimized) { | 285 if (optimized) { |
281 ASSERT(function.HasCode()); | 286 ASSERT(function.HasCode()); |
282 // Extract type feedback before the graph is built, as the graph | 287 // Extract type feedback before the graph is built, as the graph |
283 // builder uses it to attach it to nodes. | 288 // builder uses it to attach it to nodes. |
284 ASSERT(function.deoptimization_counter() < | 289 ASSERT(function.deoptimization_counter() < |
285 FLAG_deoptimization_counter_threshold); | 290 FLAG_deoptimization_counter_threshold); |
286 function.RestoreICDataMap(ic_data_array); | 291 function.RestoreICDataMap(ic_data_array); |
287 } | 292 } |
288 | 293 |
294 | |
Vyacheslav Egorov (Google)
2014/08/13 11:40:28
Accidental edit?
Florian Schneider
2014/08/13 12:08:58
Done.
| |
289 // Build the flow graph. | 295 // Build the flow graph. |
290 FlowGraphBuilder builder(parsed_function, | 296 FlowGraphBuilder builder(parsed_function, |
291 *ic_data_array, | 297 *ic_data_array, |
292 NULL, // NULL = not inlining. | 298 NULL, // NULL = not inlining. |
293 osr_id, | 299 osr_id, |
294 optimized); | 300 optimized); |
295 flow_graph = builder.BuildGraph(); | 301 flow_graph = builder.BuildGraph(); |
296 } | 302 } |
297 | 303 |
298 if (FLAG_print_flow_graph || | 304 if (FLAG_print_flow_graph || |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
538 isolate); | 544 isolate); |
539 graph_compiler.CompileGraph(); | 545 graph_compiler.CompileGraph(); |
540 } | 546 } |
541 { | 547 { |
542 TimerScope timer(FLAG_compiler_stats, | 548 TimerScope timer(FLAG_compiler_stats, |
543 &CompilerStats::codefinalizer_timer, | 549 &CompilerStats::codefinalizer_timer, |
544 isolate); | 550 isolate); |
545 const Code& code = Code::Handle( | 551 const Code& code = Code::Handle( |
546 Code::FinalizeCode(function, &assembler, optimized)); | 552 Code::FinalizeCode(function, &assembler, optimized)); |
547 code.set_is_optimized(optimized); | 553 code.set_is_optimized(optimized); |
548 // CHA should not be used for unoptimized code. | |
549 ASSERT(optimized || !isolate->cha_used()); | |
550 if (isolate->cha_used()) { | |
551 Class::Handle(function.Owner()).RegisterCHACode(code); | |
552 isolate->set_cha_used(false); | |
553 } | |
554 graph_compiler.FinalizePcDescriptors(code); | 554 graph_compiler.FinalizePcDescriptors(code); |
555 graph_compiler.FinalizeDeoptInfo(code); | 555 graph_compiler.FinalizeDeoptInfo(code); |
556 graph_compiler.FinalizeStackmaps(code); | 556 graph_compiler.FinalizeStackmaps(code); |
557 graph_compiler.FinalizeVarDescriptors(code); | 557 graph_compiler.FinalizeVarDescriptors(code); |
558 graph_compiler.FinalizeExceptionHandlers(code); | 558 graph_compiler.FinalizeExceptionHandlers(code); |
559 graph_compiler.FinalizeStaticCallTargetsTable(code); | 559 graph_compiler.FinalizeStaticCallTargetsTable(code); |
560 | 560 |
561 if (optimized) { | 561 if (optimized) { |
562 if (osr_id == Isolate::kNoDeoptId) { | 562 if (osr_id == Isolate::kNoDeoptId) { |
563 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode())); | 563 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode())); |
564 if (FLAG_trace_compiler || FLAG_trace_patching) { | 564 if (FLAG_trace_compiler || FLAG_trace_patching) { |
565 if (FLAG_trace_compiler) { | 565 if (FLAG_trace_compiler) { |
566 OS::Print(" "); | 566 OS::Print(" "); |
567 } | 567 } |
568 OS::Print("Patch unoptimized '%s' entry point %#" Px "\n", | 568 OS::Print("Patch unoptimized '%s' entry point %#" Px "\n", |
569 function.ToFullyQualifiedCString(), | 569 function.ToFullyQualifiedCString(), |
570 Code::Handle(function.unoptimized_code()).EntryPoint()); | 570 Code::Handle(function.unoptimized_code()).EntryPoint()); |
571 } | 571 } |
572 } | 572 } |
573 function.AttachCode(code); | 573 function.AttachCode(code); |
574 | 574 |
575 // Register code with the classes it depends on because of CHA. | |
576 for (intptr_t i = 0; | |
577 i < isolate->cha()->cha_classes().length(); | |
578 ++i) { | |
579 isolate->cha()->cha_classes()[i]->RegisterCHACode(code); | |
580 } | |
581 | |
575 for (intptr_t i = 0; | 582 for (intptr_t i = 0; |
576 i < flow_graph->guarded_fields()->length(); | 583 i < flow_graph->guarded_fields()->length(); |
577 i++) { | 584 i++) { |
578 const Field* field = (*flow_graph->guarded_fields())[i]; | 585 const Field* field = (*flow_graph->guarded_fields())[i]; |
579 field->RegisterDependentCode(code); | 586 field->RegisterDependentCode(code); |
580 } | 587 } |
581 } else { // not optimized. | 588 } else { // not optimized. |
582 if (function.ic_data_array() == Array::null()) { | 589 if (function.ic_data_array() == Array::null()) { |
583 function.SaveICDataMap(graph_compiler.deopt_id_to_ic_data()); | 590 function.SaveICDataMap(graph_compiler.deopt_id_to_ic_data()); |
584 } | 591 } |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
973 const Object& result = | 980 const Object& result = |
974 Object::Handle(isolate->object_store()->sticky_error()); | 981 Object::Handle(isolate->object_store()->sticky_error()); |
975 isolate->object_store()->clear_sticky_error(); | 982 isolate->object_store()->clear_sticky_error(); |
976 return result.raw(); | 983 return result.raw(); |
977 } | 984 } |
978 UNREACHABLE(); | 985 UNREACHABLE(); |
979 return Object::null(); | 986 return Object::null(); |
980 } | 987 } |
981 | 988 |
982 } // namespace dart | 989 } // namespace dart |
OLD | NEW |