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/bit_vector.h" | 9 #include "vm/bit_vector.h" |
10 #include "vm/cha.h" | 10 #include "vm/cha.h" |
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 for (intptr_t i = 0; i < block_order().length(); ++i) { | 496 for (intptr_t i = 0; i < block_order().length(); ++i) { |
497 // Compile the block entry. | 497 // Compile the block entry. |
498 BlockEntryInstr* entry = block_order()[i]; | 498 BlockEntryInstr* entry = block_order()[i]; |
499 assembler()->Comment("B%" Pd "", entry->block_id()); | 499 assembler()->Comment("B%" Pd "", entry->block_id()); |
500 set_current_block(entry); | 500 set_current_block(entry); |
501 | 501 |
502 if (WasCompacted(entry)) { | 502 if (WasCompacted(entry)) { |
503 continue; | 503 continue; |
504 } | 504 } |
505 | 505 |
506 #if defined(DEBUG) | 506 #if defined(DEBUG) && !defined(TARGET_ARCH_DBC) |
507 if (!is_optimizing()) { | 507 if (!is_optimizing()) { |
508 FrameStateClear(); | 508 FrameStateClear(); |
509 } | 509 } |
510 #endif | 510 #endif |
511 | 511 |
512 LoopInfoComment(assembler(), *entry, *loop_headers); | 512 LoopInfoComment(assembler(), *entry, *loop_headers); |
513 | 513 |
514 entry->set_offset(assembler()->CodeSize()); | 514 entry->set_offset(assembler()->CodeSize()); |
515 BeginCodeSourceRange(); | 515 BeginCodeSourceRange(); |
516 entry->EmitNativeCode(this); | 516 entry->EmitNativeCode(this); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
550 BeginCodeSourceRange(); | 550 BeginCodeSourceRange(); |
551 EmitInstructionPrologue(instr); | 551 EmitInstructionPrologue(instr); |
552 ASSERT(pending_deoptimization_env_ == NULL); | 552 ASSERT(pending_deoptimization_env_ == NULL); |
553 pending_deoptimization_env_ = instr->env(); | 553 pending_deoptimization_env_ = instr->env(); |
554 instr->EmitNativeCode(this); | 554 instr->EmitNativeCode(this); |
555 pending_deoptimization_env_ = NULL; | 555 pending_deoptimization_env_ = NULL; |
556 EmitInstructionEpilogue(instr); | 556 EmitInstructionEpilogue(instr); |
557 EndCodeSourceRange(instr->token_pos()); | 557 EndCodeSourceRange(instr->token_pos()); |
558 } | 558 } |
559 | 559 |
560 #if defined(DEBUG) | 560 #if defined(DEBUG) && !defined(TARGET_ARCH_DBC) |
561 if (!is_optimizing()) { | 561 if (!is_optimizing()) { |
562 FrameStateUpdateWith(instr); | 562 FrameStateUpdateWith(instr); |
563 } | 563 } |
564 #endif | 564 #endif |
565 } | 565 } |
566 | 566 |
567 #if defined(DEBUG) | 567 #if defined(DEBUG) && !defined(TARGET_ARCH_DBC) |
568 ASSERT(is_optimizing() || FrameStateIsSafeToCall()); | 568 ASSERT(is_optimizing() || FrameStateIsSafeToCall()); |
569 #endif | 569 #endif |
570 } | 570 } |
571 | 571 |
572 if (is_optimizing()) { | 572 if (is_optimizing()) { |
573 LogBlock lb; | 573 LogBlock lb; |
574 intervals.Add( | 574 intervals.Add( |
575 IntervalStruct(prev_offset, prev_inlining_pos, prev_inlining_id)); | 575 IntervalStruct(prev_offset, prev_inlining_pos, prev_inlining_id)); |
576 inlined_code_intervals_ = | 576 inlined_code_intervals_ = |
577 Array::New(intervals.length() * Code::kInlIntNumEntries, Heap::kOld); | 577 Array::New(intervals.length() * Code::kInlIntNumEntries, Heap::kOld); |
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1140 // branches from intrinsic code redirect to here where the slow-path | 1140 // branches from intrinsic code redirect to here where the slow-path |
1141 // (normal function body) starts. | 1141 // (normal function body) starts. |
1142 // This means that there must not be any side-effects in intrinsic code | 1142 // This means that there must not be any side-effects in intrinsic code |
1143 // before any deoptimization point. | 1143 // before any deoptimization point. |
1144 ASSERT(!intrinsic_slow_path_label_.IsBound()); | 1144 ASSERT(!intrinsic_slow_path_label_.IsBound()); |
1145 assembler()->Bind(&intrinsic_slow_path_label_); | 1145 assembler()->Bind(&intrinsic_slow_path_label_); |
1146 return false; | 1146 return false; |
1147 } | 1147 } |
1148 | 1148 |
1149 | 1149 |
| 1150 // DBC is very different from other architectures in how it performs instance |
| 1151 // and static calls because it does not use stubs. |
| 1152 #if !defined(TARGET_ARCH_DBC) |
1150 void FlowGraphCompiler::GenerateInstanceCall( | 1153 void FlowGraphCompiler::GenerateInstanceCall( |
1151 intptr_t deopt_id, | 1154 intptr_t deopt_id, |
1152 TokenPosition token_pos, | 1155 TokenPosition token_pos, |
1153 intptr_t argument_count, | 1156 intptr_t argument_count, |
1154 LocationSummary* locs, | 1157 LocationSummary* locs, |
1155 const ICData& ic_data_in) { | 1158 const ICData& ic_data_in) { |
1156 ICData& ic_data = ICData::ZoneHandle(ic_data_in.Original()); | 1159 ICData& ic_data = ICData::ZoneHandle(ic_data_in.Original()); |
1157 if (FLAG_precompiled_mode) { | 1160 if (FLAG_precompiled_mode) { |
1158 ic_data = ic_data.AsUnaryClassChecks(); | 1161 ic_data = ic_data.AsUnaryClassChecks(); |
1159 EmitSwitchableInstanceCall(ic_data, argument_count, | 1162 EmitSwitchableInstanceCall(ic_data, argument_count, |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1279 Label* is_instance_lbl) { | 1282 Label* is_instance_lbl) { |
1280 assembler()->Comment("ListTypeCheck"); | 1283 assembler()->Comment("ListTypeCheck"); |
1281 Label unknown; | 1284 Label unknown; |
1282 GrowableArray<intptr_t> args; | 1285 GrowableArray<intptr_t> args; |
1283 args.Add(kArrayCid); | 1286 args.Add(kArrayCid); |
1284 args.Add(kGrowableObjectArrayCid); | 1287 args.Add(kGrowableObjectArrayCid); |
1285 args.Add(kImmutableArrayCid); | 1288 args.Add(kImmutableArrayCid); |
1286 CheckClassIds(kClassIdReg, args, is_instance_lbl, &unknown); | 1289 CheckClassIds(kClassIdReg, args, is_instance_lbl, &unknown); |
1287 assembler()->Bind(&unknown); | 1290 assembler()->Bind(&unknown); |
1288 } | 1291 } |
1289 | 1292 #endif // !defined(TARGET_ARCH_DBC) |
1290 | 1293 |
1291 void FlowGraphCompiler::EmitComment(Instruction* instr) { | 1294 void FlowGraphCompiler::EmitComment(Instruction* instr) { |
1292 if (!FLAG_support_il_printer || !FLAG_support_disassembler) { | 1295 if (!FLAG_support_il_printer || !FLAG_support_disassembler) { |
1293 return; | 1296 return; |
1294 } | 1297 } |
1295 #ifndef PRODUCT | 1298 #ifndef PRODUCT |
1296 char buffer[256]; | 1299 char buffer[256]; |
1297 BufferFormatter f(buffer, sizeof(buffer)); | 1300 BufferFormatter f(buffer, sizeof(buffer)); |
1298 instr->PrintTo(&f); | 1301 instr->PrintTo(&f); |
1299 assembler()->Comment("%s", buffer); | 1302 assembler()->Comment("%s", buffer); |
1300 #endif | 1303 #endif |
1301 } | 1304 } |
1302 | 1305 |
1303 | 1306 |
| 1307 #if !defined(TARGET_ARCH_DBC) |
| 1308 // TODO(vegorov) enable edge-counters on DBC if we consider them beneficial. |
1304 bool FlowGraphCompiler::NeedsEdgeCounter(TargetEntryInstr* block) { | 1309 bool FlowGraphCompiler::NeedsEdgeCounter(TargetEntryInstr* block) { |
1305 // Only emit an edge counter if there is not goto at the end of the block, | 1310 // Only emit an edge counter if there is not goto at the end of the block, |
1306 // except for the entry block. | 1311 // except for the entry block. |
1307 return (FLAG_reorder_basic_blocks | 1312 return (FLAG_reorder_basic_blocks |
1308 && (!block->last_instruction()->IsGoto() | 1313 && (!block->last_instruction()->IsGoto() |
1309 || (block == flow_graph().graph_entry()->normal_entry()))); | 1314 || (block == flow_graph().graph_entry()->normal_entry()))); |
1310 } | 1315 } |
1311 | 1316 |
1312 | 1317 |
1313 // Allocate a register that is not explicitly blocked. | 1318 // Allocate a register that is not explicitly blocked. |
1314 static Register AllocateFreeRegister(bool* blocked_registers) { | 1319 static Register AllocateFreeRegister(bool* blocked_registers) { |
1315 for (intptr_t regno = 0; regno < kNumberOfCpuRegisters; regno++) { | 1320 for (intptr_t regno = 0; regno < kNumberOfCpuRegisters; regno++) { |
1316 if (!blocked_registers[regno]) { | 1321 if (!blocked_registers[regno]) { |
1317 blocked_registers[regno] = true; | 1322 blocked_registers[regno] = true; |
1318 return static_cast<Register>(regno); | 1323 return static_cast<Register>(regno); |
1319 } | 1324 } |
1320 } | 1325 } |
1321 UNREACHABLE(); | 1326 UNREACHABLE(); |
1322 return kNoRegister; | 1327 return kNoRegister; |
1323 } | 1328 } |
1324 | 1329 #endif |
1325 | |
1326 static uword RegMaskBit(Register reg) { | |
1327 return ((reg) != kNoRegister) ? (1 << (reg)) : 0; | |
1328 } | |
1329 | 1330 |
1330 | 1331 |
1331 void FlowGraphCompiler::AllocateRegistersLocally(Instruction* instr) { | 1332 void FlowGraphCompiler::AllocateRegistersLocally(Instruction* instr) { |
1332 ASSERT(!is_optimizing()); | 1333 ASSERT(!is_optimizing()); |
1333 | |
1334 instr->InitializeLocationSummary(zone(), | 1334 instr->InitializeLocationSummary(zone(), |
1335 false); // Not optimizing. | 1335 false); // Not optimizing. |
| 1336 |
| 1337 // No need to allocate registers based on LocationSummary on DBC as in |
| 1338 // unoptimized mode it's a stack based bytecode just like IR itself. |
| 1339 #if !defined(TARGET_ARCH_DBC) |
1336 LocationSummary* locs = instr->locs(); | 1340 LocationSummary* locs = instr->locs(); |
1337 | 1341 |
1338 bool blocked_registers[kNumberOfCpuRegisters]; | 1342 bool blocked_registers[kNumberOfCpuRegisters]; |
1339 | 1343 |
1340 // Block all registers globally reserved by the assembler, etc and mark | 1344 // Block all registers globally reserved by the assembler, etc and mark |
1341 // the rest as free. | 1345 // the rest as free. |
1342 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { | 1346 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { |
1343 blocked_registers[i] = (kDartAvailableCpuRegs & (1 << i)) == 0; | 1347 blocked_registers[i] = (kDartAvailableCpuRegs & (1 << i)) == 0; |
1344 } | 1348 } |
1345 | 1349 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1415 break; | 1419 break; |
1416 case Location::kSameAsFirstInput: | 1420 case Location::kSameAsFirstInput: |
1417 result_location = locs->in(0); | 1421 result_location = locs->in(0); |
1418 break; | 1422 break; |
1419 case Location::kRequiresFpuRegister: | 1423 case Location::kRequiresFpuRegister: |
1420 UNREACHABLE(); | 1424 UNREACHABLE(); |
1421 break; | 1425 break; |
1422 } | 1426 } |
1423 locs->set_out(0, result_location); | 1427 locs->set_out(0, result_location); |
1424 } | 1428 } |
| 1429 #endif // !defined(TARGET_ARCH_DBC) |
1425 } | 1430 } |
1426 | 1431 |
1427 | 1432 |
| 1433 static uword RegMaskBit(Register reg) { |
| 1434 return ((reg) != kNoRegister) ? (1 << (reg)) : 0; |
| 1435 } |
| 1436 |
| 1437 |
1428 ParallelMoveResolver::ParallelMoveResolver(FlowGraphCompiler* compiler) | 1438 ParallelMoveResolver::ParallelMoveResolver(FlowGraphCompiler* compiler) |
1429 : compiler_(compiler), moves_(32) {} | 1439 : compiler_(compiler), moves_(32) {} |
1430 | 1440 |
1431 | 1441 |
1432 void ParallelMoveResolver::EmitNativeCode(ParallelMoveInstr* parallel_move) { | 1442 void ParallelMoveResolver::EmitNativeCode(ParallelMoveInstr* parallel_move) { |
1433 ASSERT(moves_.is_empty()); | 1443 ASSERT(moves_.is_empty()); |
1434 // Build up a worklist of moves. | 1444 // Build up a worklist of moves. |
1435 BuildInitialMoveList(parallel_move); | 1445 BuildInitialMoveList(parallel_move); |
1436 | 1446 |
1437 for (int i = 0; i < moves_.length(); ++i) { | 1447 for (int i = 0; i < moves_.length(); ++i) { |
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1831 // |token_pos|. | 1841 // |token_pos|. |
1832 code_source_map_builder()->AddEntry(saved_code_size_, token_pos); | 1842 code_source_map_builder()->AddEntry(saved_code_size_, token_pos); |
1833 BeginCodeSourceRange(); | 1843 BeginCodeSourceRange(); |
1834 return true; | 1844 return true; |
1835 } | 1845 } |
1836 ); | 1846 ); |
1837 return false; | 1847 return false; |
1838 } | 1848 } |
1839 | 1849 |
1840 | 1850 |
| 1851 #if !defined(TARGET_ARCH_DBC) |
| 1852 // DBC emits calls very differently from other architectures due to its |
| 1853 // interpreted nature. |
1841 void FlowGraphCompiler::EmitPolymorphicInstanceCall( | 1854 void FlowGraphCompiler::EmitPolymorphicInstanceCall( |
1842 const ICData& ic_data, | 1855 const ICData& ic_data, |
1843 intptr_t argument_count, | 1856 intptr_t argument_count, |
1844 const Array& argument_names, | 1857 const Array& argument_names, |
1845 intptr_t deopt_id, | 1858 intptr_t deopt_id, |
1846 TokenPosition token_pos, | 1859 TokenPosition token_pos, |
1847 LocationSummary* locs, | 1860 LocationSummary* locs, |
1848 bool complete) { | 1861 bool complete) { |
1849 if (FLAG_polymorphic_with_deopt) { | 1862 if (FLAG_polymorphic_with_deopt) { |
1850 Label* deopt = AddDeoptStub(deopt_id, | 1863 Label* deopt = AddDeoptStub(deopt_id, |
(...skipping 23 matching lines...) Expand all Loading... |
1874 EmitTestAndCall(ic_data, argument_count, argument_names, | 1887 EmitTestAndCall(ic_data, argument_count, argument_names, |
1875 slow_path->entry_label(), // No cid match. | 1888 slow_path->entry_label(), // No cid match. |
1876 &ok, // Found cid. | 1889 &ok, // Found cid. |
1877 deopt_id, token_pos, locs, false); | 1890 deopt_id, token_pos, locs, false); |
1878 | 1891 |
1879 assembler()->Bind(slow_path->exit_label()); | 1892 assembler()->Bind(slow_path->exit_label()); |
1880 assembler()->Bind(&ok); | 1893 assembler()->Bind(&ok); |
1881 } | 1894 } |
1882 } | 1895 } |
1883 } | 1896 } |
| 1897 #endif |
1884 | 1898 |
1885 | 1899 #if defined(DEBUG) && !defined(TARGET_ARCH_DBC) |
1886 #if defined(DEBUG) | 1900 // TODO(vegorov) re-enable frame state tracking on DBC. It is |
| 1901 // currently disabled because it relies on LocationSummaries and |
| 1902 // we don't use them during unoptimized compilation on DBC. |
1887 void FlowGraphCompiler::FrameStateUpdateWith(Instruction* instr) { | 1903 void FlowGraphCompiler::FrameStateUpdateWith(Instruction* instr) { |
1888 ASSERT(!is_optimizing()); | 1904 ASSERT(!is_optimizing()); |
1889 | 1905 |
1890 switch (instr->tag()) { | 1906 switch (instr->tag()) { |
1891 case Instruction::kPushArgument: | 1907 case Instruction::kPushArgument: |
1892 case Instruction::kPushTemp: | 1908 case Instruction::kPushTemp: |
1893 // Do nothing. | 1909 // Do nothing. |
1894 break; | 1910 break; |
1895 | 1911 |
1896 case Instruction::kDropTemps: | 1912 case Instruction::kDropTemps: |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1947 } | 1963 } |
1948 } | 1964 } |
1949 return true; | 1965 return true; |
1950 } | 1966 } |
1951 | 1967 |
1952 | 1968 |
1953 void FlowGraphCompiler::FrameStateClear() { | 1969 void FlowGraphCompiler::FrameStateClear() { |
1954 ASSERT(!is_optimizing()); | 1970 ASSERT(!is_optimizing()); |
1955 frame_state_.TruncateTo(0); | 1971 frame_state_.TruncateTo(0); |
1956 } | 1972 } |
1957 #endif | 1973 #endif // defined(DEBUG) && !defined(TARGET_ARCH_DBC) |
1958 | 1974 |
1959 | 1975 |
1960 } // namespace dart | 1976 } // namespace dart |
OLD | NEW |