OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/pipeline.h" | 5 #include "src/compiler/pipeline.h" |
6 | 6 |
7 #include <fstream> // NOLINT(readability/streams) | 7 #include <fstream> // NOLINT(readability/streams) |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "src/base/adapters.h" | 10 #include "src/base/adapters.h" |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 } | 280 } |
281 | 281 |
282 void InitializeRegisterAllocationData(const RegisterConfiguration* config, | 282 void InitializeRegisterAllocationData(const RegisterConfiguration* config, |
283 CallDescriptor* descriptor) { | 283 CallDescriptor* descriptor) { |
284 DCHECK(register_allocation_data_ == nullptr); | 284 DCHECK(register_allocation_data_ == nullptr); |
285 register_allocation_data_ = new (register_allocation_zone()) | 285 register_allocation_data_ = new (register_allocation_zone()) |
286 RegisterAllocationData(config, register_allocation_zone(), frame(), | 286 RegisterAllocationData(config, register_allocation_zone(), frame(), |
287 sequence(), debug_name_.get()); | 287 sequence(), debug_name_.get()); |
288 } | 288 } |
289 | 289 |
| 290 void BeginPhaseKind(const char* phase_kind_name) { |
| 291 if (pipeline_statistics() != nullptr) { |
| 292 pipeline_statistics()->BeginPhaseKind(phase_kind_name); |
| 293 } |
| 294 } |
| 295 |
| 296 void EndPhaseKind() { |
| 297 if (pipeline_statistics() != nullptr) { |
| 298 pipeline_statistics()->EndPhaseKind(); |
| 299 } |
| 300 } |
| 301 |
290 private: | 302 private: |
291 Isolate* const isolate_; | 303 Isolate* const isolate_; |
292 CompilationInfo* const info_; | 304 CompilationInfo* const info_; |
293 base::SmartArrayPointer<char> debug_name_; | 305 base::SmartArrayPointer<char> debug_name_; |
294 Zone* outer_zone_ = nullptr; | 306 Zone* outer_zone_ = nullptr; |
295 ZonePool* const zone_pool_; | 307 ZonePool* const zone_pool_; |
296 PipelineStatistics* pipeline_statistics_ = nullptr; | 308 PipelineStatistics* pipeline_statistics_ = nullptr; |
297 bool compilation_failed_ = false; | 309 bool compilation_failed_ = false; |
298 Handle<Code> code_ = Handle<Code>::null(); | 310 Handle<Code> code_ = Handle<Code>::null(); |
299 | 311 |
(...skipping 977 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1277 static const char* phase_name() { return nullptr; } | 1289 static const char* phase_name() { return nullptr; } |
1278 | 1290 |
1279 void Run(PipelineData* data, Zone* temp_zone, const bool untyped, | 1291 void Run(PipelineData* data, Zone* temp_zone, const bool untyped, |
1280 bool values_only = false) { | 1292 bool values_only = false) { |
1281 Verifier::Run(data->graph(), !untyped ? Verifier::TYPED : Verifier::UNTYPED, | 1293 Verifier::Run(data->graph(), !untyped ? Verifier::TYPED : Verifier::UNTYPED, |
1282 values_only ? Verifier::kValuesOnly : Verifier::kAll); | 1294 values_only ? Verifier::kValuesOnly : Verifier::kAll); |
1283 } | 1295 } |
1284 }; | 1296 }; |
1285 | 1297 |
1286 | 1298 |
1287 void Pipeline::BeginPhaseKind(const char* phase_kind_name) { | |
1288 if (data_->pipeline_statistics() != nullptr) { | |
1289 data_->pipeline_statistics()->BeginPhaseKind(phase_kind_name); | |
1290 } | |
1291 } | |
1292 | |
1293 void Pipeline::EndPhaseKind() { | |
1294 if (data_->pipeline_statistics() != nullptr) { | |
1295 data_->pipeline_statistics()->EndPhaseKind(); | |
1296 } | |
1297 } | |
1298 | |
1299 void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) { | 1299 void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) { |
1300 if (FLAG_trace_turbo) { | 1300 if (FLAG_trace_turbo) { |
1301 Run<PrintGraphPhase>(phase); | 1301 Run<PrintGraphPhase>(phase); |
1302 } | 1302 } |
1303 if (FLAG_turbo_verify) { | 1303 if (FLAG_turbo_verify) { |
1304 Run<VerifyGraphPhase>(untyped); | 1304 Run<VerifyGraphPhase>(untyped); |
1305 } | 1305 } |
1306 } | 1306 } |
1307 | 1307 |
1308 bool Pipeline::CreateGraph() { | 1308 bool Pipeline::CreateGraph() { |
1309 PipelineData* data = this->data_; | 1309 PipelineData* data = this->data_; |
1310 | 1310 |
1311 BeginPhaseKind("graph creation"); | 1311 data->BeginPhaseKind("graph creation"); |
1312 | 1312 |
1313 if (FLAG_trace_turbo) { | 1313 if (FLAG_trace_turbo) { |
1314 OFStream os(stdout); | 1314 OFStream os(stdout); |
1315 os << "---------------------------------------------------\n" | 1315 os << "---------------------------------------------------\n" |
1316 << "Begin compiling method " << info()->GetDebugName().get() | 1316 << "Begin compiling method " << info()->GetDebugName().get() |
1317 << " using Turbofan" << std::endl; | 1317 << " using Turbofan" << std::endl; |
1318 TurboCfgFile tcf(isolate()); | 1318 TurboCfgFile tcf(isolate()); |
1319 tcf << AsC1VCompilation(info()); | 1319 tcf << AsC1VCompilation(info()); |
1320 } | 1320 } |
1321 | 1321 |
1322 data->source_positions()->AddDecorator(); | 1322 data->source_positions()->AddDecorator(); |
1323 | 1323 |
1324 if (FLAG_loop_assignment_analysis) { | 1324 if (FLAG_loop_assignment_analysis) { |
1325 Run<LoopAssignmentAnalysisPhase>(); | 1325 Run<LoopAssignmentAnalysisPhase>(); |
1326 } | 1326 } |
1327 | 1327 |
1328 Run<TypeHintAnalysisPhase>(); | 1328 Run<TypeHintAnalysisPhase>(); |
1329 | 1329 |
1330 Run<GraphBuilderPhase>(); | 1330 Run<GraphBuilderPhase>(); |
1331 if (data->compilation_failed()) { | 1331 if (data->compilation_failed()) { |
1332 EndPhaseKind(); | 1332 data->EndPhaseKind(); |
1333 return false; | 1333 return false; |
1334 } | 1334 } |
1335 RunPrintAndVerify("Initial untyped", true); | 1335 RunPrintAndVerify("Initial untyped", true); |
1336 | 1336 |
1337 // Perform OSR deconstruction. | 1337 // Perform OSR deconstruction. |
1338 if (info()->is_osr()) { | 1338 if (info()->is_osr()) { |
1339 Run<OsrDeconstructionPhase>(); | 1339 Run<OsrDeconstructionPhase>(); |
1340 RunPrintAndVerify("OSR deconstruction", true); | 1340 RunPrintAndVerify("OSR deconstruction", true); |
1341 } | 1341 } |
1342 | 1342 |
(...skipping 15 matching lines...) Expand all Loading... |
1358 // Type the graph and keep the Typer running on newly created nodes within | 1358 // Type the graph and keep the Typer running on newly created nodes within |
1359 // this scope; the Typer is automatically unlinked from the Graph once we | 1359 // this scope; the Typer is automatically unlinked from the Graph once we |
1360 // leave this scope below. | 1360 // leave this scope below. |
1361 Typer typer(isolate(), data->graph(), info()->is_deoptimization_enabled() | 1361 Typer typer(isolate(), data->graph(), info()->is_deoptimization_enabled() |
1362 ? Typer::kDeoptimizationEnabled | 1362 ? Typer::kDeoptimizationEnabled |
1363 : Typer::kNoFlags, | 1363 : Typer::kNoFlags, |
1364 info()->dependencies()); | 1364 info()->dependencies()); |
1365 Run<TyperPhase>(&typer); | 1365 Run<TyperPhase>(&typer); |
1366 RunPrintAndVerify("Typed"); | 1366 RunPrintAndVerify("Typed"); |
1367 | 1367 |
1368 BeginPhaseKind("lowering"); | 1368 data->BeginPhaseKind("lowering"); |
1369 | 1369 |
1370 // Lower JSOperators where we can determine types. | 1370 // Lower JSOperators where we can determine types. |
1371 Run<TypedLoweringPhase>(); | 1371 Run<TypedLoweringPhase>(); |
1372 RunPrintAndVerify("Lowered typed"); | 1372 RunPrintAndVerify("Lowered typed"); |
1373 | 1373 |
1374 if (FLAG_turbo_stress_loop_peeling) { | 1374 if (FLAG_turbo_stress_loop_peeling) { |
1375 Run<StressLoopPeelingPhase>(); | 1375 Run<StressLoopPeelingPhase>(); |
1376 RunPrintAndVerify("Loop peeled"); | 1376 RunPrintAndVerify("Loop peeled"); |
1377 } | 1377 } |
1378 | 1378 |
(...skipping 21 matching lines...) Expand all Loading... |
1400 // selection due to the way we handle truncations; if we'd want to look | 1400 // selection due to the way we handle truncations; if we'd want to look |
1401 // at types afterwards we'd essentially need to re-type (large portions | 1401 // at types afterwards we'd essentially need to re-type (large portions |
1402 // of) the graph. | 1402 // of) the graph. |
1403 // | 1403 // |
1404 // In order to catch bugs related to type access after this point we remove | 1404 // In order to catch bugs related to type access after this point we remove |
1405 // the types from the nodes at this point (currently only in Debug builds). | 1405 // the types from the nodes at this point (currently only in Debug builds). |
1406 Run<UntyperPhase>(); | 1406 Run<UntyperPhase>(); |
1407 RunPrintAndVerify("Untyped", true); | 1407 RunPrintAndVerify("Untyped", true); |
1408 #endif | 1408 #endif |
1409 | 1409 |
1410 EndPhaseKind(); | 1410 data->EndPhaseKind(); |
1411 | 1411 |
1412 return true; | 1412 return true; |
1413 } | 1413 } |
1414 | 1414 |
1415 bool Pipeline::OptimizeGraph(Linkage* linkage) { | 1415 bool Pipeline::OptimizeGraph(Linkage* linkage) { |
1416 PipelineData* data = this->data_; | 1416 PipelineData* data = this->data_; |
1417 | 1417 |
1418 BeginPhaseKind("block building"); | 1418 data->BeginPhaseKind("block building"); |
1419 | 1419 |
1420 Run<EffectControlLinearizationPhase>(); | 1420 Run<EffectControlLinearizationPhase>(); |
1421 RunPrintAndVerify("Effect and control linearized", true); | 1421 RunPrintAndVerify("Effect and control linearized", true); |
1422 | 1422 |
1423 Run<BranchEliminationPhase>(); | 1423 Run<BranchEliminationPhase>(); |
1424 RunPrintAndVerify("Branch conditions eliminated", true); | 1424 RunPrintAndVerify("Branch conditions eliminated", true); |
1425 | 1425 |
1426 // Optimize control flow. | 1426 // Optimize control flow. |
1427 if (FLAG_turbo_cf_optimization) { | 1427 if (FLAG_turbo_cf_optimization) { |
1428 Run<ControlFlowOptimizationPhase>(); | 1428 Run<ControlFlowOptimizationPhase>(); |
1429 RunPrintAndVerify("Control flow optimized", true); | 1429 RunPrintAndVerify("Control flow optimized", true); |
1430 } | 1430 } |
1431 | 1431 |
1432 // Lower changes that have been inserted before. | 1432 // Lower changes that have been inserted before. |
1433 Run<LateOptimizationPhase>(); | 1433 Run<LateOptimizationPhase>(); |
1434 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. | 1434 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
1435 RunPrintAndVerify("Late optimized", true); | 1435 RunPrintAndVerify("Late optimized", true); |
1436 | 1436 |
1437 Run<LateGraphTrimmingPhase>(); | 1437 Run<LateGraphTrimmingPhase>(); |
1438 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. | 1438 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
1439 RunPrintAndVerify("Late trimmed", true); | 1439 RunPrintAndVerify("Late trimmed", true); |
1440 | 1440 |
1441 data->source_positions()->RemoveDecorator(); | 1441 data->source_positions()->RemoveDecorator(); |
1442 | 1442 |
1443 return ScheduleAndSelectInstructions(linkage); | 1443 return ScheduleAndSelectInstructions(linkage); |
1444 } | 1444 } |
1445 | 1445 |
1446 Handle<Code> Pipeline::GenerateCode() { | |
1447 PipelineData* data = this->data_; | |
1448 | |
1449 Linkage linkage(Linkage::ComputeIncoming(data->instruction_zone(), info())); | |
1450 | |
1451 if (!CreateGraph()) return Handle<Code>::null(); | |
1452 if (!OptimizeGraph(&linkage)) return Handle<Code>::null(); | |
1453 return GenerateCode(&linkage); | |
1454 } | |
1455 | |
1456 Handle<Code> Pipeline::GenerateCodeForCodeStub(Isolate* isolate, | 1446 Handle<Code> Pipeline::GenerateCodeForCodeStub(Isolate* isolate, |
1457 CallDescriptor* call_descriptor, | 1447 CallDescriptor* call_descriptor, |
1458 Graph* graph, Schedule* schedule, | 1448 Graph* graph, Schedule* schedule, |
1459 Code::Flags flags, | 1449 Code::Flags flags, |
1460 const char* debug_name) { | 1450 const char* debug_name) { |
1461 CompilationInfo info(CStrVector(debug_name), isolate, graph->zone(), flags); | 1451 CompilationInfo info(CStrVector(debug_name), isolate, graph->zone(), flags); |
1462 | 1452 |
1463 // Construct a pipeline for scheduling and code generation. | 1453 // Construct a pipeline for scheduling and code generation. |
1464 ZonePool zone_pool(isolate->allocator()); | 1454 ZonePool zone_pool(isolate->allocator()); |
1465 PipelineData data(&zone_pool, &info, graph, schedule); | 1455 PipelineData data(&zone_pool, &info, graph, schedule); |
(...skipping 21 matching lines...) Expand all Loading... |
1487 return pipeline.ScheduleAndGenerateCode(call_descriptor); | 1477 return pipeline.ScheduleAndGenerateCode(call_descriptor); |
1488 } | 1478 } |
1489 | 1479 |
1490 // static | 1480 // static |
1491 Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info) { | 1481 Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info) { |
1492 ZonePool zone_pool(info->isolate()->allocator()); | 1482 ZonePool zone_pool(info->isolate()->allocator()); |
1493 base::SmartPointer<PipelineStatistics> pipeline_statistics( | 1483 base::SmartPointer<PipelineStatistics> pipeline_statistics( |
1494 CreatePipelineStatistics(info, &zone_pool)); | 1484 CreatePipelineStatistics(info, &zone_pool)); |
1495 PipelineData data(&zone_pool, info, pipeline_statistics.get()); | 1485 PipelineData data(&zone_pool, info, pipeline_statistics.get()); |
1496 Pipeline pipeline(&data); | 1486 Pipeline pipeline(&data); |
1497 return pipeline.GenerateCode(); | 1487 |
| 1488 Linkage linkage(Linkage::ComputeIncoming(data.instruction_zone(), info)); |
| 1489 |
| 1490 if (!pipeline.CreateGraph()) return Handle<Code>::null(); |
| 1491 if (!pipeline.OptimizeGraph(&linkage)) return Handle<Code>::null(); |
| 1492 return pipeline.GenerateCode(&linkage); |
1498 } | 1493 } |
1499 | 1494 |
1500 // static | 1495 // static |
1501 Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info, | 1496 Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info, |
1502 Graph* graph, | 1497 Graph* graph, |
1503 Schedule* schedule) { | 1498 Schedule* schedule) { |
1504 CallDescriptor* call_descriptor = | 1499 CallDescriptor* call_descriptor = |
1505 Linkage::ComputeIncoming(info->zone(), info); | 1500 Linkage::ComputeIncoming(info->zone(), info); |
1506 return GenerateCodeForTesting(info, call_descriptor, graph, schedule); | 1501 return GenerateCodeForTesting(info, call_descriptor, graph, schedule); |
1507 } | 1502 } |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1591 | 1586 |
1592 if (FLAG_trace_turbo) { | 1587 if (FLAG_trace_turbo) { |
1593 std::ostringstream source_position_output; | 1588 std::ostringstream source_position_output; |
1594 // Output source position information before the graph is deleted. | 1589 // Output source position information before the graph is deleted. |
1595 data_->source_positions()->Print(source_position_output); | 1590 data_->source_positions()->Print(source_position_output); |
1596 data_->set_source_position_output(source_position_output.str()); | 1591 data_->set_source_position_output(source_position_output.str()); |
1597 } | 1592 } |
1598 | 1593 |
1599 data->DeleteGraphZone(); | 1594 data->DeleteGraphZone(); |
1600 | 1595 |
1601 BeginPhaseKind("register allocation"); | 1596 data->BeginPhaseKind("register allocation"); |
1602 | 1597 |
1603 bool run_verifier = FLAG_turbo_verify_allocation; | 1598 bool run_verifier = FLAG_turbo_verify_allocation; |
1604 | 1599 |
1605 // Allocate registers. | 1600 // Allocate registers. |
1606 AllocateRegisters( | 1601 AllocateRegisters( |
1607 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN), | 1602 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN), |
1608 call_descriptor, run_verifier); | 1603 call_descriptor, run_verifier); |
1609 Run<FrameElisionPhase>(); | 1604 Run<FrameElisionPhase>(); |
1610 if (data->compilation_failed()) { | 1605 if (data->compilation_failed()) { |
1611 info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); | 1606 info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); |
1612 EndPhaseKind(); | 1607 data->EndPhaseKind(); |
1613 return false; | 1608 return false; |
1614 } | 1609 } |
1615 | 1610 |
1616 // TODO(mtrofin): move this off to the register allocator. | 1611 // TODO(mtrofin): move this off to the register allocator. |
1617 bool generate_frame_at_start = | 1612 bool generate_frame_at_start = |
1618 data_->sequence()->instruction_blocks().front()->must_construct_frame(); | 1613 data_->sequence()->instruction_blocks().front()->must_construct_frame(); |
1619 // Optimimize jumps. | 1614 // Optimimize jumps. |
1620 if (FLAG_turbo_jt) { | 1615 if (FLAG_turbo_jt) { |
1621 Run<JumpThreadingPhase>(generate_frame_at_start); | 1616 Run<JumpThreadingPhase>(generate_frame_at_start); |
1622 } | 1617 } |
1623 | 1618 |
1624 EndPhaseKind(); | 1619 data->EndPhaseKind(); |
1625 | 1620 |
1626 return true; | 1621 return true; |
1627 } | 1622 } |
1628 | 1623 |
1629 Handle<Code> Pipeline::GenerateCode(Linkage* linkage) { | 1624 Handle<Code> Pipeline::GenerateCode(Linkage* linkage) { |
1630 PipelineData* data = this->data_; | 1625 PipelineData* data = this->data_; |
1631 | 1626 |
1632 BeginPhaseKind("code generation"); | 1627 data->BeginPhaseKind("code generation"); |
1633 | 1628 |
1634 // Generate final machine code. | 1629 // Generate final machine code. |
1635 Run<GenerateCodePhase>(linkage); | 1630 Run<GenerateCodePhase>(linkage); |
1636 | 1631 |
1637 Handle<Code> code = data->code(); | 1632 Handle<Code> code = data->code(); |
1638 if (data->profiler_data()) { | 1633 if (data->profiler_data()) { |
1639 #if ENABLE_DISASSEMBLER | 1634 #if ENABLE_DISASSEMBLER |
1640 std::ostringstream os; | 1635 std::ostringstream os; |
1641 code->Disassemble(nullptr, os); | 1636 code->Disassemble(nullptr, os); |
1642 data->profiler_data()->SetCode(&os); | 1637 data->profiler_data()->SetCode(&os); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1775 data->DeleteRegisterAllocationZone(); | 1770 data->DeleteRegisterAllocationZone(); |
1776 } | 1771 } |
1777 | 1772 |
1778 CompilationInfo* Pipeline::info() const { return data_->info(); } | 1773 CompilationInfo* Pipeline::info() const { return data_->info(); } |
1779 | 1774 |
1780 Isolate* Pipeline::isolate() const { return info()->isolate(); } | 1775 Isolate* Pipeline::isolate() const { return info()->isolate(); } |
1781 | 1776 |
1782 } // namespace compiler | 1777 } // namespace compiler |
1783 } // namespace internal | 1778 } // namespace internal |
1784 } // namespace v8 | 1779 } // namespace v8 |
OLD | NEW |