v8/src/compiler/pipeline.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

117 lines
4.4 KiB
C
Raw Normal View History

// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_COMPILER_PIPELINE_H_
#define V8_COMPILER_PIPELINE_H_
#include <memory>
// Clients of this interface shouldn't depend on lots of compiler internals.
// Do not include anything from src/compiler here!
#include "src/common/globals.h"
#include "src/objects/code.h"
namespace v8 {
namespace internal {
struct AssemblerOptions;
class OptimizedCompilationInfo;
class TurbofanCompilationJob;
Profile-guided optimization of builtins Design doc: https://docs.google.com/document/d/1szInbXZfaErWW70d30hJsOLL0Es-l5_g8d2rXm1ZBqI/edit?usp=sharing V8 can already collect data about how many times each basic block in the builtins is run. This change enables using that data for profile-guided optimization. New comments in BUILD.gn describe how to use this feature. A few implementation details worth mentioning, which aren't covered in the design doc: - BasicBlockProfilerData currently contains an array of RPO numbers. However, this array is always just [0, 1, 2, 3, ...], so this change removes that array. A new DCHECK in BasicBlockInstrumentor::Instrument ensures that the removal is valid. - RPO numbers, while useful for printing data that matches with the stringified schedule, are not useful for matching profiling data with blocks that haven't been scheduled yet. This change adds a new array of block IDs in BasicBlockProfilerData, so that block counters can be used for PGO. - Basic block counters need to be written to a file so that they can be provided to a subsequent run of mksnapshot, but the design doc doesn't specify the transfer format or what file is used. In this change, I propose using the existing v8.log file for that purpose. Block count records look like this: block,TestLessThanHandler,37,29405 This line indicates that block ID 37 in TestLessThanHandler was run 29405 times. If multiple lines refer to the same block, the reader adds them all together. I like this format because it's easy to use: - V8 already has robust logic for creating the log file, naming it to avoid conflicts in multi-process situations, etc. - Line order doesn't matter, and interleaved writes from various logging sources are fine, given that V8 writes each line atomically. - Combining multiple sources of profiling data is as simple as concatenating their v8.log files together. - It is a good idea to avoid making any changes based on profiling data if the function being compiled doesn't match the one that was profiled, since it is common to use profiling data downloaded from a central lab which is updated only periodically. To check whether a function matches, I propose using a hash of the Graph state right before scheduling. This might be stricter than necessary, as some changes to the function might be small enough that the profile data is still relevant, but I'd rather err on the side of not making incorrect changes. This hash is also written to the v8.log file, in a line that looks like this: builtin_hash,LdaZeroHandler,3387822046 Bug: v8:10470 Change-Id: I429e5ce5efa94e01e7489deb3996012cf860cf13 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2220765 Commit-Queue: Seth Brenith <seth.brenith@microsoft.com> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/master@{#69008}
2020-07-16 16:37:08 +00:00
class ProfileDataFromFile;
class RegisterConfiguration;
namespace wasm {
class AssemblerBufferCache;
struct CompilationEnv;
struct FunctionBody;
struct WasmCompilationResult;
struct WasmModule;
class WireBytesStorage;
} // namespace wasm
namespace compiler {
class CallDescriptor;
class Graph;
class InstructionSequence;
class JSGraph;
class JSHeapBroker;
class MachineGraph;
class NodeOriginTable;
class Schedule;
class SourcePositionTable;
[wasm][turbofan] Implement loop unrolling for wasm Design doc: https://docs.google.com/document/d/1AsUCqslMUB6fLdnGq0ZoPk2kn50jIJAWAL77lKXXP5g/ Currently, wasm loop unrolling is disabled by default. We intend to further investigate its compilation time cost and running time benefits before enabling it. Additional changes: - Introduce LoopFinder::FindUnnestedLoopFromHeader() as a lightweight loop analysis. - Move EliminateLoopExit into LoopPeeling and expose it. - Introduce loop_info_ field into WasmGraphBuildingInterface, fill it up in Loop(). - Break after encountering the first loop in BuildNestedLoopExits. - Introduce struct WasmLoopInfo. A WasmLoopInfo vector is instantiated in ExecuteTurbofanWasmCompilation, passed to BuildGraphForWasmFunction to be filled up by WasmGraphBuildingInterface, and then passed to GenerateCodeForWasmFunction to be used in WasmLoopUnrollingPhase. - Introduce WasmLoopUnrollingPhase and insert it into the wasm compilation pipeline. - Fix an issue where exception values were not wrapped in WasmGraphBuilderInterface. - Update --wasm-loop-unrolling flag description. Bug: v8:11298 Change-Id: I4b57cf2ea8520931f60769f843ffd57b3ca6399b Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2697349 Commit-Queue: Manos Koukoutos <manoskouk@chromium.org> Reviewed-by: Clemens Backes <clemensb@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org> Cr-Commit-Position: refs/heads/master@{#73009}
2021-02-24 13:49:09 +00:00
struct WasmLoopInfo;
class Pipeline : public AllStatic {
public:
// Returns a new compilation job for the given JavaScript function.
static V8_EXPORT_PRIVATE std::unique_ptr<TurbofanCompilationJob>
NewCompilationJob(Isolate* isolate, Handle<JSFunction> function,
CodeKind code_kind, bool has_script,
BytecodeOffset osr_offset = BytecodeOffset::None(),
JavaScriptFrame* osr_frame = nullptr);
// Run the pipeline for the WebAssembly compilation info.
static void GenerateCodeForWasmFunction(
OptimizedCompilationInfo* info, wasm::CompilationEnv* env,
const wasm::WireBytesStorage* wire_bytes_storage, MachineGraph* mcgraph,
CallDescriptor* call_descriptor, SourcePositionTable* source_positions,
NodeOriginTable* node_origins, wasm::FunctionBody function_body,
const wasm::WasmModule* module, int function_index,
std::vector<compiler::WasmLoopInfo>* loop_infos,
wasm::AssemblerBufferCache* buffer_cache);
// Run the pipeline on a machine graph and generate code.
static wasm::WasmCompilationResult GenerateCodeForWasmNativeStub(
CallDescriptor* call_descriptor, MachineGraph* mcgraph, CodeKind kind,
const char* debug_name, const AssemblerOptions& assembler_options,
SourcePositionTable* source_positions = nullptr);
// Returns a new compilation job for a wasm heap stub.
static std::unique_ptr<TurbofanCompilationJob> NewWasmHeapStubCompilationJob(
Isolate* isolate, CallDescriptor* call_descriptor,
std::unique_ptr<Zone> zone, Graph* graph, CodeKind kind,
std::unique_ptr<char[]> debug_name, const AssemblerOptions& options,
SourcePositionTable* source_positions = nullptr);
// Run the pipeline on a machine graph and generate code.
static MaybeHandle<Code> GenerateCodeForCodeStub(
Isolate* isolate, CallDescriptor* call_descriptor, Graph* graph,
JSGraph* jsgraph, SourcePositionTable* source_positions, CodeKind kind,
const char* debug_name, Builtin builtin, const AssemblerOptions& options,
Profile-guided optimization of builtins Design doc: https://docs.google.com/document/d/1szInbXZfaErWW70d30hJsOLL0Es-l5_g8d2rXm1ZBqI/edit?usp=sharing V8 can already collect data about how many times each basic block in the builtins is run. This change enables using that data for profile-guided optimization. New comments in BUILD.gn describe how to use this feature. A few implementation details worth mentioning, which aren't covered in the design doc: - BasicBlockProfilerData currently contains an array of RPO numbers. However, this array is always just [0, 1, 2, 3, ...], so this change removes that array. A new DCHECK in BasicBlockInstrumentor::Instrument ensures that the removal is valid. - RPO numbers, while useful for printing data that matches with the stringified schedule, are not useful for matching profiling data with blocks that haven't been scheduled yet. This change adds a new array of block IDs in BasicBlockProfilerData, so that block counters can be used for PGO. - Basic block counters need to be written to a file so that they can be provided to a subsequent run of mksnapshot, but the design doc doesn't specify the transfer format or what file is used. In this change, I propose using the existing v8.log file for that purpose. Block count records look like this: block,TestLessThanHandler,37,29405 This line indicates that block ID 37 in TestLessThanHandler was run 29405 times. If multiple lines refer to the same block, the reader adds them all together. I like this format because it's easy to use: - V8 already has robust logic for creating the log file, naming it to avoid conflicts in multi-process situations, etc. - Line order doesn't matter, and interleaved writes from various logging sources are fine, given that V8 writes each line atomically. - Combining multiple sources of profiling data is as simple as concatenating their v8.log files together. - It is a good idea to avoid making any changes based on profiling data if the function being compiled doesn't match the one that was profiled, since it is common to use profiling data downloaded from a central lab which is updated only periodically. To check whether a function matches, I propose using a hash of the Graph state right before scheduling. This might be stricter than necessary, as some changes to the function might be small enough that the profile data is still relevant, but I'd rather err on the side of not making incorrect changes. This hash is also written to the v8.log file, in a line that looks like this: builtin_hash,LdaZeroHandler,3387822046 Bug: v8:10470 Change-Id: I429e5ce5efa94e01e7489deb3996012cf860cf13 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2220765 Commit-Queue: Seth Brenith <seth.brenith@microsoft.com> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/master@{#69008}
2020-07-16 16:37:08 +00:00
const ProfileDataFromFile* profile_data);
// ---------------------------------------------------------------------------
// The following methods are for testing purposes only. Avoid production use.
// ---------------------------------------------------------------------------
// Run the pipeline on JavaScript bytecode and generate code. If requested,
// hands out the heap broker on success, transferring its ownership to the
// caller.
V8_EXPORT_PRIVATE static MaybeHandle<Code> GenerateCodeForTesting(
OptimizedCompilationInfo* info, Isolate* isolate,
std::unique_ptr<JSHeapBroker>* out_broker = nullptr);
// Run the pipeline on a machine graph and generate code. If {schedule} is
// {nullptr}, then compute a new schedule for code generation.
V8_EXPORT_PRIVATE static MaybeHandle<Code> GenerateCodeForTesting(
OptimizedCompilationInfo* info, Isolate* isolate,
CallDescriptor* call_descriptor, Graph* graph,
const AssemblerOptions& options, Schedule* schedule = nullptr);
// Run just the register allocator phases.
V8_EXPORT_PRIVATE static void AllocateRegistersForTesting(
const RegisterConfiguration* config, InstructionSequence* sequence,
bool use_fast_register_allocator, bool run_verifier);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Pipeline);
};
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_PIPELINE_H_