OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/wasm-compiler.h" | 5 #include "src/compiler/wasm-compiler.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/assembler-inl.h" | 9 #include "src/assembler-inl.h" |
10 #include "src/base/platform/elapsed-timer.h" | 10 #include "src/base/platform/elapsed-timer.h" |
(...skipping 3969 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3980 if (FLAG_trace_wasm_decode_time) { | 3980 if (FLAG_trace_wasm_decode_time) { |
3981 decode_timer.Start(); | 3981 decode_timer.Start(); |
3982 } | 3982 } |
3983 // Create a TF graph during decoding. | 3983 // Create a TF graph during decoding. |
3984 | 3984 |
3985 Graph* graph = jsgraph_->graph(); | 3985 Graph* graph = jsgraph_->graph(); |
3986 CommonOperatorBuilder* common = jsgraph_->common(); | 3986 CommonOperatorBuilder* common = jsgraph_->common(); |
3987 MachineOperatorBuilder* machine = jsgraph_->machine(); | 3987 MachineOperatorBuilder* machine = jsgraph_->machine(); |
3988 SourcePositionTable* source_position_table = | 3988 SourcePositionTable* source_position_table = |
3989 new (jsgraph_->zone()) SourcePositionTable(graph); | 3989 new (jsgraph_->zone()) SourcePositionTable(graph); |
3990 WasmGraphBuilder builder(&module_env_->module_env, jsgraph_->zone(), jsgraph_, | 3990 WasmGraphBuilder builder(module_env_, jsgraph_->zone(), jsgraph_, |
3991 function_->sig, source_position_table); | 3991 func_body_.sig, source_position_table); |
3992 const byte* module_start = module_env_->wire_bytes.start(); | |
3993 wasm::FunctionBody body = {function_->sig, module_start, | |
3994 module_start + function_->code_start_offset, | |
3995 module_start + function_->code_end_offset}; | |
3996 graph_construction_result_ = | 3992 graph_construction_result_ = |
3997 wasm::BuildTFGraph(isolate_->allocator(), &builder, body); | 3993 wasm::BuildTFGraph(isolate_->allocator(), &builder, func_body_); |
3998 | 3994 |
3999 if (graph_construction_result_.failed()) { | 3995 if (graph_construction_result_.failed()) { |
4000 if (FLAG_trace_wasm_compiler) { | 3996 if (FLAG_trace_wasm_compiler) { |
4001 OFStream os(stdout); | 3997 OFStream os(stdout); |
4002 os << "Compilation failed: " << graph_construction_result_ << std::endl; | 3998 os << "Compilation failed: " << graph_construction_result_ << std::endl; |
4003 } | 3999 } |
4004 return nullptr; | 4000 return nullptr; |
4005 } | 4001 } |
4006 | 4002 |
4007 if (machine->Is32()) { | 4003 if (machine->Is32()) { |
4008 Int64Lowering(graph, machine, common, jsgraph_->zone(), function_->sig) | 4004 Int64Lowering(graph, machine, common, jsgraph_->zone(), func_body_.sig) |
4009 .LowerGraph(); | 4005 .LowerGraph(); |
4010 } | 4006 } |
4011 | 4007 |
4012 if (builder.has_simd() && !CpuFeatures::SupportsSimd128()) { | 4008 if (builder.has_simd() && !CpuFeatures::SupportsSimd128()) { |
4013 SimdScalarLowering(graph, machine, common, jsgraph_->zone(), function_->sig) | 4009 SimdScalarLowering(graph, machine, common, jsgraph_->zone(), func_body_.sig) |
4014 .LowerGraph(); | 4010 .LowerGraph(); |
4015 } | 4011 } |
4016 | 4012 |
4017 int index = static_cast<int>(function_->func_index); | 4013 if (func_index_ >= FLAG_trace_wasm_ast_start && |
4018 | 4014 func_index_ < FLAG_trace_wasm_ast_end) { |
4019 if (index >= FLAG_trace_wasm_ast_start && index < FLAG_trace_wasm_ast_end) { | 4015 PrintRawWasmCode(isolate_->allocator(), func_body_, module_env_->module); |
4020 OFStream os(stdout); | |
4021 PrintRawWasmCode(isolate_->allocator(), body, | |
4022 module_env_->module_env.module); | |
4023 } | 4016 } |
4024 if (index >= FLAG_trace_wasm_text_start && index < FLAG_trace_wasm_text_end) { | 4017 // TODO(clemens): Remove the trace_wasm_text_start flag. |
4025 OFStream os(stdout); | 4018 // if (func_index_ >= FLAG_trace_wasm_text_start && func_index_ < |
4026 PrintWasmText(module_env_->module_env.module, module_env_->wire_bytes, | 4019 // FLAG_trace_wasm_text_end) { |
4027 function_->func_index, os, nullptr); | 4020 // OFStream os(stdout); |
4028 } | 4021 // PrintWasmText(module_env_.module, module_env_->wire_bytes, |
4022 // function_->func_index, os, nullptr); | |
4023 //} | |
4029 if (FLAG_trace_wasm_decode_time) { | 4024 if (FLAG_trace_wasm_decode_time) { |
4030 *decode_ms = decode_timer.Elapsed().InMillisecondsF(); | 4025 *decode_ms = decode_timer.Elapsed().InMillisecondsF(); |
4031 } | 4026 } |
4032 return source_position_table; | 4027 return source_position_table; |
4033 } | 4028 } |
4034 | 4029 |
4035 char* WasmCompilationUnit::GetTaggedFunctionName( | 4030 WasmCompilationUnit::WasmCompilationUnit(Isolate* isolate, |
4036 const wasm::WasmFunction* function) { | 4031 wasm::ModuleBytesEnv* module_env, |
4037 snprintf(function_name_, sizeof(function_name_), "wasm#%d", | 4032 const wasm::WasmFunction* function) |
4038 function->func_index); | 4033 : WasmCompilationUnit( |
4039 return function_name_; | 4034 isolate, &module_env->module_env, |
4040 } | 4035 wasm::FunctionBody{ |
4036 function->sig, module_env->wire_bytes.start(), | |
4037 module_env->wire_bytes.start() + function->code_start_offset, | |
4038 module_env->wire_bytes.start() + function->code_end_offset}, | |
4039 module_env->wire_bytes.GetNameOrNull(function), | |
4040 function->func_index) {} | |
4041 | 4041 |
4042 WasmCompilationUnit::WasmCompilationUnit(wasm::ErrorThrower* thrower, | 4042 WasmCompilationUnit::WasmCompilationUnit(Isolate* isolate, |
4043 Isolate* isolate, | 4043 wasm::ModuleEnv* module_env, |
4044 wasm::ModuleBytesEnv* module_env, | 4044 wasm::FunctionBody body, |
4045 const wasm::WasmFunction* function, | 4045 wasm::WasmName name, int index) |
4046 uint32_t index) | 4046 : isolate_(isolate), |
4047 : thrower_(thrower), | |
4048 isolate_(isolate), | |
4049 module_env_(module_env), | 4047 module_env_(module_env), |
4050 function_(&module_env->module_env.module->functions[index]), | 4048 func_body_(body), |
4049 func_name_(name), | |
4051 graph_zone_(new Zone(isolate->allocator(), ZONE_NAME)), | 4050 graph_zone_(new Zone(isolate->allocator(), ZONE_NAME)), |
4052 jsgraph_(new (graph_zone()) JSGraph( | 4051 jsgraph_(new (graph_zone()) JSGraph( |
4053 isolate, new (graph_zone()) Graph(graph_zone()), | 4052 isolate, new (graph_zone()) Graph(graph_zone()), |
4054 new (graph_zone()) CommonOperatorBuilder(graph_zone()), nullptr, | 4053 new (graph_zone()) CommonOperatorBuilder(graph_zone()), nullptr, |
4055 nullptr, new (graph_zone()) MachineOperatorBuilder( | 4054 nullptr, |
4056 graph_zone(), MachineType::PointerRepresentation(), | 4055 new (graph_zone()) MachineOperatorBuilder( |
4057 InstructionSelector::SupportedMachineOperatorFlags(), | 4056 graph_zone(), MachineType::PointerRepresentation(), |
4058 InstructionSelector::AlignmentRequirements()))), | 4057 InstructionSelector::SupportedMachineOperatorFlags(), |
4058 InstructionSelector::AlignmentRequirements()))), | |
4059 compilation_zone_(isolate->allocator(), ZONE_NAME), | 4059 compilation_zone_(isolate->allocator(), ZONE_NAME), |
4060 info_(function->name_length != 0 | 4060 info_(name, isolate, &compilation_zone_, |
4061 ? module_env->wire_bytes.GetNameOrNull(function) | |
4062 : CStrVector(GetTaggedFunctionName(function)), | |
4063 isolate, &compilation_zone_, | |
4064 Code::ComputeFlags(Code::WASM_FUNCTION)), | 4061 Code::ComputeFlags(Code::WASM_FUNCTION)), |
4065 job_(), | 4062 func_index_(index), |
4066 index_(index), | |
4067 ok_(true), | |
4068 protected_instructions_(&compilation_zone_) { | 4063 protected_instructions_(&compilation_zone_) { |
4069 // Create and cache this node in the main thread. | 4064 // Create and cache this node in the main thread. |
4070 jsgraph_->CEntryStubConstant(1); | 4065 jsgraph_->CEntryStubConstant(1); |
4071 } | 4066 } |
4072 | 4067 |
4073 void WasmCompilationUnit::ExecuteCompilation() { | 4068 void WasmCompilationUnit::ExecuteCompilation() { |
4074 // TODO(ahaas): The counters are not thread-safe at the moment. | 4069 // TODO(ahaas): The counters are not thread-safe at the moment. |
4075 // HistogramTimerScope wasm_compile_function_time_scope( | 4070 // HistogramTimerScope wasm_compile_function_time_scope( |
4076 // isolate_->counters()->wasm_compile_function_time()); | 4071 // isolate_->counters()->wasm_compile_function_time()); |
4077 if (FLAG_trace_wasm_compiler) { | 4072 if (FLAG_trace_wasm_compiler) { |
4078 OFStream os(stdout); | 4073 if (func_name_.start() == nullptr) { |
ahaas
2017/02/28 18:33:35
Shouldn't this be a !=?
Clemens Hammacher
2017/03/02 11:52:13
Indeed. Fixed.
| |
4079 os << "Compiling WASM function " | 4074 PrintF("Compiling WASM function '%.*s'\n\n", func_name_.length(), |
4080 << wasm::WasmFunctionName( | 4075 func_name_.start()); |
4081 function_, module_env_->wire_bytes.GetNameOrNull(function_)) | 4076 } else { |
4082 << std::endl; | 4077 PrintF("Compiling WASM function <unnamed>\n\n"); |
4083 os << std::endl; | 4078 } |
4084 } | 4079 } |
4085 | 4080 |
4086 double decode_ms = 0; | 4081 double decode_ms = 0; |
4087 size_t node_count = 0; | 4082 size_t node_count = 0; |
4088 | 4083 |
4089 std::unique_ptr<Zone> graph_zone(graph_zone_.release()); | 4084 std::unique_ptr<Zone> graph_zone(graph_zone_.release()); |
4090 SourcePositionTable* source_positions = BuildGraphForWasmFunction(&decode_ms); | 4085 SourcePositionTable* source_positions = BuildGraphForWasmFunction(&decode_ms); |
4091 | 4086 |
4092 if (graph_construction_result_.failed()) { | 4087 if (graph_construction_result_.failed()) { |
4093 ok_ = false; | 4088 ok_ = false; |
4094 return; | 4089 return; |
4095 } | 4090 } |
4096 | 4091 |
4097 base::ElapsedTimer pipeline_timer; | 4092 base::ElapsedTimer pipeline_timer; |
4098 if (FLAG_trace_wasm_decode_time) { | 4093 if (FLAG_trace_wasm_decode_time) { |
4099 node_count = jsgraph_->graph()->NodeCount(); | 4094 node_count = jsgraph_->graph()->NodeCount(); |
4100 pipeline_timer.Start(); | 4095 pipeline_timer.Start(); |
4101 } | 4096 } |
4102 | 4097 |
4103 // Run the compiler pipeline to generate machine code. | 4098 // Run the compiler pipeline to generate machine code. |
4104 CallDescriptor* descriptor = wasm::ModuleEnv::GetWasmCallDescriptor( | 4099 CallDescriptor* descriptor = wasm::ModuleEnv::GetWasmCallDescriptor( |
4105 &compilation_zone_, function_->sig); | 4100 &compilation_zone_, func_body_.sig); |
4106 if (jsgraph_->machine()->Is32()) { | 4101 if (jsgraph_->machine()->Is32()) { |
4107 descriptor = module_env_->module_env.GetI32WasmCallDescriptor( | 4102 descriptor = |
4108 &compilation_zone_, descriptor); | 4103 module_env_->GetI32WasmCallDescriptor(&compilation_zone_, descriptor); |
4109 } | 4104 } |
4110 job_.reset(Pipeline::NewWasmCompilationJob( | 4105 job_.reset(Pipeline::NewWasmCompilationJob( |
4111 &info_, jsgraph_, descriptor, source_positions, &protected_instructions_, | 4106 &info_, jsgraph_, descriptor, source_positions, &protected_instructions_, |
4112 module_env_->module_env.module->origin != wasm::kWasmOrigin)); | 4107 module_env_->module->origin != wasm::kWasmOrigin)); |
4113 ok_ = job_->ExecuteJob() == CompilationJob::SUCCEEDED; | 4108 ok_ = job_->ExecuteJob() == CompilationJob::SUCCEEDED; |
4114 // TODO(bradnelson): Improve histogram handling of size_t. | 4109 // TODO(bradnelson): Improve histogram handling of size_t. |
4115 // TODO(ahaas): The counters are not thread-safe at the moment. | 4110 // TODO(ahaas): The counters are not thread-safe at the moment. |
4116 // isolate_->counters()->wasm_compile_function_peak_memory_bytes() | 4111 // isolate_->counters()->wasm_compile_function_peak_memory_bytes() |
4117 // ->AddSample( | 4112 // ->AddSample( |
4118 // static_cast<int>(jsgraph->graph()->zone()->allocation_size())); | 4113 // static_cast<int>(jsgraph->graph()->zone()->allocation_size())); |
4119 | 4114 |
4120 if (FLAG_trace_wasm_decode_time) { | 4115 if (FLAG_trace_wasm_decode_time) { |
4121 double pipeline_ms = pipeline_timer.Elapsed().InMillisecondsF(); | 4116 double pipeline_ms = pipeline_timer.Elapsed().InMillisecondsF(); |
4122 PrintF( | 4117 PrintF( |
4123 "wasm-compilation phase 1 ok: %u bytes, %0.3f ms decode, %zu nodes, " | 4118 "wasm-compilation phase 1 ok: %u bytes, %0.3f ms decode, %zu nodes, " |
4124 "%0.3f ms pipeline\n", | 4119 "%0.3f ms pipeline\n", |
4125 function_->code_end_offset - function_->code_start_offset, decode_ms, | 4120 static_cast<unsigned>(func_body_.end - func_body_.start), decode_ms, |
4126 node_count, pipeline_ms); | 4121 node_count, pipeline_ms); |
4127 } | 4122 } |
4128 } | 4123 } |
4129 | 4124 |
4130 Handle<Code> WasmCompilationUnit::FinishCompilation() { | 4125 Handle<Code> WasmCompilationUnit::FinishCompilation( |
4126 wasm::ErrorThrower* thrower) { | |
4131 if (!ok_) { | 4127 if (!ok_) { |
4132 if (graph_construction_result_.failed()) { | 4128 if (graph_construction_result_.failed()) { |
4133 // Add the function as another context for the exception | 4129 // Add the function as another context for the exception |
4134 ScopedVector<char> buffer(128); | 4130 ScopedVector<char> buffer(128); |
4135 wasm::WasmName name = module_env_->wire_bytes.GetName(function_); | 4131 if (func_name_.start() == nullptr) { |
4136 SNPrintF(buffer, "Compiling WASM function #%d:%.*s failed:", | 4132 SNPrintF(buffer, |
4137 function_->func_index, name.length(), name.start()); | 4133 "Compiling WASM function #%d:%.*s failed:", func_index_, |
4138 thrower_->CompileFailed(buffer.start(), graph_construction_result_); | 4134 func_name_.length(), func_name_.start()); |
4135 } else { | |
4136 SNPrintF(buffer, "Compiling WASM function #%d failed:", func_index_); | |
4137 } | |
4138 thrower->CompileFailed(buffer.start(), graph_construction_result_); | |
4139 } | 4139 } |
4140 | 4140 |
4141 return Handle<Code>::null(); | 4141 return Handle<Code>::null(); |
4142 } | 4142 } |
4143 base::ElapsedTimer codegen_timer; | 4143 base::ElapsedTimer codegen_timer; |
4144 if (FLAG_trace_wasm_decode_time) { | 4144 if (FLAG_trace_wasm_decode_time) { |
4145 codegen_timer.Start(); | 4145 codegen_timer.Start(); |
4146 } | 4146 } |
4147 if (job_->FinalizeJob() != CompilationJob::SUCCEEDED) { | 4147 if (job_->FinalizeJob() != CompilationJob::SUCCEEDED) { |
4148 return Handle<Code>::null(); | 4148 return Handle<Code>::null(); |
4149 } | 4149 } |
4150 Handle<Code> code = info_.code(); | 4150 Handle<Code> code = info_.code(); |
4151 DCHECK(!code.is_null()); | 4151 DCHECK(!code.is_null()); |
4152 | 4152 |
4153 if (isolate_->logger()->is_logging_code_events() || | 4153 if (isolate_->logger()->is_logging_code_events() || |
4154 isolate_->is_profiling()) { | 4154 isolate_->is_profiling()) { |
4155 RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate_, code, | 4155 RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate_, code, |
4156 "WASM_function", function_->func_index, | 4156 "WASM_function", func_index_, |
4157 wasm::WasmName("module"), | 4157 wasm::WasmName("module"), func_name_); |
4158 module_env_->wire_bytes.GetName(function_)); | |
4159 } | 4158 } |
4160 | 4159 |
4161 if (FLAG_trace_wasm_decode_time) { | 4160 if (FLAG_trace_wasm_decode_time) { |
4162 double codegen_ms = codegen_timer.Elapsed().InMillisecondsF(); | 4161 double codegen_ms = codegen_timer.Elapsed().InMillisecondsF(); |
4163 PrintF("wasm-code-generation ok: %u bytes, %0.3f ms code generation\n", | 4162 PrintF("wasm-code-generation ok: %u bytes, %0.3f ms code generation\n", |
4164 function_->code_end_offset - function_->code_start_offset, | 4163 static_cast<unsigned>(func_body_.end - func_body_.start), |
4165 codegen_ms); | 4164 codegen_ms); |
4166 } | 4165 } |
4167 | 4166 |
4168 return code; | 4167 return code; |
4169 } | 4168 } |
4170 | 4169 |
4170 // static | |
4171 Handle<Code> WasmCompilationUnit::CompileWasmFunction( | |
4172 wasm::ErrorThrower* thrower, Isolate* isolate, | |
4173 wasm::ModuleBytesEnv* module_env, const wasm::WasmFunction* function) { | |
4174 WasmCompilationUnit unit(isolate, module_env, function); | |
4175 unit.ExecuteCompilation(); | |
4176 return unit.FinishCompilation(thrower); | |
4177 } | |
4178 | |
4171 } // namespace compiler | 4179 } // namespace compiler |
4172 } // namespace internal | 4180 } // namespace internal |
4173 } // namespace v8 | 4181 } // namespace v8 |
OLD | NEW |