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 |