Commit b5829880 authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[turbofan] Move bytecode analysis to the serializer

When --concurrent-inlining is on, run bytecode analysis for all relevant
functions at serialization time, and store the results in the broker.

Change bytecode analysis such that running it for OSR produces information
that subsumes the non-OSR case. This lets us avoid doing and storing two
analyses for the top-level function in case we do OSR and the function
gets inlined into itself.

Bug: v8:7790
Change-Id: I7d5df0b2652e6e5c758c85578e51b4f8d041b0d9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1690959
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarMichael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62711}
parent 4ee7697c
......@@ -79,17 +79,21 @@ ResumeJumpTarget ResumeJumpTarget::AtLoopHeader(int loop_header_offset,
}
BytecodeAnalysis::BytecodeAnalysis(Handle<BytecodeArray> bytecode_array,
Zone* zone, bool do_liveness_analysis)
Zone* zone, BailoutId osr_bailout_id,
bool analyze_liveness)
: bytecode_array_(bytecode_array),
do_liveness_analysis_(do_liveness_analysis),
zone_(zone),
osr_bailout_id_(osr_bailout_id),
analyze_liveness_(analyze_liveness),
loop_stack_(zone),
loop_end_index_queue_(zone),
resume_jump_targets_(zone),
end_to_header_(zone),
header_to_info_(zone),
osr_entry_point_(-1),
liveness_map_(bytecode_array->length(), zone) {}
liveness_map_(bytecode_array->length(), zone) {
Analyze();
}
namespace {
......@@ -315,15 +319,13 @@ void UpdateAssignments(
} // namespace
void BytecodeAnalysis::Analyze(BailoutId osr_bailout_id) {
void BytecodeAnalysis::Analyze() {
loop_stack_.push({-1, nullptr});
BytecodeLivenessState* next_bytecode_in_liveness = nullptr;
bool is_osr = !osr_bailout_id.IsNone();
int osr_loop_end_offset = is_osr ? osr_bailout_id.ToInt() : -1;
int generator_switch_index = -1;
int osr_loop_end_offset = osr_bailout_id_.ToInt();
DCHECK_EQ(osr_loop_end_offset < 0, osr_bailout_id_.IsNone());
interpreter::BytecodeArrayRandomIterator iterator(bytecode_array(), zone());
for (iterator.GoToEnd(); iterator.IsValid(); --iterator) {
......@@ -345,14 +347,14 @@ void BytecodeAnalysis::Analyze(BailoutId osr_bailout_id) {
if (current_offset == osr_loop_end_offset) {
osr_entry_point_ = loop_header;
} else if (current_offset < osr_loop_end_offset) {
// Check we've found the osr_entry_point if we've gone past the
// Assert that we've found the osr_entry_point if we've gone past the
// osr_loop_end_offset. Note, we are iterating the bytecode in reverse,
// so the less than in the check is correct.
DCHECK_NE(-1, osr_entry_point_);
// so the less-than in the above condition is correct.
DCHECK_LE(0, osr_entry_point_);
}
// Save the index so that we can do another pass later.
if (do_liveness_analysis_) {
if (analyze_liveness_) {
loop_end_index_queue_.push_back(iterator.current_index());
}
} else if (loop_stack_.size() > 1) {
......@@ -365,8 +367,8 @@ void BytecodeAnalysis::Analyze(BailoutId osr_bailout_id) {
// information we currently have.
UpdateAssignments(bytecode, current_loop_info->assignments(), iterator);
// Update suspend counts for this loop, though only if not OSR.
if (!is_osr && bytecode == Bytecode::kSuspendGenerator) {
// Update suspend counts for this loop.
if (bytecode == Bytecode::kSuspendGenerator) {
int suspend_id = iterator.GetUnsignedImmediateOperand(3);
int resume_offset = current_offset + iterator.current_bytecode_size();
current_loop_info->AddResumeTarget(
......@@ -420,7 +422,7 @@ void BytecodeAnalysis::Analyze(BailoutId osr_bailout_id) {
}
}
}
} else if (!is_osr && bytecode == Bytecode::kSuspendGenerator) {
} else if (bytecode == Bytecode::kSuspendGenerator) {
// If we're not in a loop, we still need to look for suspends.
// TODO(leszeks): It would be nice to de-duplicate this with the in-loop
// case
......@@ -430,7 +432,7 @@ void BytecodeAnalysis::Analyze(BailoutId osr_bailout_id) {
ResumeJumpTarget::Leaf(suspend_id, resume_offset));
}
if (do_liveness_analysis_) {
if (analyze_liveness_) {
BytecodeLiveness& liveness = liveness_map_.InitializeLiveness(
current_offset, bytecode_array()->register_count(), zone());
UpdateLiveness(bytecode, liveness, &next_bytecode_in_liveness, iterator,
......@@ -443,7 +445,7 @@ void BytecodeAnalysis::Analyze(BailoutId osr_bailout_id) {
DCHECK(ResumeJumpTargetsAreValid());
if (!do_liveness_analysis_) return;
if (!analyze_liveness_) return;
// At this point, every bytecode has a valid in and out liveness, except for
// propagating liveness across back edges (i.e. JumpLoop). Subsequent liveness
......@@ -547,7 +549,7 @@ void BytecodeAnalysis::Analyze(BailoutId osr_bailout_id) {
}
}
DCHECK(do_liveness_analysis_);
DCHECK(analyze_liveness_);
if (FLAG_trace_environment_liveness) {
StdoutStream of;
PrintLivenessTo(of);
......@@ -619,14 +621,14 @@ const LoopInfo& BytecodeAnalysis::GetLoopInfoFor(int header_offset) const {
const BytecodeLivenessState* BytecodeAnalysis::GetInLivenessFor(
int offset) const {
if (!do_liveness_analysis_) return nullptr;
if (!analyze_liveness_) return nullptr;
return liveness_map_.GetInLiveness(offset);
}
const BytecodeLivenessState* BytecodeAnalysis::GetOutLivenessFor(
int offset) const {
if (!do_liveness_analysis_) return nullptr;
if (!analyze_liveness_) return nullptr;
return liveness_map_.GetOutLiveness(offset);
}
......@@ -671,9 +673,8 @@ bool BytecodeAnalysis::ResumeJumpTargetsAreValid() {
}
// If the iterator is invalid, we've reached the end without finding the
// generator switch. Similarly, if we are OSR-ing, we're not resuming, so we
// need no jump targets. So, ensure there are no jump targets and exit.
if (!iterator.IsValid() || HasOsrEntryPoint()) {
// generator switch. So, ensure there are no jump targets and exit.
if (!iterator.IsValid()) {
// Check top-level.
if (!resume_jump_targets().empty()) {
PrintF(stderr,
......
......@@ -92,18 +92,14 @@ struct V8_EXPORT_PRIVATE LoopInfo {
ZoneVector<ResumeJumpTarget> resume_jump_targets_;
};
class V8_EXPORT_PRIVATE BytecodeAnalysis {
// Analyze the bytecodes to find the loop ranges, loop nesting, loop assignments
// and liveness. NOTE: The broker/serializer relies on the fact that an
// analysis for OSR (osr_bailout_id is not None) subsumes an analysis for
// non-OSR (osr_bailout_id is None).
class V8_EXPORT_PRIVATE BytecodeAnalysis : public ZoneObject {
public:
BytecodeAnalysis(Handle<BytecodeArray> bytecode_array, Zone* zone,
bool do_liveness_analysis);
// Analyze the bytecodes to find the loop ranges, loop nesting, loop
// assignments and liveness, under the assumption that there is an OSR bailout
// at {osr_bailout_id}.
//
// No other methods in this class return valid information until this has been
// called.
void Analyze(BailoutId osr_bailout_id);
BailoutId osr_bailout_id, bool analyze_liveness);
// Return true if the given offset is a loop header
bool IsLoopHeader(int offset) const;
......@@ -118,23 +114,30 @@ class V8_EXPORT_PRIVATE BytecodeAnalysis {
return resume_jump_targets_;
}
// True if the current analysis has an OSR entry point.
bool HasOsrEntryPoint() const { return osr_entry_point_ != -1; }
int osr_entry_point() const { return osr_entry_point_; }
// Gets the in-liveness for the bytecode at {offset}.
// Gets the in-/out-liveness for the bytecode at {offset}.
const BytecodeLivenessState* GetInLivenessFor(int offset) const;
// Gets the out-liveness for the bytecode at {offset}.
const BytecodeLivenessState* GetOutLivenessFor(int offset) const;
// In the case of OSR, the analysis also computes the (bytecode offset of the)
// OSR entry point from the {osr_bailout_id} that was given to the
// constructor.
int osr_entry_point() const {
CHECK_LE(0, osr_entry_point_);
return osr_entry_point_;
}
// Return the osr_bailout_id (for verification purposes).
BailoutId osr_bailout_id() const { return osr_bailout_id_; }
// Return whether liveness analysis was performed (for verification purposes).
bool liveness_analyzed() const { return analyze_liveness_; }
private:
struct LoopStackEntry {
int header_offset;
LoopInfo* loop_info;
};
void Analyze();
void PushLoop(int loop_header, int loop_end);
#if DEBUG
......@@ -153,17 +156,15 @@ class V8_EXPORT_PRIVATE BytecodeAnalysis {
std::ostream& PrintLivenessTo(std::ostream& os) const;
Handle<BytecodeArray> const bytecode_array_;
bool const do_liveness_analysis_;
Zone* const zone_;
BailoutId const osr_bailout_id_;
bool const analyze_liveness_;
ZoneStack<LoopStackEntry> loop_stack_;
ZoneVector<int> loop_end_index_queue_;
ZoneVector<ResumeJumpTarget> resume_jump_targets_;
ZoneMap<int, int> end_to_header_;
ZoneMap<int, LoopInfo> header_to_info_;
int osr_entry_point_;
BytecodeLivenessMap liveness_map_;
DISALLOW_COPY_AND_ASSIGN(BytecodeAnalysis);
......
......@@ -340,8 +340,6 @@ class BytecodeGraphBuilder {
return bytecode_analysis_;
}
void RunBytecodeAnalysis() { bytecode_analysis_.Analyze(osr_offset_); }
int currently_peeled_loop_offset() const {
return currently_peeled_loop_offset_;
}
......@@ -385,9 +383,9 @@ class BytecodeGraphBuilder {
const FrameStateFunctionInfo* const frame_state_function_info_;
std::unique_ptr<SourcePositionTableIterator> source_position_iterator_;
interpreter::BytecodeArrayIterator bytecode_iterator_;
BytecodeAnalysis bytecode_analysis_;
BytecodeAnalysis const& bytecode_analysis_;
Environment* environment_;
BailoutId const osr_offset_;
bool const osr_;
int currently_peeled_loop_offset_;
bool skip_next_stack_check_;
......@@ -958,11 +956,12 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(
shared_info)),
bytecode_iterator_(
base::make_unique<OffHeapBytecodeArray>(bytecode_array)),
bytecode_analysis_(
bytecode_array.object(), local_zone,
flags & BytecodeGraphBuilderFlag::kAnalyzeEnvironmentLiveness),
bytecode_analysis_(broker_->GetBytecodeAnalysis(
bytecode_array.object(), osr_offset,
flags & BytecodeGraphBuilderFlag::kAnalyzeEnvironmentLiveness,
!FLAG_concurrent_inlining)),
environment_(nullptr),
osr_offset_(osr_offset),
osr_(!osr_offset.IsNone()),
currently_peeled_loop_offset_(-1),
skip_next_stack_check_(flags &
BytecodeGraphBuilderFlag::kSkipFirstStackCheck),
......@@ -1117,19 +1116,17 @@ class BytecodeGraphBuilder::OsrIteratorState {
void ProcessOsrPrelude() {
ZoneVector<int> outer_loop_offsets(graph_builder_->local_zone());
BytecodeAnalysis const& bytecode_analysis =
graph_builder_->bytecode_analysis();
int osr_offset = bytecode_analysis.osr_entry_point();
int osr_entry = graph_builder_->bytecode_analysis().osr_entry_point();
// We find here the outermost loop which contains the OSR loop.
int outermost_loop_offset = osr_offset;
while ((outermost_loop_offset =
bytecode_analysis.GetLoopInfoFor(outermost_loop_offset)
.parent_offset()) != -1) {
int outermost_loop_offset = osr_entry;
while ((outermost_loop_offset = graph_builder_->bytecode_analysis()
.GetLoopInfoFor(outermost_loop_offset)
.parent_offset()) != -1) {
outer_loop_offsets.push_back(outermost_loop_offset);
}
outermost_loop_offset =
outer_loop_offsets.empty() ? osr_offset : outer_loop_offsets.back();
outer_loop_offsets.empty() ? osr_entry : outer_loop_offsets.back();
graph_builder_->AdvanceIteratorsTo(outermost_loop_offset);
// We save some iterators states at the offsets of the loop headers of the
......@@ -1147,14 +1144,16 @@ class BytecodeGraphBuilder::OsrIteratorState {
}
// Finishing by advancing to the OSR entry
graph_builder_->AdvanceIteratorsTo(osr_offset);
graph_builder_->AdvanceIteratorsTo(osr_entry);
// Enters all remaining exception handler which end before the OSR loop
// so that on next call of VisitSingleBytecode they will get popped from
// the exception handlers stack.
graph_builder_->ExitThenEnterExceptionHandlers(osr_offset);
graph_builder_->ExitThenEnterExceptionHandlers(osr_entry);
graph_builder_->set_currently_peeled_loop_offset(
bytecode_analysis.GetLoopInfoFor(osr_offset).parent_offset());
graph_builder_->bytecode_analysis()
.GetLoopInfoFor(osr_entry)
.parent_offset());
}
void RestoreState(int target_offset, int new_parent_offset) {
......@@ -1203,8 +1202,8 @@ void BytecodeGraphBuilder::RemoveMergeEnvironmentsBeforeOffset(
void BytecodeGraphBuilder::AdvanceToOsrEntryAndPeelLoops() {
OsrIteratorState iterator_states(this);
iterator_states.ProcessOsrPrelude();
int osr_offset = bytecode_analysis().osr_entry_point();
DCHECK_EQ(bytecode_iterator().current_offset(), osr_offset);
int osr_entry = bytecode_analysis().osr_entry_point();
DCHECK_EQ(bytecode_iterator().current_offset(), osr_entry);
environment()->FillWithOsrValues();
......@@ -1222,7 +1221,7 @@ void BytecodeGraphBuilder::AdvanceToOsrEntryAndPeelLoops() {
// parent loop entirely, and so on.
int current_parent_offset =
bytecode_analysis().GetLoopInfoFor(osr_offset).parent_offset();
bytecode_analysis().GetLoopInfoFor(osr_entry).parent_offset();
while (current_parent_offset != -1) {
const LoopInfo& current_parent_loop =
bytecode_analysis().GetLoopInfoFor(current_parent_offset);
......@@ -1294,14 +1293,12 @@ void BytecodeGraphBuilder::VisitSingleBytecode() {
}
void BytecodeGraphBuilder::VisitBytecodes() {
RunBytecodeAnalysis();
if (!bytecode_analysis().resume_jump_targets().empty()) {
environment()->BindGeneratorState(
jsgraph()->SmiConstant(JSGeneratorObject::kGeneratorExecuting));
}
if (bytecode_analysis().HasOsrEntryPoint()) {
if (osr_) {
// We peel the OSR loop and any outer loop containing it except that we
// leave the nodes corresponding to the whole outermost loop (including
// the last copies of the loops it contains) to be generated by the normal
......
......@@ -25,6 +25,9 @@ class SourcePositionTable;
enum class BytecodeGraphBuilderFlag : uint8_t {
kSkipFirstStackCheck = 1 << 0,
// TODO(neis): Remove liveness flag here when concurrent inlining is always
// on, because then the serializer will be the only place where we perform
// bytecode analysis.
kAnalyzeEnvironmentLiveness = 1 << 1,
kBailoutOnUninitialized = 1 << 2,
};
......
......@@ -13,6 +13,7 @@
#include "src/ast/modules.h"
#include "src/codegen/code-factory.h"
#include "src/compiler/access-info.h"
#include "src/compiler/bytecode-analysis.h"
#include "src/compiler/graph-reducer.h"
#include "src/compiler/per-isolate-compiler-cache.h"
#include "src/compiler/vector-slot-pair.h"
......@@ -1353,20 +1354,18 @@ class BytecodeArrayData : public FixedArrayBaseData {
void SerializeForCompilation(JSHeapBroker* broker) {
if (is_serialized_for_compilation_) return;
DCHECK(bytecodes_.empty());
DCHECK(constant_pool_.empty());
Handle<BytecodeArray> bytecode_array =
Handle<BytecodeArray>::cast(object());
DCHECK(bytecodes_.empty());
bytecodes_.reserve(bytecode_array->length());
for (int i = 0; i < bytecode_array->length(); i++) {
bytecodes_.push_back(bytecode_array->get(i));
}
DCHECK(constant_pool_.empty());
Handle<FixedArray> constant_pool(bytecode_array->constant_pool(),
broker->isolate());
constant_pool_.reserve(constant_pool->length());
for (int i = 0; i < constant_pool->length(); i++) {
constant_pool_.push_back(broker->GetOrCreateData(constant_pool->get(i)));
......@@ -2067,6 +2066,7 @@ JSHeapBroker::JSHeapBroker(Isolate* isolate, Zone* broker_zone,
array_and_object_prototypes_(zone()),
tracing_enabled_(tracing_enabled),
feedback_(zone()),
bytecode_analyses_(zone()),
ais_for_loading_then_(zone()) {
// Note that this initialization of the refs_ pointer with the minimal
// initial capacity is redundant in the normal use case (concurrent
......@@ -4050,6 +4050,36 @@ NamedAccessFeedback const* ProcessedFeedback::AsNamedAccess() const {
return static_cast<NamedAccessFeedback const*>(this);
}
BytecodeAnalysis const& JSHeapBroker::GetBytecodeAnalysis(
Handle<BytecodeArray> bytecode_array, BailoutId osr_bailout_id,
bool analyze_liveness, bool serialize) {
ObjectData* bytecode_array_data = GetData(bytecode_array);
CHECK_NOT_NULL(bytecode_array_data);
auto it = bytecode_analyses_.find(bytecode_array_data);
if (it != bytecode_analyses_.end()) {
// Bytecode analysis can be run for OSR or for non-OSR. In the rare case
// where we optimize for OSR and consider the top-level function itself for
// inlining (because of recursion), we need both the OSR and the non-OSR
// analysis. Fortunately, the only difference between the two lies in
// whether the OSR entry offset gets computed (from the OSR bailout id).
// Hence it's okay to reuse the OSR-version when asked for the non-OSR
// version, such that we need to store at most one analysis result per
// bytecode array.
CHECK_IMPLIES(osr_bailout_id != it->second->osr_bailout_id(),
osr_bailout_id.IsNone());
CHECK_EQ(analyze_liveness, it->second->liveness_analyzed());
return *it->second;
}
CHECK(serialize);
BytecodeAnalysis* analysis = new (zone()) BytecodeAnalysis(
bytecode_array, zone(), osr_bailout_id, analyze_liveness);
DCHECK_EQ(analysis->osr_bailout_id(), osr_bailout_id);
bytecode_analyses_[bytecode_array_data] = analysis;
return *analysis;
}
OffHeapBytecodeArray::OffHeapBytecodeArray(BytecodeArrayRef bytecode_array)
: array_(bytecode_array) {}
......
......@@ -22,6 +22,7 @@ namespace v8 {
namespace internal {
namespace compiler {
class BytecodeAnalysis;
class ObjectRef;
std::ostream& operator<<(std::ostream& os, const ObjectRef& ref);
......@@ -108,6 +109,10 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
GlobalAccessFeedback const* ProcessFeedbackForGlobalAccess(
FeedbackSource const& source);
BytecodeAnalysis const& GetBytecodeAnalysis(
Handle<BytecodeArray> bytecode_array, BailoutId osr_offset,
bool analyze_liveness, bool serialize);
base::Optional<NameRef> GetNameFeedback(FeedbackNexus const& nexus);
// If there is no result stored for {map}, we return an Invalid
......@@ -144,6 +149,7 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
ZoneUnorderedMap<FeedbackSource, ProcessedFeedback const*,
FeedbackSource::Hash, FeedbackSource::Equal>
feedback_;
ZoneUnorderedMap<ObjectData*, BytecodeAnalysis*> bytecode_analyses_;
typedef ZoneUnorderedMap<MapRef, PropertyAccessInfo, ObjectRef::Hash,
ObjectRef::Equal>
MapToAccessInfos;
......
......@@ -1359,12 +1359,13 @@ struct SerializationPhase {
if (data->info()->is_source_positions_enabled()) {
flags |= SerializerForBackgroundCompilationFlag::kCollectSourcePositions;
}
if (data->info()->is_osr()) {
flags |= SerializerForBackgroundCompilationFlag::kOsr;
if (data->info()->is_analyze_environment_liveness()) {
flags |=
SerializerForBackgroundCompilationFlag::kAnalyzeEnvironmentLiveness;
}
SerializerForBackgroundCompilation serializer(
data->broker(), data->dependencies(), temp_zone,
data->info()->closure(), flags);
data->info()->closure(), flags, data->info()->osr_offset());
serializer.Run();
}
};
......
......@@ -362,14 +362,16 @@ int SerializerForBackgroundCompilation::Environment::RegisterToLocalIndex(
SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
JSHeapBroker* broker, CompilationDependencies* dependencies, Zone* zone,
Handle<JSFunction> closure, SerializerForBackgroundCompilationFlags flags)
Handle<JSFunction> closure, SerializerForBackgroundCompilationFlags flags,
BailoutId osr_offset)
: broker_(broker),
dependencies_(dependencies),
zone_(zone),
environment_(new (zone) Environment(
zone, CompilationSubject(closure, broker_->isolate(), zone))),
jump_target_environments_(zone),
flags_(flags) {
flags_(flags),
osr_offset_(osr_offset) {
JSFunctionRef(broker, closure).Serialize();
}
......@@ -383,8 +385,8 @@ SerializerForBackgroundCompilation::SerializerForBackgroundCompilation(
environment_(new (zone) Environment(zone, broker_->isolate(), function,
new_target, arguments)),
jump_target_environments_(zone),
flags_(flags) {
DCHECK(!(flags_ & SerializerForBackgroundCompilationFlag::kOsr));
flags_(flags),
osr_offset_(BailoutId::None()) {
TraceScope tracer(
broker_, this,
"SerializerForBackgroundCompilation::SerializerForBackgroundCompilation");
......@@ -402,7 +404,7 @@ bool SerializerForBackgroundCompilation::BailoutOnUninitialized(
SerializerForBackgroundCompilationFlag::kBailoutOnUninitialized)) {
return false;
}
if (flags() & SerializerForBackgroundCompilationFlag::kOsr) {
if (!osr_offset().IsNone()) {
// Exclude OSR from this optimization because we might end up skipping the
// OSR entry point. TODO(neis): Support OSR?
return false;
......@@ -483,6 +485,11 @@ void SerializerForBackgroundCompilation::TraverseBytecode() {
BytecodeArrayRef bytecode_array(
broker(), handle(environment()->function().shared()->GetBytecodeArray(),
broker()->isolate()));
broker()->GetBytecodeAnalysis(
bytecode_array.object(), osr_offset(),
flags() &
SerializerForBackgroundCompilationFlag::kAnalyzeEnvironmentLiveness,
true);
bytecode_array.SerializeForCompilation();
BytecodeArrayIterator iterator(bytecode_array.object());
ExceptionHandlerMatcher handler_matcher(iterator, bytecode_array.object());
......@@ -1010,7 +1017,7 @@ Hints SerializerForBackgroundCompilation::RunChildSerializer(
SerializerForBackgroundCompilation child_serializer(
broker(), dependencies(), zone(), function, new_target, arguments,
flags().without(SerializerForBackgroundCompilationFlag::kOsr));
flags());
return child_serializer.Run();
}
......
......@@ -284,7 +284,7 @@ using HintsVector = ZoneVector<Hints>;
enum class SerializerForBackgroundCompilationFlag : uint8_t {
kBailoutOnUninitialized = 1 << 0,
kCollectSourcePositions = 1 << 1,
kOsr = 1 << 2,
kAnalyzeEnvironmentLiveness = 1 << 2,
};
using SerializerForBackgroundCompilationFlags =
base::Flags<SerializerForBackgroundCompilationFlag>;
......@@ -340,8 +340,8 @@ class SerializerForBackgroundCompilation {
public:
SerializerForBackgroundCompilation(
JSHeapBroker* broker, CompilationDependencies* dependencies, Zone* zone,
Handle<JSFunction> closure,
SerializerForBackgroundCompilationFlags flags);
Handle<JSFunction> closure, SerializerForBackgroundCompilationFlags flags,
BailoutId osr_offset);
Hints Run(); // NOTE: Returns empty for an already-serialized function.
class Environment;
......@@ -435,6 +435,7 @@ class SerializerForBackgroundCompilation {
Zone* zone() const { return zone_; }
Environment* environment() const { return environment_; }
SerializerForBackgroundCompilationFlags flags() const { return flags_; }
BailoutId osr_offset() const { return osr_offset_; }
JSHeapBroker* const broker_;
CompilationDependencies* const dependencies_;
......@@ -442,6 +443,7 @@ class SerializerForBackgroundCompilation {
Environment* const environment_;
ZoneUnorderedMap<int, Environment*> jump_target_environments_;
SerializerForBackgroundCompilationFlags const flags_;
BailoutId const osr_offset_;
};
} // namespace compiler
......
......@@ -59,8 +59,7 @@ class BytecodeAnalysisTest : public TestWithIsolateAndZone {
Handle<BytecodeArray> bytecode,
const std::vector<std::pair<std::string, std::string>>&
expected_liveness) {
BytecodeAnalysis analysis(bytecode, zone(), true);
analysis.Analyze(BailoutId::None());
BytecodeAnalysis analysis(bytecode, zone(), BailoutId::None(), true);
interpreter::BytecodeArrayIterator iterator(bytecode);
for (auto liveness : expected_liveness) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment