| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/cha.h" | 9 #include "vm/cha.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 static bool IsEmptyBlock(BlockEntryInstr* block) { | 173 static bool IsEmptyBlock(BlockEntryInstr* block) { |
| 174 return !block->HasParallelMove() && | 174 return !block->HasParallelMove() && |
| 175 block->next()->IsGoto() && | 175 block->next()->IsGoto() && |
| 176 !block->next()->AsGoto()->HasParallelMove(); | 176 !block->next()->AsGoto()->HasParallelMove(); |
| 177 } | 177 } |
| 178 | 178 |
| 179 | 179 |
| 180 void FlowGraphCompiler::CompactBlock(BlockEntryInstr* block) { | 180 void FlowGraphCompiler::CompactBlock(BlockEntryInstr* block) { |
| 181 BlockInfo* block_info = block_info_[block->postorder_number()]; | 181 BlockInfo* block_info = block_info_[block->postorder_number()]; |
| 182 | 182 |
| 183 // Break out of cycles in the control flow graph. |
| 183 if (block_info->is_marked()) { | 184 if (block_info->is_marked()) { |
| 184 return; | 185 return; |
| 185 } | 186 } |
| 186 block_info->mark(); | 187 block_info->mark(); |
| 187 | 188 |
| 188 if (IsEmptyBlock(block)) { | 189 if (IsEmptyBlock(block)) { |
| 190 // For empty blocks, record a corresponding nonempty target as their |
| 191 // jump label. |
| 189 BlockEntryInstr* target = block->next()->AsGoto()->successor(); | 192 BlockEntryInstr* target = block->next()->AsGoto()->successor(); |
| 190 CompactBlock(target); | 193 CompactBlock(target); |
| 191 block_info->set_jump_label(GetJumpLabel(target)); | 194 block_info->set_jump_label(GetJumpLabel(target)); |
| 192 } | 195 } |
| 193 } | 196 } |
| 194 | 197 |
| 195 | 198 |
| 196 void FlowGraphCompiler::CompactBlocks() { | 199 void FlowGraphCompiler::CompactBlocks() { |
| 197 Label* fallthrough_label = NULL; | 200 // This algorithm does not garbage collect blocks in place, but merely |
| 201 // records forwarding label information. In this way it avoids having to |
| 202 // change join and target entries. |
| 203 Label* nonempty_label = NULL; |
| 198 for (intptr_t i = block_order().length() - 1; i >= 1; --i) { | 204 for (intptr_t i = block_order().length() - 1; i >= 1; --i) { |
| 199 BlockEntryInstr* block = block_order()[i]; | 205 BlockEntryInstr* block = block_order()[i]; |
| 200 | 206 |
| 201 // Unoptimized code must emit all possible deoptimization points. | 207 // Unoptimized code must emit all possible deoptimization points. |
| 202 if (is_optimizing()) { | 208 if (is_optimizing()) { |
| 203 CompactBlock(block); | 209 CompactBlock(block); |
| 204 } | 210 } |
| 205 | 211 |
| 212 // For nonempty blocks, record the next nonempty block in the block |
| 213 // order. Since no code is emitted for empty blocks, control flow is |
| 214 // eligible to fall through to the next nonempty one. |
| 206 if (!WasCompacted(block)) { | 215 if (!WasCompacted(block)) { |
| 207 BlockInfo* block_info = block_info_[block->postorder_number()]; | 216 BlockInfo* block_info = block_info_[block->postorder_number()]; |
| 208 block_info->set_fallthrough_label(fallthrough_label); | 217 block_info->set_next_nonempty_label(nonempty_label); |
| 209 fallthrough_label = GetJumpLabel(block); | 218 nonempty_label = GetJumpLabel(block); |
| 210 } | 219 } |
| 211 } | 220 } |
| 212 | 221 |
| 213 ASSERT(block_order()[0]->IsGraphEntry()); | 222 ASSERT(block_order()[0]->IsGraphEntry()); |
| 214 BlockInfo* block_info = block_info_[block_order()[0]->postorder_number()]; | 223 BlockInfo* block_info = block_info_[block_order()[0]->postorder_number()]; |
| 215 block_info->set_fallthrough_label(fallthrough_label); | 224 block_info->set_next_nonempty_label(nonempty_label); |
| 216 } | 225 } |
| 217 | 226 |
| 218 | 227 |
| 219 void FlowGraphCompiler::VisitBlocks() { | 228 void FlowGraphCompiler::VisitBlocks() { |
| 220 CompactBlocks(); | 229 CompactBlocks(); |
| 221 | 230 |
| 222 for (intptr_t i = 0; i < block_order().length(); ++i) { | 231 for (intptr_t i = 0; i < block_order().length(); ++i) { |
| 223 // Compile the block entry. | 232 // Compile the block entry. |
| 224 BlockEntryInstr* entry = block_order()[i]; | 233 BlockEntryInstr* entry = block_order()[i]; |
| 225 assembler()->Comment("B%" Pd "", entry->block_id()); | 234 assembler()->Comment("B%" Pd "", entry->block_id()); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 | 291 |
| 283 bool FlowGraphCompiler::WasCompacted( | 292 bool FlowGraphCompiler::WasCompacted( |
| 284 BlockEntryInstr* block_entry) const { | 293 BlockEntryInstr* block_entry) const { |
| 285 const intptr_t block_index = block_entry->postorder_number(); | 294 const intptr_t block_index = block_entry->postorder_number(); |
| 286 return block_info_[block_index]->WasCompacted(); | 295 return block_info_[block_index]->WasCompacted(); |
| 287 } | 296 } |
| 288 | 297 |
| 289 | 298 |
| 290 bool FlowGraphCompiler::CanFallThroughTo(BlockEntryInstr* block_entry) const { | 299 bool FlowGraphCompiler::CanFallThroughTo(BlockEntryInstr* block_entry) const { |
| 291 const intptr_t current_index = current_block()->postorder_number(); | 300 const intptr_t current_index = current_block()->postorder_number(); |
| 292 Label* fallthrough_label = block_info_[current_index]->fallthrough_label(); | 301 Label* next_nonempty = block_info_[current_index]->next_nonempty_label(); |
| 293 return fallthrough_label == GetJumpLabel(block_entry); | 302 return next_nonempty == GetJumpLabel(block_entry); |
| 294 } | 303 } |
| 295 | 304 |
| 296 | 305 |
| 297 void FlowGraphCompiler::AddSlowPathCode(SlowPathCode* code) { | 306 void FlowGraphCompiler::AddSlowPathCode(SlowPathCode* code) { |
| 298 slow_path_code_.Add(code); | 307 slow_path_code_.Add(code); |
| 299 } | 308 } |
| 300 | 309 |
| 301 | 310 |
| 302 void FlowGraphCompiler::GenerateDeferredCode() { | 311 void FlowGraphCompiler::GenerateDeferredCode() { |
| 303 for (intptr_t i = 0; i < slow_path_code_.length(); i++) { | 312 for (intptr_t i = 0; i < slow_path_code_.length(); i++) { |
| (...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1100 | 1109 |
| 1101 for (int i = 0; i < len; i++) { | 1110 for (int i = 0; i < len; i++) { |
| 1102 sorted->Add(CidTarget(ic_data.GetReceiverClassIdAt(i), | 1111 sorted->Add(CidTarget(ic_data.GetReceiverClassIdAt(i), |
| 1103 &Function::ZoneHandle(ic_data.GetTargetAt(i)), | 1112 &Function::ZoneHandle(ic_data.GetTargetAt(i)), |
| 1104 ic_data.GetCountAt(i))); | 1113 ic_data.GetCountAt(i))); |
| 1105 } | 1114 } |
| 1106 sorted->Sort(HighestCountFirst); | 1115 sorted->Sort(HighestCountFirst); |
| 1107 } | 1116 } |
| 1108 | 1117 |
| 1109 } // namespace dart | 1118 } // namespace dart |
| OLD | NEW |