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