[turbofan] Serialize bytecode array for concurrent graph building.

We also introduce a subclass of AbstractBytecodeArray to allow access
to the off-heap copy of bytecode array from the bytecode iterator.

Note that not all bytecode iterators have been converted to iterate
the off-heap copy; in particular, bytecode analysis still iterates
the on-heap bytecode array.

Bug: v8:7790
Change-Id: Icc1b0adb5f63d7cfe94286311f64f209067bbfd5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1672931
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Reviewed-by: Maya Lekova <mslekova@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62403}
This commit is contained in:
Jaroslav Sevcik 2019-06-27 07:52:42 +02:00 committed by Commit Bot
parent fc8c4ef27e
commit a8070482c8
10 changed files with 211 additions and 40 deletions

View File

@ -32,7 +32,7 @@ namespace compiler {
class BytecodeGraphBuilder {
public:
BytecodeGraphBuilder(JSHeapBroker* broker, Zone* local_zone,
Handle<BytecodeArray> bytecode_array,
BytecodeArrayRef bytecode_array,
Handle<SharedFunctionInfo> shared,
Handle<FeedbackVector> feedback_vector,
BailoutId osr_offset, JSGraph* jsgraph,
@ -318,9 +318,7 @@ class BytecodeGraphBuilder {
return jsgraph_->simplified();
}
Zone* local_zone() const { return local_zone_; }
const Handle<BytecodeArray>& bytecode_array() const {
return bytecode_array_;
}
const BytecodeArrayRef bytecode_array() const { return bytecode_array_; }
const Handle<FeedbackVector>& feedback_vector() const {
return feedback_vector_;
}
@ -382,7 +380,7 @@ class BytecodeGraphBuilder {
Zone* const local_zone_;
JSGraph* const jsgraph_;
CallFrequency const invocation_frequency_;
Handle<BytecodeArray> const bytecode_array_;
BytecodeArrayRef const bytecode_array_;
Handle<FeedbackVector> const feedback_vector_;
JSTypeHintLowering const type_hint_lowering_;
const FrameStateFunctionInfo* const frame_state_function_info_;
@ -938,8 +936,7 @@ Node* BytecodeGraphBuilder::Environment::Checkpoint(
}
BytecodeGraphBuilder::BytecodeGraphBuilder(
JSHeapBroker* broker, Zone* local_zone,
Handle<BytecodeArray> bytecode_array,
JSHeapBroker* broker, Zone* local_zone, BytecodeArrayRef bytecode_array,
Handle<SharedFunctionInfo> shared_info,
Handle<FeedbackVector> feedback_vector, BailoutId osr_offset,
JSGraph* jsgraph, CallFrequency const& invocation_frequency,
@ -958,13 +955,15 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(
: JSTypeHintLowering::kNoFlags),
frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
FrameStateType::kInterpretedFunction,
bytecode_array->parameter_count(), bytecode_array->register_count(),
bytecode_array.parameter_count(), bytecode_array.register_count(),
shared_info)),
source_position_iterator_(
handle(bytecode_array->SourcePositionTableIfCollected(), isolate())),
bytecode_iterator_(bytecode_array),
handle(bytecode_array.object()->SourcePositionTableIfCollected(),
isolate())),
bytecode_iterator_(
base::make_unique<OffHeapBytecodeArray>(bytecode_array)),
bytecode_analysis_(
bytecode_array, local_zone,
bytecode_array.object(), local_zone,
flags & BytecodeGraphBuilderFlag::kAnalyzeEnvironmentLiveness),
environment_(nullptr),
osr_offset_(osr_offset),
@ -1009,21 +1008,18 @@ VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) {
}
void BytecodeGraphBuilder::CreateGraph() {
BytecodeArrayRef bytecode_array_ref(broker(), bytecode_array());
SourcePositionTable::Scope pos_scope(source_positions_, start_position_);
// Set up the basic structure of the graph. Outputs for {Start} are the formal
// parameters (including the receiver) plus new target, number of arguments,
// context and closure.
int actual_parameter_count = bytecode_array_ref.parameter_count() + 4;
int actual_parameter_count = bytecode_array().parameter_count() + 4;
graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
Environment env(
this, bytecode_array_ref.register_count(),
bytecode_array_ref.parameter_count(),
bytecode_array_ref.incoming_new_target_or_generator_register(),
graph()->start());
Environment env(this, bytecode_array().register_count(),
bytecode_array().parameter_count(),
bytecode_array().incoming_new_target_or_generator_register(),
graph()->start());
set_environment(&env);
VisitBytecodes();
@ -3289,8 +3285,7 @@ void BytecodeGraphBuilder::VisitSuspendGenerator() {
CHECK_EQ(0, first_reg.index());
int register_count =
static_cast<int>(bytecode_iterator().GetRegisterCountOperand(2));
int parameter_count_without_receiver =
bytecode_array()->parameter_count() - 1;
int parameter_count_without_receiver = bytecode_array().parameter_count() - 1;
Node* suspend_id = jsgraph()->SmiConstant(
bytecode_iterator().GetUnsignedImmediateOperand(3));
@ -3430,8 +3425,7 @@ void BytecodeGraphBuilder::VisitResumeGenerator() {
const BytecodeLivenessState* liveness = bytecode_analysis().GetOutLivenessFor(
bytecode_iterator().current_offset());
int parameter_count_without_receiver =
bytecode_array()->parameter_count() - 1;
int parameter_count_without_receiver = bytecode_array().parameter_count() - 1;
// Mapping between registers and array indices must match that used in
// InterpreterAssembler::ExportParametersAndRegisterFile.
@ -3824,7 +3818,7 @@ Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) {
}
void BytecodeGraphBuilder::ExitThenEnterExceptionHandlers(int current_offset) {
HandlerTable table(*bytecode_array());
HandlerTable table(*(bytecode_array().object()));
// Potentially exit exception handlers.
while (!exception_handlers_.empty()) {
@ -4027,7 +4021,9 @@ void BuildGraphFromBytecode(JSHeapBroker* broker, Zone* local_zone,
SourcePositionTable* source_positions,
Handle<Context> native_context, int inlining_id,
BytecodeGraphBuilderFlags flags) {
BytecodeGraphBuilder builder(broker, local_zone, bytecode_array, shared,
BytecodeArrayRef bytecode_array_ref(broker, bytecode_array);
DCHECK(bytecode_array_ref.IsSerializedForCompilation());
BytecodeGraphBuilder builder(broker, local_zone, bytecode_array_ref, shared,
feedback_vector, osr_offset, jsgraph,
invocation_frequency, source_positions,
native_context, inlining_id, flags);

View File

@ -1311,18 +1311,74 @@ class BytecodeArrayData : public FixedArrayBaseData {
return incoming_new_target_or_generator_register_;
}
uint8_t get(int index) const {
DCHECK(is_serialized_for_compilation_);
return bytecodes_[index];
}
Address GetFirstBytecodeAddress() const {
return reinterpret_cast<Address>(bytecodes_.data());
}
Handle<Object> GetConstantAtIndex(int index, Isolate* isolate) const {
return constant_pool_[index]->object();
}
bool IsConstantAtIndexSmi(int index) const {
return constant_pool_[index]->is_smi();
}
Smi GetConstantAtIndexAsSmi(int index) const {
return *(Handle<Smi>::cast(constant_pool_[index]->object()));
}
bool IsSerializedForCompilation() const {
return is_serialized_for_compilation_;
}
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());
bytecodes_.reserve(bytecode_array->length());
for (int i = 0; i < bytecode_array->length(); i++) {
bytecodes_.push_back(bytecode_array->get(i));
}
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)));
}
is_serialized_for_compilation_ = true;
}
BytecodeArrayData(JSHeapBroker* broker, ObjectData** storage,
Handle<BytecodeArray> object)
: FixedArrayBaseData(broker, storage, object),
register_count_(object->register_count()),
parameter_count_(object->parameter_count()),
incoming_new_target_or_generator_register_(
object->incoming_new_target_or_generator_register()) {}
object->incoming_new_target_or_generator_register()),
bytecodes_(broker->zone()),
constant_pool_(broker->zone()) {}
private:
int const register_count_;
int const parameter_count_;
interpreter::Register const incoming_new_target_or_generator_register_;
bool is_serialized_for_compilation_ = false;
ZoneVector<uint8_t> bytecodes_;
ZoneVector<ObjectData*> constant_pool_;
};
class JSArrayData : public JSObjectData {
@ -2639,6 +2695,62 @@ double FixedDoubleArrayRef::get_scalar(int i) const {
return data()->AsFixedDoubleArray()->Get(i).get_scalar();
}
uint8_t BytecodeArrayRef::get(int index) const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation;
AllowHandleDereference allow_handle_dereference;
return object()->get(index);
}
return data()->AsBytecodeArray()->get(index);
}
Address BytecodeArrayRef::GetFirstBytecodeAddress() const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation;
AllowHandleDereference allow_handle_dereference;
return object()->GetFirstBytecodeAddress();
}
return data()->AsBytecodeArray()->GetFirstBytecodeAddress();
}
Handle<Object> BytecodeArrayRef::GetConstantAtIndex(int index) const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation;
AllowHandleDereference allow_handle_dereference;
return handle(object()->constant_pool().get(index), broker()->isolate());
}
return data()->AsBytecodeArray()->GetConstantAtIndex(index,
broker()->isolate());
}
bool BytecodeArrayRef::IsConstantAtIndexSmi(int index) const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation;
AllowHandleDereference allow_handle_dereference;
return object()->constant_pool().get(index).IsSmi();
}
return data()->AsBytecodeArray()->IsConstantAtIndexSmi(index);
}
Smi BytecodeArrayRef::GetConstantAtIndexAsSmi(int index) const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation;
AllowHandleDereference allow_handle_dereference;
return Smi::cast(object()->constant_pool().get(index));
}
return data()->AsBytecodeArray()->GetConstantAtIndexAsSmi(index);
}
bool BytecodeArrayRef::IsSerializedForCompilation() const {
if (broker()->mode() == JSHeapBroker::kDisabled) return true;
return data()->AsBytecodeArray()->IsSerializedForCompilation();
}
void BytecodeArrayRef::SerializeForCompilation() {
if (broker()->mode() == JSHeapBroker::kDisabled) return;
data()->AsBytecodeArray()->SerializeForCompilation(broker());
}
#define IF_BROKER_DISABLED_ACCESS_HANDLE_C(holder, name) \
if (broker()->mode() == JSHeapBroker::kDisabled) { \
AllowHandleAllocation handle_allocation; \
@ -3773,6 +3885,36 @@ NamedAccessFeedback const* ProcessedFeedback::AsNamedAccess() const {
return static_cast<NamedAccessFeedback const*>(this);
}
OffHeapBytecodeArray::OffHeapBytecodeArray(BytecodeArrayRef bytecode_array)
: array_(bytecode_array) {}
int OffHeapBytecodeArray::length() const { return array_.length(); }
int OffHeapBytecodeArray::parameter_count() const {
return array_.parameter_count();
}
uint8_t OffHeapBytecodeArray::get(int index) const { return array_.get(index); }
void OffHeapBytecodeArray::set(int index, uint8_t value) { UNREACHABLE(); }
Address OffHeapBytecodeArray::GetFirstBytecodeAddress() const {
return array_.GetFirstBytecodeAddress();
}
Handle<Object> OffHeapBytecodeArray::GetConstantAtIndex(
int index, Isolate* isolate) const {
return array_.GetConstantAtIndex(index);
}
bool OffHeapBytecodeArray::IsConstantAtIndexSmi(int index) const {
return array_.IsConstantAtIndexSmi(index);
}
Smi OffHeapBytecodeArray::GetConstantAtIndexAsSmi(int index) const {
return array_.GetConstantAtIndexAsSmi(index);
}
#undef BIMODAL_ACCESSOR
#undef BIMODAL_ACCESSOR_B
#undef BIMODAL_ACCESSOR_C

View File

@ -11,6 +11,7 @@
#include "src/compiler/refs-map.h"
#include "src/handles/handles.h"
#include "src/ic/call-optimization.h"
#include "src/interpreter/bytecode-array-accessor.h"
#include "src/objects/feedback-vector.h"
#include "src/objects/function-kind.h"
#include "src/objects/instance-type.h"
@ -605,6 +606,18 @@ class BytecodeArrayRef : public FixedArrayBaseRef {
int register_count() const;
int parameter_count() const;
interpreter::Register incoming_new_target_or_generator_register() const;
// Bytecode access methods.
uint8_t get(int index) const;
Address GetFirstBytecodeAddress() const;
// Constant pool access.
Handle<Object> GetConstantAtIndex(int index) const;
bool IsConstantAtIndexSmi(int index) const;
Smi GetConstantAtIndexAsSmi(int index) const;
bool IsSerializedForCompilation() const;
void SerializeForCompilation();
};
class JSArrayRef : public JSObjectRef {
@ -1008,6 +1021,23 @@ Reduction NoChangeBecauseOfMissingData(JSHeapBroker* broker,
// compilation is finished.
bool CanInlineElementAccess(MapRef const& map);
class OffHeapBytecodeArray final : public interpreter::AbstractBytecodeArray {
public:
explicit OffHeapBytecodeArray(BytecodeArrayRef bytecode_array);
int length() const override;
int parameter_count() const override;
uint8_t get(int index) const override;
void set(int index, uint8_t value) override;
Address GetFirstBytecodeAddress() const override;
Handle<Object> GetConstantAtIndex(int index, Isolate* isolate) const override;
bool IsConstantAtIndexSmi(int index) const override;
Smi GetConstantAtIndexAsSmi(int index) const override;
private:
BytecodeArrayRef array_;
};
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -482,6 +482,7 @@ void SerializerForBackgroundCompilation::TraverseBytecode() {
BytecodeArrayRef bytecode_array(
broker(), handle(environment()->function().shared()->GetBytecodeArray(),
broker()->isolate()));
bytecode_array.SerializeForCompilation();
BytecodeArrayIterator iterator(bytecode_array.object());
ExceptionHandlerMatcher handler_matcher(iterator, bytecode_array.object());

View File

@ -55,8 +55,8 @@ class OnHeapBytecodeArray final : public AbstractBytecodeArray {
} // namespace
BytecodeArrayAccessor::BytecodeArrayAccessor(
AbstractBytecodeArray* bytecode_array, int initial_offset)
: bytecode_array_(bytecode_array),
std::unique_ptr<AbstractBytecodeArray> bytecode_array, int initial_offset)
: bytecode_array_(std::move(bytecode_array)),
bytecode_offset_(initial_offset),
operand_scale_(OperandScale::kSingle),
prefix_offset_(0) {
@ -65,8 +65,9 @@ BytecodeArrayAccessor::BytecodeArrayAccessor(
BytecodeArrayAccessor::BytecodeArrayAccessor(
Handle<BytecodeArray> bytecode_array, int initial_offset)
: BytecodeArrayAccessor(new OnHeapBytecodeArray(bytecode_array),
initial_offset) {}
: BytecodeArrayAccessor(
base::make_unique<OnHeapBytecodeArray>(bytecode_array),
initial_offset) {}
void BytecodeArrayAccessor::SetOffset(int offset) {
bytecode_offset_ = offset;

View File

@ -83,7 +83,7 @@ class V8_EXPORT_PRIVATE AbstractBytecodeArray {
class V8_EXPORT_PRIVATE BytecodeArrayAccessor {
public:
BytecodeArrayAccessor(AbstractBytecodeArray* bytecode_array,
BytecodeArrayAccessor(std::unique_ptr<AbstractBytecodeArray> bytecode_array,
int initial_offset);
BytecodeArrayAccessor(Handle<BytecodeArray> bytecode_array,

View File

@ -11,8 +11,8 @@ namespace internal {
namespace interpreter {
BytecodeArrayIterator::BytecodeArrayIterator(
AbstractBytecodeArray* bytecode_array)
: BytecodeArrayAccessor(bytecode_array, 0) {}
std::unique_ptr<AbstractBytecodeArray> bytecode_array)
: BytecodeArrayAccessor(std::move(bytecode_array), 0) {}
BytecodeArrayIterator::BytecodeArrayIterator(
Handle<BytecodeArray> bytecode_array)

View File

@ -14,7 +14,8 @@ namespace interpreter {
class V8_EXPORT_PRIVATE BytecodeArrayIterator final
: public BytecodeArrayAccessor {
public:
explicit BytecodeArrayIterator(AbstractBytecodeArray* array);
explicit BytecodeArrayIterator(std::unique_ptr<AbstractBytecodeArray> array);
explicit BytecodeArrayIterator(Handle<BytecodeArray> array);
void Advance();

View File

@ -11,8 +11,8 @@ namespace internal {
namespace interpreter {
BytecodeArrayRandomIterator::BytecodeArrayRandomIterator(
AbstractBytecodeArray* bytecode_array, Zone* zone)
: BytecodeArrayAccessor(bytecode_array, 0), offsets_(zone) {
std::unique_ptr<AbstractBytecodeArray> bytecode_array, Zone* zone)
: BytecodeArrayAccessor(std::move(bytecode_array), 0), offsets_(zone) {
Initialize();
}

View File

@ -16,10 +16,10 @@ namespace interpreter {
class V8_EXPORT_PRIVATE BytecodeArrayRandomIterator final
: public BytecodeArrayAccessor {
public:
explicit BytecodeArrayRandomIterator(AbstractBytecodeArray* bytecode_array,
Zone* zone);
explicit BytecodeArrayRandomIterator(Handle<BytecodeArray> bytecode_array,
Zone* zone);
BytecodeArrayRandomIterator(
std::unique_ptr<AbstractBytecodeArray> bytecode_array, Zone* zone);
BytecodeArrayRandomIterator(Handle<BytecodeArray> bytecode_array, Zone* zone);
BytecodeArrayRandomIterator& operator++() {
++current_index_;