| 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 |