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/platform/elapsed-timer.h" | 10 #include "src/base/platform/elapsed-timer.h" |
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 | 582 |
583 | 583 |
584 struct ComputeSchedulePhase { | 584 struct ComputeSchedulePhase { |
585 static const char* phase_name() { return "scheduling"; } | 585 static const char* phase_name() { return "scheduling"; } |
586 | 586 |
587 void Run(PipelineData* data, Zone* temp_zone) { | 587 void Run(PipelineData* data, Zone* temp_zone) { |
588 Schedule* schedule = Scheduler::ComputeSchedule( | 588 Schedule* schedule = Scheduler::ComputeSchedule( |
589 temp_zone, data->graph(), data->info()->is_splitting_enabled() | 589 temp_zone, data->graph(), data->info()->is_splitting_enabled() |
590 ? Scheduler::kSplitNodes | 590 ? Scheduler::kSplitNodes |
591 : Scheduler::kNoFlags); | 591 : Scheduler::kNoFlags); |
592 TraceSchedule(schedule); | |
593 if (FLAG_turbo_verify) ScheduleVerifier::Run(schedule); | 592 if (FLAG_turbo_verify) ScheduleVerifier::Run(schedule); |
594 data->set_schedule(schedule); | 593 data->set_schedule(schedule); |
595 } | 594 } |
596 }; | 595 }; |
597 | 596 |
598 | 597 |
599 struct InstructionSelectionPhase { | 598 struct InstructionSelectionPhase { |
600 static const char* phase_name() { return "select instructions"; } | 599 static const char* phase_name() { return "select instructions"; } |
601 | 600 |
602 void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) { | 601 void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) { |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
942 | 941 |
943 // Lower any remaining generic JSOperators. | 942 // Lower any remaining generic JSOperators. |
944 Run<GenericLoweringPhase>(); | 943 Run<GenericLoweringPhase>(); |
945 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. | 944 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
946 RunPrintAndVerify("Lowered generic", true); | 945 RunPrintAndVerify("Lowered generic", true); |
947 | 946 |
948 BeginPhaseKind("block building"); | 947 BeginPhaseKind("block building"); |
949 | 948 |
950 data.source_positions()->RemoveDecorator(); | 949 data.source_positions()->RemoveDecorator(); |
951 | 950 |
952 // Compute a schedule. | 951 return ScheduleAndGenerateCode( |
953 Run<ComputeSchedulePhase>(); | 952 Linkage::ComputeIncoming(data.instruction_zone(), info())); |
954 | |
955 { | |
956 // Generate optimized code. | |
957 Linkage linkage(Linkage::ComputeIncoming(data.instruction_zone(), info())); | |
958 GenerateCode(&linkage); | |
959 } | |
960 Handle<Code> code = data.code(); | |
961 info()->SetCode(code); | |
962 | |
963 // Print optimized code. | |
964 v8::internal::CodeGenerator::PrintCode(code, info()); | |
965 | |
966 if (FLAG_trace_turbo) { | |
967 FILE* json_file = OpenVisualizerLogFile(info(), NULL, "json", "a+"); | |
968 if (json_file != nullptr) { | |
969 OFStream json_of(json_file); | |
970 json_of | |
971 << "{\"name\":\"disassembly\",\"type\":\"disassembly\",\"data\":\""; | |
972 #if ENABLE_DISASSEMBLER | |
973 std::stringstream disassembly_stream; | |
974 code->Disassemble(NULL, disassembly_stream); | |
975 std::string disassembly_string(disassembly_stream.str()); | |
976 for (const auto& c : disassembly_string) { | |
977 json_of << AsEscapedUC16ForJSON(c); | |
978 } | |
979 #endif // ENABLE_DISASSEMBLER | |
980 json_of << "\"}\n]}"; | |
981 fclose(json_file); | |
982 } | |
983 OFStream os(stdout); | |
984 os << "---------------------------------------------------\n" | |
985 << "Finished compiling method " << GetDebugName(info()).get() | |
986 << " using Turbofan" << std::endl; | |
987 } | |
988 | |
989 return code; | |
990 } | 953 } |
991 | 954 |
992 | 955 |
993 Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info, | 956 Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info, |
994 Graph* graph, | 957 Graph* graph, |
995 Schedule* schedule) { | 958 Schedule* schedule) { |
996 CallDescriptor* call_descriptor = | 959 CallDescriptor* call_descriptor = |
997 Linkage::ComputeIncoming(info->zone(), info); | 960 Linkage::ComputeIncoming(info->zone(), info); |
998 return GenerateCodeForTesting(info, call_descriptor, graph, schedule); | 961 return GenerateCodeForTesting(info, call_descriptor, graph, schedule); |
999 } | 962 } |
1000 | 963 |
1001 | 964 |
1002 Handle<Code> Pipeline::GenerateCodeForTesting(Isolate* isolate, | 965 Handle<Code> Pipeline::GenerateCodeForTesting(Isolate* isolate, |
1003 CallDescriptor* call_descriptor, | 966 CallDescriptor* call_descriptor, |
1004 Graph* graph, | 967 Graph* graph, |
1005 Schedule* schedule) { | 968 Schedule* schedule) { |
1006 FakeStubForTesting stub(isolate); | 969 FakeStubForTesting stub(isolate); |
1007 CompilationInfo info(&stub, isolate, graph->zone()); | 970 CompilationInfo info(&stub, isolate, graph->zone()); |
1008 return GenerateCodeForTesting(&info, call_descriptor, graph, schedule); | 971 return GenerateCodeForTesting(&info, call_descriptor, graph, schedule); |
1009 } | 972 } |
1010 | 973 |
1011 | 974 |
1012 Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info, | 975 Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info, |
1013 CallDescriptor* call_descriptor, | 976 CallDescriptor* call_descriptor, |
1014 Graph* graph, | 977 Graph* graph, |
1015 Schedule* schedule) { | 978 Schedule* schedule) { |
1016 CHECK(SupportedBackend()); | 979 // Construct a pipeline for scheduling and code generation. |
1017 ZonePool zone_pool; | 980 ZonePool zone_pool; |
1018 Pipeline pipeline(info); | 981 Pipeline pipeline(info); |
1019 PipelineData data(&zone_pool, info); | 982 PipelineData data(&zone_pool, info); |
1020 pipeline.data_ = &data; | 983 pipeline.data_ = &data; |
1021 data.InitializeTorTesting(graph, schedule); | 984 data.InitializeTorTesting(graph, schedule); |
1022 if (schedule == NULL) { | 985 if (data.schedule() == nullptr) { |
1023 // TODO(rossberg): Should this really be untyped? | 986 // TODO(rossberg): Should this really be untyped? |
1024 pipeline.RunPrintAndVerify("Machine", true); | 987 pipeline.RunPrintAndVerify("Machine", true); |
1025 pipeline.Run<ComputeSchedulePhase>(); | |
1026 } else { | |
1027 TraceSchedule(schedule); | |
1028 } | 988 } |
1029 | 989 |
1030 Linkage linkage(call_descriptor); | 990 return pipeline.ScheduleAndGenerateCode(call_descriptor); |
1031 pipeline.GenerateCode(&linkage); | |
1032 Handle<Code> code = data.code(); | |
1033 | |
1034 #if ENABLE_DISASSEMBLER | |
1035 if (!code.is_null() && FLAG_print_opt_code) { | |
1036 CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer()); | |
1037 OFStream os(tracing_scope.file()); | |
1038 code->Disassemble("test code", os); | |
1039 } | |
1040 #endif | |
1041 return code; | |
1042 } | 991 } |
1043 | 992 |
1044 | 993 |
1045 bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config, | 994 bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config, |
1046 InstructionSequence* sequence, | 995 InstructionSequence* sequence, |
1047 bool run_verifier) { | 996 bool run_verifier) { |
1048 FakeStubForTesting stub(sequence->isolate()); | 997 FakeStubForTesting stub(sequence->isolate()); |
1049 CompilationInfo info(&stub, sequence->isolate(), sequence->zone()); | 998 CompilationInfo info(&stub, sequence->isolate(), sequence->zone()); |
1050 ZonePool zone_pool; | 999 ZonePool zone_pool; |
1051 PipelineData data(&zone_pool, &info); | 1000 PipelineData data(&zone_pool, &info); |
1052 data.InitializeTorTesting(sequence); | 1001 data.InitializeTorTesting(sequence); |
1053 Pipeline pipeline(&info); | 1002 Pipeline pipeline(&info); |
1054 pipeline.data_ = &data; | 1003 pipeline.data_ = &data; |
1055 pipeline.AllocateRegisters(config, run_verifier); | 1004 pipeline.AllocateRegisters(config, run_verifier); |
1056 return !data.compilation_failed(); | 1005 return !data.compilation_failed(); |
1057 } | 1006 } |
1058 | 1007 |
1059 | 1008 |
1060 void Pipeline::GenerateCode(Linkage* linkage) { | 1009 Handle<Code> Pipeline::ScheduleAndGenerateCode( |
| 1010 CallDescriptor* call_descriptor) { |
1061 PipelineData* data = this->data_; | 1011 PipelineData* data = this->data_; |
1062 | 1012 |
1063 DCHECK_NOT_NULL(linkage); | |
1064 DCHECK_NOT_NULL(data->graph()); | 1013 DCHECK_NOT_NULL(data->graph()); |
1065 DCHECK_NOT_NULL(data->schedule()); | |
1066 CHECK(SupportedBackend()); | 1014 CHECK(SupportedBackend()); |
1067 | 1015 |
| 1016 if (data->schedule() == nullptr) Run<ComputeSchedulePhase>(); |
| 1017 TraceSchedule(data->schedule()); |
| 1018 |
1068 BasicBlockProfiler::Data* profiler_data = NULL; | 1019 BasicBlockProfiler::Data* profiler_data = NULL; |
1069 if (FLAG_turbo_profiling) { | 1020 if (FLAG_turbo_profiling) { |
1070 profiler_data = BasicBlockInstrumentor::Instrument(info(), data->graph(), | 1021 profiler_data = BasicBlockInstrumentor::Instrument(info(), data->graph(), |
1071 data->schedule()); | 1022 data->schedule()); |
1072 } | 1023 } |
1073 | 1024 |
1074 data->InitializeInstructionSequence(); | 1025 data->InitializeInstructionSequence(); |
1075 | 1026 |
1076 // Select and schedule instructions covering the scheduled graph. | 1027 // Select and schedule instructions covering the scheduled graph. |
1077 Run<InstructionSelectionPhase>(linkage); | 1028 Linkage linkage(call_descriptor); |
| 1029 Run<InstructionSelectionPhase>(&linkage); |
1078 | 1030 |
1079 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { | 1031 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { |
1080 TurboCfgFile tcf(isolate()); | 1032 TurboCfgFile tcf(isolate()); |
1081 tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(), | 1033 tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(), |
1082 data->sequence()); | 1034 data->sequence()); |
1083 } | 1035 } |
1084 | 1036 |
1085 data->DeleteGraphZone(); | 1037 data->DeleteGraphZone(); |
1086 | 1038 |
1087 BeginPhaseKind("register allocation"); | 1039 BeginPhaseKind("register allocation"); |
1088 | 1040 |
1089 bool run_verifier = FLAG_turbo_verify_allocation; | 1041 bool run_verifier = FLAG_turbo_verify_allocation; |
1090 // Allocate registers. | 1042 // Allocate registers. |
1091 AllocateRegisters(RegisterConfiguration::ArchDefault(), run_verifier); | 1043 AllocateRegisters(RegisterConfiguration::ArchDefault(), run_verifier); |
1092 if (data->compilation_failed()) { | 1044 if (data->compilation_failed()) { |
1093 info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); | 1045 info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); |
1094 return; | 1046 return Handle<Code>(); |
1095 } | 1047 } |
1096 | 1048 |
1097 BeginPhaseKind("code generation"); | 1049 BeginPhaseKind("code generation"); |
1098 | 1050 |
1099 // Optimimize jumps. | 1051 // Optimimize jumps. |
1100 if (FLAG_turbo_jt) { | 1052 if (FLAG_turbo_jt) { |
1101 Run<JumpThreadingPhase>(); | 1053 Run<JumpThreadingPhase>(); |
1102 } | 1054 } |
1103 | 1055 |
1104 // Generate final machine code. | 1056 // Generate final machine code. |
1105 Run<GenerateCodePhase>(linkage); | 1057 Run<GenerateCodePhase>(&linkage); |
1106 | 1058 |
| 1059 Handle<Code> code = data->code(); |
1107 if (profiler_data != NULL) { | 1060 if (profiler_data != NULL) { |
1108 #if ENABLE_DISASSEMBLER | 1061 #if ENABLE_DISASSEMBLER |
1109 std::ostringstream os; | 1062 std::ostringstream os; |
1110 data->code()->Disassemble(NULL, os); | 1063 code->Disassemble(NULL, os); |
1111 profiler_data->SetCode(&os); | 1064 profiler_data->SetCode(&os); |
1112 #endif | 1065 #endif |
1113 } | 1066 } |
| 1067 |
| 1068 info()->SetCode(code); |
| 1069 v8::internal::CodeGenerator::PrintCode(code, info()); |
| 1070 |
| 1071 if (FLAG_trace_turbo) { |
| 1072 FILE* json_file = OpenVisualizerLogFile(info(), NULL, "json", "a+"); |
| 1073 if (json_file != nullptr) { |
| 1074 OFStream json_of(json_file); |
| 1075 json_of |
| 1076 << "{\"name\":\"disassembly\",\"type\":\"disassembly\",\"data\":\""; |
| 1077 #if ENABLE_DISASSEMBLER |
| 1078 std::stringstream disassembly_stream; |
| 1079 code->Disassemble(NULL, disassembly_stream); |
| 1080 std::string disassembly_string(disassembly_stream.str()); |
| 1081 for (const auto& c : disassembly_string) { |
| 1082 json_of << AsEscapedUC16ForJSON(c); |
| 1083 } |
| 1084 #endif // ENABLE_DISASSEMBLER |
| 1085 json_of << "\"}\n]}"; |
| 1086 fclose(json_file); |
| 1087 } |
| 1088 OFStream os(stdout); |
| 1089 os << "---------------------------------------------------\n" |
| 1090 << "Finished compiling method " << GetDebugName(info()).get() |
| 1091 << " using Turbofan" << std::endl; |
| 1092 } |
| 1093 |
| 1094 return code; |
1114 } | 1095 } |
1115 | 1096 |
1116 | 1097 |
1117 void Pipeline::AllocateRegisters(const RegisterConfiguration* config, | 1098 void Pipeline::AllocateRegisters(const RegisterConfiguration* config, |
1118 bool run_verifier) { | 1099 bool run_verifier) { |
1119 PipelineData* data = this->data_; | 1100 PipelineData* data = this->data_; |
1120 | 1101 |
1121 // Don't track usage for this zone in compiler stats. | 1102 // Don't track usage for this zone in compiler stats. |
1122 SmartPointer<Zone> verifier_zone; | 1103 SmartPointer<Zone> verifier_zone; |
1123 RegisterAllocatorVerifier* verifier = nullptr; | 1104 RegisterAllocatorVerifier* verifier = nullptr; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1178 | 1159 |
1179 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { | 1160 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { |
1180 TurboCfgFile tcf(data->isolate()); | 1161 TurboCfgFile tcf(data->isolate()); |
1181 tcf << AsC1VAllocator("CodeGen", data->register_allocator()); | 1162 tcf << AsC1VAllocator("CodeGen", data->register_allocator()); |
1182 } | 1163 } |
1183 } | 1164 } |
1184 | 1165 |
1185 } // namespace compiler | 1166 } // namespace compiler |
1186 } // namespace internal | 1167 } // namespace internal |
1187 } // namespace v8 | 1168 } // namespace v8 |
OLD | NEW |