| 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/globals.h" // Needed here to get TARGET_ARCH_XXX. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_XXX. |
| 6 | 6 |
| 7 #include "vm/flow_graph_compiler.h" | 7 #include "vm/flow_graph_compiler.h" |
| 8 | 8 |
| 9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/debugger.h" | 10 #include "vm/debugger.h" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 AllocateIncomingParametersRecursive(env->outer(), stack_height); | 55 AllocateIncomingParametersRecursive(env->outer(), stack_height); |
| 56 for (Environment::ShallowIterator it(env); !it.Done(); it.Advance()) { | 56 for (Environment::ShallowIterator it(env); !it.Done(); it.Advance()) { |
| 57 if (it.CurrentLocation().IsInvalid()) { | 57 if (it.CurrentLocation().IsInvalid()) { |
| 58 ASSERT(it.CurrentValue()->definition()->IsPushArgument()); | 58 ASSERT(it.CurrentValue()->definition()->IsPushArgument()); |
| 59 it.SetCurrentLocation(Location::StackSlot((*stack_height)++)); | 59 it.SetCurrentLocation(Location::StackSlot((*stack_height)++)); |
| 60 } | 60 } |
| 61 } | 61 } |
| 62 } | 62 } |
| 63 | 63 |
| 64 | 64 |
| 65 RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler) { | 65 RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler, |
| 66 DeoptInfoBuilder* builder) { |
| 66 if (deoptimization_env_ == NULL) return DeoptInfo::null(); | 67 if (deoptimization_env_ == NULL) return DeoptInfo::null(); |
| 67 | 68 |
| 68 intptr_t stack_height = compiler->StackSize(); | 69 intptr_t stack_height = compiler->StackSize(); |
| 69 AllocateIncomingParametersRecursive(deoptimization_env_, &stack_height); | 70 AllocateIncomingParametersRecursive(deoptimization_env_, &stack_height); |
| 70 | 71 |
| 71 const Function& function = compiler->parsed_function().function(); | |
| 72 // For functions with optional arguments, all incoming arguments are copied | |
| 73 // to spill slots. The deoptimization environment does not track them. | |
| 74 const intptr_t incoming_arg_count = | |
| 75 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | |
| 76 DeoptInfoBuilder builder(compiler->object_table(), incoming_arg_count); | |
| 77 | |
| 78 intptr_t slot_ix = 0; | 72 intptr_t slot_ix = 0; |
| 79 Environment* inner = deoptimization_env_; | 73 Environment* current = deoptimization_env_; |
| 80 | 74 |
| 81 // For the innermost environment, call the virtual return builder. | 75 // For the innermost environment, call the virtual return builder. |
| 82 BuildReturnAddress(&builder, inner->function(), slot_ix++); | 76 BuildReturnAddress(builder, current->function(), slot_ix++); |
| 83 | 77 |
| 84 // For the innermost environment, set outgoing arguments and the locals. | 78 // For the innermost environment, set outgoing arguments and the locals. |
| 85 for (intptr_t i = inner->Length() - 1; | 79 for (intptr_t i = current->Length() - 1; |
| 86 i >= inner->fixed_parameter_count(); | 80 i >= current->fixed_parameter_count(); |
| 87 i--) { | 81 i--) { |
| 88 builder.AddCopy(inner->LocationAt(i), *inner->ValueAt(i), slot_ix++); | 82 builder->AddCopy(current->LocationAt(i), *current->ValueAt(i), slot_ix++); |
| 89 } | 83 } |
| 90 | 84 |
| 91 // PC marker and caller FP. | 85 // PC marker and caller FP. |
| 92 builder.AddPcMarker(inner->function(), slot_ix++); | 86 builder->AddPcMarker(current->function(), slot_ix++); |
| 93 builder.AddCallerFp(slot_ix++); | 87 builder->AddCallerFp(slot_ix++); |
| 94 | 88 |
| 95 while (inner->outer() != NULL) { | 89 Environment* previous = current; |
| 96 // Write the frame for an outer environment. | 90 current = current->outer(); |
| 97 const Environment* current = inner->outer(); | 91 while (current != NULL) { |
| 98 | |
| 99 // For any outer environment the deopt id is that of the call instruction | 92 // For any outer environment the deopt id is that of the call instruction |
| 100 // which is recorded in the outer environment. | 93 // which is recorded in the outer environment. |
| 101 builder.AddReturnAddressAfter(current->function(), | 94 builder->AddReturnAddressAfter(current->function(), |
| 102 current->deopt_id(), | 95 current->deopt_id(), |
| 103 slot_ix++); | 96 slot_ix++); |
| 104 | 97 |
| 105 // The values of outgoing arguments can be changed from the inlined call so | 98 // The values of outgoing arguments can be changed from the inlined call so |
| 106 // we must read them from the inner environment. | 99 // we must read them from the previous environment. |
| 107 for (intptr_t i = inner->fixed_parameter_count() - 1; i >= 0; i--) { | 100 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { |
| 108 builder.AddCopy(inner->LocationAt(i), *inner->ValueAt(i), slot_ix++); | 101 builder->AddCopy(previous->LocationAt(i), *previous->ValueAt(i), |
| 102 slot_ix++); |
| 109 } | 103 } |
| 110 | 104 |
| 111 // Set the locals, note that outgoing arguments are not in the environment. | 105 // Set the locals, note that outgoing arguments are not in the environment. |
| 112 for (intptr_t i = current->Length() - 1; | 106 for (intptr_t i = current->Length() - 1; |
| 113 i >= current->fixed_parameter_count(); | 107 i >= current->fixed_parameter_count(); |
| 114 i--) { | 108 i--) { |
| 115 builder.AddCopy(current->LocationAt(i), *current->ValueAt(i), slot_ix++); | 109 builder->AddCopy(current->LocationAt(i), *current->ValueAt(i), slot_ix++); |
| 116 } | 110 } |
| 117 | 111 |
| 118 // PC marker and caller FP. | 112 // PC marker and caller FP. |
| 119 builder.AddPcMarker(current->function(), slot_ix++); | 113 builder->AddPcMarker(current->function(), slot_ix++); |
| 120 builder.AddCallerFp(slot_ix++); | 114 builder->AddCallerFp(slot_ix++); |
| 121 | 115 |
| 122 // Iterate on the outer environment. | 116 // Iterate on the outer environment. |
| 123 inner = inner->outer(); | 117 previous = current; |
| 118 current = current->outer(); |
| 124 } | 119 } |
| 125 ASSERT(inner != NULL); // The inner pointer is now the outermost environment. | 120 // The previous pointer is now the outermost environment. |
| 121 ASSERT(previous != NULL); |
| 126 | 122 |
| 127 // For the outermost environment, set caller PC. | 123 // For the outermost environment, set caller PC. |
| 128 builder.AddCallerPc(slot_ix++); | 124 builder->AddCallerPc(slot_ix++); |
| 129 | 125 |
| 130 // For the outermost environment, set the incoming arguments. | 126 // For the outermost environment, set the incoming arguments. |
| 131 for (intptr_t i = inner->fixed_parameter_count() - 1; i >= 0; i--) { | 127 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { |
| 132 builder.AddCopy(inner->LocationAt(i), *inner->ValueAt(i), slot_ix++); | 128 builder->AddCopy(previous->LocationAt(i), *previous->ValueAt(i), slot_ix++); |
| 133 } | 129 } |
| 134 | 130 |
| 135 const DeoptInfo& deopt_info = DeoptInfo::Handle(builder.CreateDeoptInfo()); | 131 const DeoptInfo& deopt_info = DeoptInfo::Handle(builder->CreateDeoptInfo()); |
| 136 return deopt_info.raw(); | 132 return deopt_info.raw(); |
| 137 } | 133 } |
| 138 | 134 |
| 139 | 135 |
| 140 FlowGraphCompiler::FlowGraphCompiler(Assembler* assembler, | 136 FlowGraphCompiler::FlowGraphCompiler(Assembler* assembler, |
| 141 const FlowGraph& flow_graph, | 137 const FlowGraph& flow_graph, |
| 142 bool is_optimizing, | 138 bool is_optimizing, |
| 143 bool is_leaf) | 139 bool is_leaf) |
| 144 : assembler_(assembler), | 140 : assembler_(assembler), |
| 145 parsed_function_(flow_graph.parsed_function()), | 141 parsed_function_(flow_graph.parsed_function()), |
| 146 block_order_(flow_graph.reverse_postorder()), | 142 block_order_(flow_graph.reverse_postorder()), |
| 147 current_block_(NULL), | 143 current_block_(NULL), |
| 148 exception_handlers_list_(NULL), | 144 exception_handlers_list_(NULL), |
| 149 pc_descriptors_list_(NULL), | 145 pc_descriptors_list_(NULL), |
| 150 stackmap_table_builder_( | 146 stackmap_table_builder_( |
| 151 is_optimizing ? new StackmapTableBuilder() : NULL), | 147 is_optimizing ? new StackmapTableBuilder() : NULL), |
| 152 block_info_(block_order_.length()), | 148 block_info_(block_order_.length()), |
| 153 deopt_infos_(), | 149 deopt_infos_(), |
| 154 object_table_(GrowableObjectArray::Handle(GrowableObjectArray::New())), | |
| 155 is_optimizing_(is_optimizing), | 150 is_optimizing_(is_optimizing), |
| 156 is_dart_leaf_(is_leaf), | 151 is_dart_leaf_(is_leaf), |
| 157 bool_true_(Bool::ZoneHandle(Bool::True())), | 152 bool_true_(Bool::ZoneHandle(Bool::True())), |
| 158 bool_false_(Bool::ZoneHandle(Bool::False())), | 153 bool_false_(Bool::ZoneHandle(Bool::False())), |
| 159 double_class_(Class::ZoneHandle( | 154 double_class_(Class::ZoneHandle( |
| 160 Isolate::Current()->object_store()->double_class())), | 155 Isolate::Current()->object_store()->double_class())), |
| 161 parallel_move_resolver_(this) { | 156 parallel_move_resolver_(this) { |
| 162 ASSERT(assembler != NULL); | 157 ASSERT(assembler != NULL); |
| 163 } | 158 } |
| 164 | 159 |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 void FlowGraphCompiler::FinalizePcDescriptors(const Code& code) { | 377 void FlowGraphCompiler::FinalizePcDescriptors(const Code& code) { |
| 383 ASSERT(pc_descriptors_list_ != NULL); | 378 ASSERT(pc_descriptors_list_ != NULL); |
| 384 const PcDescriptors& descriptors = PcDescriptors::Handle( | 379 const PcDescriptors& descriptors = PcDescriptors::Handle( |
| 385 pc_descriptors_list_->FinalizePcDescriptors(code.EntryPoint())); | 380 pc_descriptors_list_->FinalizePcDescriptors(code.EntryPoint())); |
| 386 if (!is_optimizing_) descriptors.Verify(parsed_function_.function()); | 381 if (!is_optimizing_) descriptors.Verify(parsed_function_.function()); |
| 387 code.set_pc_descriptors(descriptors); | 382 code.set_pc_descriptors(descriptors); |
| 388 } | 383 } |
| 389 | 384 |
| 390 | 385 |
| 391 void FlowGraphCompiler::FinalizeDeoptInfo(const Code& code) { | 386 void FlowGraphCompiler::FinalizeDeoptInfo(const Code& code) { |
| 387 // For functions with optional arguments, all incoming arguments are copied |
| 388 // to spill slots. The deoptimization environment does not track them. |
| 389 const Function& function = parsed_function().function(); |
| 390 const intptr_t incoming_arg_count = |
| 391 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
| 392 DeoptInfoBuilder builder(incoming_arg_count); |
| 393 |
| 392 const Array& array = | 394 const Array& array = |
| 393 Array::Handle(Array::New(DeoptTable::SizeFor(deopt_infos_.length()), | 395 Array::Handle(Array::New(DeoptTable::SizeFor(deopt_infos_.length()), |
| 394 Heap::kOld)); | 396 Heap::kOld)); |
| 395 Smi& offset = Smi::Handle(); | 397 Smi& offset = Smi::Handle(); |
| 396 DeoptInfo& info = DeoptInfo::Handle(); | 398 DeoptInfo& info = DeoptInfo::Handle(); |
| 397 Smi& reason = Smi::Handle(); | 399 Smi& reason = Smi::Handle(); |
| 398 for (intptr_t i = 0; i < deopt_infos_.length(); i++) { | 400 for (intptr_t i = 0; i < deopt_infos_.length(); i++) { |
| 399 offset = Smi::New(deopt_infos_[i]->pc_offset()); | 401 offset = Smi::New(deopt_infos_[i]->pc_offset()); |
| 400 info = deopt_infos_[i]->CreateDeoptInfo(this); | 402 info = deopt_infos_[i]->CreateDeoptInfo(this, &builder); |
| 401 reason = Smi::New(deopt_infos_[i]->reason()); | 403 reason = Smi::New(deopt_infos_[i]->reason()); |
| 402 DeoptTable::SetEntry(array, i, offset, info, reason); | 404 DeoptTable::SetEntry(array, i, offset, info, reason); |
| 403 } | 405 } |
| 404 code.set_deopt_info_array(array); | 406 code.set_deopt_info_array(array); |
| 405 const Array& object_array = Array::Handle(Array::MakeArray(object_table_)); | 407 const Array& object_array = |
| 408 Array::Handle(Array::MakeArray(builder.object_table())); |
| 406 code.set_object_table(object_array); | 409 code.set_object_table(object_array); |
| 407 } | 410 } |
| 408 | 411 |
| 409 | 412 |
| 410 void FlowGraphCompiler::FinalizeStackmaps(const Code& code) { | 413 void FlowGraphCompiler::FinalizeStackmaps(const Code& code) { |
| 411 if (stackmap_table_builder_ == NULL) { | 414 if (stackmap_table_builder_ == NULL) { |
| 412 // The unoptimizing compiler has no stack maps. | 415 // The unoptimizing compiler has no stack maps. |
| 413 code.set_stackmaps(Array::Handle()); | 416 code.set_stackmaps(Array::Handle()); |
| 414 } else { | 417 } else { |
| 415 // Finalize the stack map array and add it to the code object. | 418 // Finalize the stack map array and add it to the code object. |
| (...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 900 case ABOVE: return unsigned_left > unsigned_right; | 903 case ABOVE: return unsigned_left > unsigned_right; |
| 901 case ABOVE_EQUAL: return unsigned_left >= unsigned_right; | 904 case ABOVE_EQUAL: return unsigned_left >= unsigned_right; |
| 902 default: | 905 default: |
| 903 UNIMPLEMENTED(); | 906 UNIMPLEMENTED(); |
| 904 return false; | 907 return false; |
| 905 } | 908 } |
| 906 } | 909 } |
| 907 | 910 |
| 908 | 911 |
| 909 } // namespace dart | 912 } // namespace dart |
| OLD | NEW |