[wasm] First step to separate graph construction from graph compilation.

This is the first step to implement parallel compilation. The next steps
will be to split the pipeline to separate instruction selection from
code generation, and then to call all that from within a CancelableTask.

R=titzer@chromium.org

Review URL: https://codereview.chromium.org/1900713005

Cr-Commit-Position: refs/heads/master@{#35784}
This commit is contained in:
ahaas 2016-04-26 01:38:24 -07:00 committed by Commit bot
parent c9d9016d4b
commit a0f8869378
3 changed files with 81 additions and 43 deletions

View File

@ -73,7 +73,7 @@ namespace v8 {
namespace internal {
namespace compiler {
class PipelineData {
class PipelineData : public ZoneObject {
public:
// For main entry point.
PipelineData(ZonePool* zone_pool, CompilationInfo* info,
@ -174,12 +174,14 @@ class PipelineData {
register_allocation_zone_(register_allocation_zone_scope_.zone()),
register_allocation_data_(nullptr) {}
~PipelineData() {
void Destroy() {
DeleteRegisterAllocationZone();
DeleteInstructionZone();
DeleteGraphZone();
}
~PipelineData() { Destroy(); }
Isolate* isolate() const { return isolate_; }
CompilationInfo* info() const { return info_; }
ZonePool* zone_pool() const { return zone_pool_; }
@ -1380,6 +1382,14 @@ Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info,
return pipeline.ScheduleAndGenerateCode(call_descriptor);
}
void Pipeline::InitializeWasmCompilation(Zone* pipeline_zone,
ZonePool* zone_pool, Graph* graph) {
data_ = new (pipeline_zone) PipelineData(zone_pool, info(), graph, nullptr);
RunPrintAndVerify("Machine", true);
}
void Pipeline::FinalizeWasmCompilation() { data_->Destroy(); }
OptimizedCompileJob* Pipeline::NewCompilationJob(CompilationInfo* info) {
return new (info->zone()) PipelineCompilationJob(info);
}
@ -1402,6 +1412,7 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode(
CallDescriptor* call_descriptor) {
PipelineData* data = this->data_;
DCHECK_NOT_NULL(data);
DCHECK_NOT_NULL(data->graph());
if (data->schedule() == nullptr) Run<ComputeSchedulePhase>();

View File

@ -15,6 +15,7 @@ namespace internal {
class CompilationInfo;
class OptimizedCompileJob;
class RegisterConfiguration;
class Zone;
namespace compiler {
@ -24,6 +25,7 @@ class InstructionSequence;
class Linkage;
class PipelineData;
class Schedule;
class ZonePool;
class Pipeline {
public:
@ -61,6 +63,12 @@ class Pipeline {
// Returns a new compilation job for the given compilation info.
static OptimizedCompileJob* NewCompilationJob(CompilationInfo* info);
void InitializeWasmCompilation(Zone* pipeline_zone, ZonePool* zone_pool,
Graph* graph);
void FinalizeWasmCompilation();
Handle<Code> ScheduleAndGenerateCode(CallDescriptor* call_descriptor);
private:
// Helpers for executing pipeline phases.
template <typename Phase>
@ -72,7 +80,6 @@ class Pipeline {
void BeginPhaseKind(const char* phase_kind);
void RunPrintAndVerify(const char* phase, bool untyped = false);
Handle<Code> ScheduleAndGenerateCode(CallDescriptor* call_descriptor);
void AllocateRegisters(const RegisterConfiguration* config,
CallDescriptor* descriptor, bool run_verifier);

View File

@ -12,8 +12,8 @@
#include "src/compiler/access-builder.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/diamond.h"
#include "src/compiler/graph.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/graph.h"
#include "src/compiler/instruction-selector.h"
#include "src/compiler/int64-lowering.h"
#include "src/compiler/js-generic-lowering.h"
@ -24,6 +24,7 @@
#include "src/compiler/node-matchers.h"
#include "src/compiler/pipeline.h"
#include "src/compiler/source-position.h"
#include "src/compiler/zone-pool.h"
#include "src/code-factory.h"
#include "src/code-stubs.h"
@ -2846,35 +2847,24 @@ Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module,
return code;
}
// Helper function to compile a single function.
Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
wasm::ModuleEnv* module_env,
const wasm::WasmFunction& function) {
HistogramTimerScope wasm_compile_function_time_scope(
isolate->counters()->wasm_compile_function_time());
if (FLAG_trace_wasm_compiler) {
OFStream os(stdout);
os << "Compiling WASM function "
<< wasm::WasmFunctionName(&function, module_env) << std::endl;
os << std::endl;
}
double decode_ms = 0;
JSGraph* BuildGraphForWasmFunction(Zone* zone, wasm::ErrorThrower& thrower,
Isolate* isolate,
wasm::ModuleEnv*& module_env,
const wasm::WasmFunction& function,
double* decode_ms) {
base::ElapsedTimer decode_timer;
if (FLAG_trace_wasm_decode_time) {
decode_timer.Start();
}
// Create a TF graph during decoding.
Zone zone(isolate->allocator());
Graph graph(&zone);
CommonOperatorBuilder common(&zone);
MachineOperatorBuilder machine(
&zone, MachineType::PointerRepresentation(),
Graph* graph = new (zone) Graph(zone);
CommonOperatorBuilder* common = new (zone) CommonOperatorBuilder(zone);
MachineOperatorBuilder* machine = new (zone) MachineOperatorBuilder(
zone, MachineType::PointerRepresentation(),
InstructionSelector::SupportedMachineOperatorFlags());
JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
WasmGraphBuilder builder(&zone, &jsgraph, function.sig);
JSGraph* jsgraph =
new (zone) JSGraph(isolate, graph, common, nullptr, nullptr, machine);
WasmGraphBuilder builder(zone, jsgraph, function.sig);
wasm::FunctionBody body = {
module_env, function.sig, module_env->module->module_start,
module_env->module->module_start + function.code_start_offset,
@ -2882,8 +2872,8 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
wasm::TreeResult result =
wasm::BuildTFGraph(isolate->allocator(), &builder, body);
if (machine.Is32()) {
Int64Lowering r(&graph, &machine, &common, &zone, function.sig);
if (machine->Is32()) {
Int64Lowering r(graph, machine, common, zone, function.sig);
r.LowerGraph();
}
@ -2899,16 +2889,40 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
SNPrintF(buffer, "Compiling WASM function #%d:%.*s failed:",
function.func_index, name.length, name.name);
thrower.Failed(buffer.start(), result);
return Handle<Code>::null();
return nullptr;
}
int index = static_cast<int>(function.func_index);
if (index >= FLAG_trace_wasm_ast_start && index < FLAG_trace_wasm_ast_end) {
PrintAst(isolate->allocator(), body);
}
if (FLAG_trace_wasm_decode_time) {
decode_ms = decode_timer.Elapsed().InMillisecondsF();
*decode_ms = decode_timer.Elapsed().InMillisecondsF();
}
return jsgraph;
}
// Helper function to compile a single function.
Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
wasm::ModuleEnv* module_env,
const wasm::WasmFunction& function) {
HistogramTimerScope wasm_compile_function_time_scope(
isolate->counters()->wasm_compile_function_time());
if (FLAG_trace_wasm_compiler) {
OFStream os(stdout);
os << "Compiling WASM function "
<< wasm::WasmFunctionName(&function, module_env) << std::endl;
os << std::endl;
}
compiler::ZonePool zone_pool(isolate->allocator());
compiler::ZonePool::Scope graph_zone_scope(&zone_pool);
double decode_ms = 0;
JSGraph* jsgraph =
BuildGraphForWasmFunction(graph_zone_scope.zone(), thrower, isolate,
module_env, function, &decode_ms);
if (jsgraph == nullptr) {
return Handle<Code>::null();
}
base::ElapsedTimer compile_timer;
@ -2916,10 +2930,11 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
compile_timer.Start();
}
// Run the compiler pipeline to generate machine code.
CallDescriptor* descriptor =
wasm::ModuleEnv::GetWasmCallDescriptor(&zone, function.sig);
if (machine.Is32()) {
descriptor = module_env->GetI32WasmCallDescriptor(&zone, descriptor);
CallDescriptor* descriptor = wasm::ModuleEnv::GetWasmCallDescriptor(
jsgraph->graph()->zone(), function.sig);
if (jsgraph->machine()->Is32()) {
descriptor = module_env->GetI32WasmCallDescriptor(jsgraph->graph()->zone(),
descriptor);
}
Code::Flags flags = Code::ComputeFlags(Code::WASM_FUNCTION);
// add flags here if a meaningful name is helpful for debugging.
@ -2939,10 +2954,14 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
name.name);
func_name = buffer.start();
}
CompilationInfo info(func_name, isolate, &zone, flags);
Handle<Code> code =
Pipeline::GenerateCodeForTesting(&info, descriptor, &graph);
CompilationInfo info(func_name, isolate, jsgraph->graph()->zone(), flags);
compiler::ZonePool::Scope pipeline_zone_scope(&zone_pool);
Pipeline pipeline(&info);
pipeline.InitializeWasmCompilation(pipeline_zone_scope.zone(), &zone_pool,
jsgraph->graph());
Handle<Code> code = pipeline.ScheduleAndGenerateCode(descriptor);
pipeline.FinalizeWasmCompilation();
pipeline_zone_scope.Destroy();
if (debugging) {
buffer.Dispose();
}
@ -2959,11 +2978,12 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
"wasm-compile ok: %d bytes, %0.3f ms decode, %d nodes, %0.3f ms "
"compile\n",
static_cast<int>(function.code_end_offset - function.code_start_offset),
decode_ms, static_cast<int>(graph.NodeCount()), compile_ms);
decode_ms, static_cast<int>(jsgraph->graph()->NodeCount()), compile_ms);
}
// TODO(bradnelson): Improve histogram handling of size_t.
isolate->counters()->wasm_compile_function_peak_memory_bytes()->AddSample(
static_cast<int>(zone.allocation_size()));
static_cast<int>(jsgraph->graph()->zone()->allocation_size()));
graph_zone_scope.Destroy();
return code;
}