2016-06-17 13:19:58 +00:00
|
|
|
// Copyright 2016 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.
|
|
|
|
|
2017-09-21 02:04:27 +00:00
|
|
|
#ifndef V8_TEST_CCTEST_COMPILER_CODE_ASSEMBLER_TESTER_H_
|
|
|
|
#define V8_TEST_CCTEST_COMPILER_CODE_ASSEMBLER_TESTER_H_
|
|
|
|
|
2019-05-21 09:30:15 +00:00
|
|
|
#include "src/codegen/interface-descriptors.h"
|
2016-11-16 11:48:07 +00:00
|
|
|
#include "src/compiler/code-assembler.h"
|
2017-10-11 10:22:40 +00:00
|
|
|
#include "src/compiler/raw-machine-assembler.h"
|
2019-05-22 07:55:37 +00:00
|
|
|
#include "src/execution/isolate.h"
|
2019-05-22 12:44:24 +00:00
|
|
|
#include "src/handles/handles.h"
|
2016-06-17 13:19:58 +00:00
|
|
|
#include "test/cctest/compiler/function-tester.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
namespace compiler {
|
|
|
|
|
2016-11-16 11:48:07 +00:00
|
|
|
class CodeAssemblerTester {
|
2016-06-17 13:19:58 +00:00
|
|
|
public:
|
2016-11-16 11:48:07 +00:00
|
|
|
// Test generating code for a stub. Assumes VoidDescriptor call interface.
|
2018-04-05 16:25:41 +00:00
|
|
|
explicit CodeAssemblerTester(Isolate* isolate, const char* name = "test")
|
2020-07-23 10:06:02 +00:00
|
|
|
: zone_(isolate->allocator(), ZONE_NAME, kCompressGraphZone),
|
2016-11-16 11:48:07 +00:00
|
|
|
scope_(isolate),
|
2018-06-18 15:14:29 +00:00
|
|
|
state_(isolate, &zone_, VoidDescriptor{}, Code::STUB, name,
|
2018-04-30 12:13:54 +00:00
|
|
|
PoisoningMitigationLevel::kDontPoison) {}
|
2016-06-17 13:19:58 +00:00
|
|
|
|
|
|
|
// Test generating code for a JS function (e.g. builtins).
|
2016-11-16 11:48:07 +00:00
|
|
|
CodeAssemblerTester(Isolate* isolate, int parameter_count,
|
2018-04-05 16:25:41 +00:00
|
|
|
Code::Kind kind = Code::BUILTIN,
|
|
|
|
const char* name = "test")
|
2020-07-23 10:06:02 +00:00
|
|
|
: zone_(isolate->allocator(), ZONE_NAME, kCompressGraphZone),
|
2016-11-16 11:48:07 +00:00
|
|
|
scope_(isolate),
|
2018-04-05 16:25:41 +00:00
|
|
|
state_(isolate, &zone_, parameter_count, kind, name,
|
2018-04-30 12:13:54 +00:00
|
|
|
PoisoningMitigationLevel::kDontPoison) {}
|
2016-06-17 13:19:58 +00:00
|
|
|
|
2018-04-05 16:25:41 +00:00
|
|
|
CodeAssemblerTester(Isolate* isolate, Code::Kind kind,
|
|
|
|
const char* name = "test")
|
2020-07-23 10:06:02 +00:00
|
|
|
: zone_(isolate->allocator(), ZONE_NAME, kCompressGraphZone),
|
2016-11-16 11:48:07 +00:00
|
|
|
scope_(isolate),
|
2018-04-30 12:13:54 +00:00
|
|
|
state_(isolate, &zone_, 0, kind, name,
|
|
|
|
PoisoningMitigationLevel::kDontPoison) {}
|
2016-11-16 11:48:07 +00:00
|
|
|
|
2017-12-18 18:55:23 +00:00
|
|
|
CodeAssemblerTester(Isolate* isolate, CallDescriptor* call_descriptor,
|
|
|
|
const char* name = "test")
|
2020-07-23 10:06:02 +00:00
|
|
|
: zone_(isolate->allocator(), ZONE_NAME, kCompressGraphZone),
|
2017-10-11 10:22:40 +00:00
|
|
|
scope_(isolate),
|
2018-03-26 15:44:44 +00:00
|
|
|
state_(isolate, &zone_, call_descriptor, Code::STUB, name,
|
2018-12-07 14:53:22 +00:00
|
|
|
PoisoningMitigationLevel::kDontPoison, Builtins::kNoBuiltinId) {}
|
2017-10-11 10:22:40 +00:00
|
|
|
|
2016-11-16 11:48:07 +00:00
|
|
|
CodeAssemblerState* state() { return &state_; }
|
|
|
|
|
2017-10-11 10:22:40 +00:00
|
|
|
// Direct low-level access to the machine assembler, for testing only.
|
|
|
|
RawMachineAssembler* raw_assembler_for_testing() {
|
|
|
|
return state_.raw_assembler_.get();
|
|
|
|
}
|
|
|
|
|
2018-07-06 08:58:43 +00:00
|
|
|
Handle<Code> GenerateCode() {
|
2018-11-13 16:28:21 +00:00
|
|
|
return GenerateCode(AssemblerOptions::Default(scope_.isolate()));
|
2018-07-06 08:58:43 +00:00
|
|
|
}
|
2016-06-17 13:19:58 +00:00
|
|
|
|
2018-08-02 11:16:52 +00:00
|
|
|
Handle<Code> GenerateCode(const AssemblerOptions& options) {
|
2018-11-13 16:28:21 +00:00
|
|
|
if (state_.InsideBlock()) {
|
|
|
|
CodeAssembler(&state_).Unreachable();
|
|
|
|
}
|
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
|
|
|
return CodeAssembler::GenerateCode(&state_, options, nullptr);
|
2018-08-02 11:16:52 +00:00
|
|
|
}
|
|
|
|
|
2016-06-17 13:19:58 +00:00
|
|
|
Handle<Code> GenerateCodeCloseAndEscape() {
|
2016-12-13 13:55:03 +00:00
|
|
|
return scope_.CloseAndEscape(GenerateCode());
|
2016-06-17 13:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2016-11-16 11:48:07 +00:00
|
|
|
Zone zone_;
|
2016-06-17 13:19:58 +00:00
|
|
|
HandleScope scope_;
|
|
|
|
LocalContext context_;
|
2016-11-16 11:48:07 +00:00
|
|
|
CodeAssemblerState state_;
|
2016-06-17 13:19:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace compiler
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|
2017-09-21 02:04:27 +00:00
|
|
|
|
|
|
|
#endif // V8_TEST_CCTEST_COMPILER_CODE_ASSEMBLER_TESTER_H_
|