[Interpreter] Avoid allocating pairs array in VisitDeclarations.
Move the logic for allocating the global declaration pair array from VisitDeclarations to a later step. This is required for concurrent bytecode generation. This change requires adding support for reserving fixed constant pool array entries, which can be later updated with the value of the literal. BUG=v8:5203 Review-Url: https://codereview.chromium.org/2167763003 Cr-Commit-Position: refs/heads/master@{#38010}
This commit is contained in:
parent
0a6ccaf268
commit
8d4658077c
@ -179,6 +179,12 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op,
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
|
||||||
|
size_t entry) {
|
||||||
|
Output(Bytecode::kLdaConstant, UnsignedOperand(entry));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
|
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
|
||||||
v8::internal::Smi* smi) {
|
v8::internal::Smi* smi) {
|
||||||
int32_t raw_smi = smi->value();
|
int32_t raw_smi = smi->value();
|
||||||
@ -633,6 +639,15 @@ size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) {
|
|||||||
return constant_array_builder()->Insert(object);
|
return constant_array_builder()->Insert(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t BytecodeArrayBuilder::AllocateConstantPoolEntry() {
|
||||||
|
return constant_array_builder()->AllocateEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BytecodeArrayBuilder::InsertConstantPoolEntryAt(size_t entry,
|
||||||
|
Handle<Object> object) {
|
||||||
|
constant_array_builder()->InsertAllocatedEntry(entry, object);
|
||||||
|
}
|
||||||
|
|
||||||
void BytecodeArrayBuilder::SetReturnPosition() {
|
void BytecodeArrayBuilder::SetReturnPosition() {
|
||||||
if (return_position_ == kNoSourcePosition) return;
|
if (return_position_ == kNoSourcePosition) return;
|
||||||
latest_source_info_.MakeStatementPosition(return_position_);
|
latest_source_info_.MakeStatementPosition(return_position_);
|
||||||
|
@ -79,6 +79,7 @@ class BytecodeArrayBuilder final : public ZoneObject {
|
|||||||
bool TemporaryRegisterIsLive(Register reg) const;
|
bool TemporaryRegisterIsLive(Register reg) const;
|
||||||
|
|
||||||
// Constant loads to accumulator.
|
// Constant loads to accumulator.
|
||||||
|
BytecodeArrayBuilder& LoadConstantPoolEntry(size_t entry);
|
||||||
BytecodeArrayBuilder& LoadLiteral(v8::internal::Smi* value);
|
BytecodeArrayBuilder& LoadLiteral(v8::internal::Smi* value);
|
||||||
BytecodeArrayBuilder& LoadLiteral(Handle<Object> object);
|
BytecodeArrayBuilder& LoadLiteral(Handle<Object> object);
|
||||||
BytecodeArrayBuilder& LoadUndefined();
|
BytecodeArrayBuilder& LoadUndefined();
|
||||||
@ -260,6 +261,11 @@ class BytecodeArrayBuilder final : public ZoneObject {
|
|||||||
// entry, so that it can be referenced by above exception handling support.
|
// entry, so that it can be referenced by above exception handling support.
|
||||||
int NewHandlerEntry() { return handler_table_builder()->NewHandlerEntry(); }
|
int NewHandlerEntry() { return handler_table_builder()->NewHandlerEntry(); }
|
||||||
|
|
||||||
|
// Allocates a slot in the constant pool which can later be inserted.
|
||||||
|
size_t AllocateConstantPoolEntry();
|
||||||
|
// Inserts a entry into an allocated constant pool entry.
|
||||||
|
void InsertConstantPoolEntryAt(size_t entry, Handle<Object> object);
|
||||||
|
|
||||||
void InitializeReturnPosition(FunctionLiteral* literal);
|
void InitializeReturnPosition(FunctionLiteral* literal);
|
||||||
|
|
||||||
void SetStatementPosition(Statement* stmt);
|
void SetStatementPosition(Statement* stmt);
|
||||||
|
@ -532,6 +532,53 @@ class BytecodeGenerator::RegisterResultScope final
|
|||||||
Register result_register_;
|
Register result_register_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Used to build a list of global declaration initial value pairs.
|
||||||
|
class BytecodeGenerator::GlobalDeclarationsBuilder final : public ZoneObject {
|
||||||
|
public:
|
||||||
|
GlobalDeclarationsBuilder(Isolate* isolate, Zone* zone)
|
||||||
|
: isolate_(isolate),
|
||||||
|
declaration_pairs_(0, zone),
|
||||||
|
constant_pool_entry_(0),
|
||||||
|
has_constant_pool_entry_(false) {}
|
||||||
|
|
||||||
|
void AddDeclaration(FeedbackVectorSlot slot, Handle<Object> initial_value) {
|
||||||
|
DCHECK(!slot.IsInvalid());
|
||||||
|
declaration_pairs_.push_back(handle(Smi::FromInt(slot.ToInt()), isolate_));
|
||||||
|
declaration_pairs_.push_back(initial_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle<FixedArray> AllocateDeclarationPairs() {
|
||||||
|
DCHECK(has_constant_pool_entry_);
|
||||||
|
int array_index = 0;
|
||||||
|
Handle<FixedArray> data = isolate_->factory()->NewFixedArray(
|
||||||
|
static_cast<int>(declaration_pairs_.size()), TENURED);
|
||||||
|
for (Handle<Object> obj : declaration_pairs_) {
|
||||||
|
data->set(array_index++, *obj);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t constant_pool_entry() {
|
||||||
|
DCHECK(has_constant_pool_entry_);
|
||||||
|
return constant_pool_entry_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_constant_pool_entry(size_t constant_pool_entry) {
|
||||||
|
DCHECK(!empty());
|
||||||
|
DCHECK(!has_constant_pool_entry_);
|
||||||
|
constant_pool_entry_ = constant_pool_entry;
|
||||||
|
has_constant_pool_entry_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() { return declaration_pairs_.empty(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Isolate* isolate_;
|
||||||
|
ZoneVector<Handle<Object>> declaration_pairs_;
|
||||||
|
size_t constant_pool_entry_;
|
||||||
|
bool has_constant_pool_entry_;
|
||||||
|
};
|
||||||
|
|
||||||
BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
|
BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
|
||||||
: isolate_(info->isolate()),
|
: isolate_(info->isolate()),
|
||||||
zone_(info->zone()),
|
zone_(info->zone()),
|
||||||
@ -542,7 +589,9 @@ BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
|
|||||||
info->SourcePositionRecordingMode())),
|
info->SourcePositionRecordingMode())),
|
||||||
info_(info),
|
info_(info),
|
||||||
scope_(info->scope()),
|
scope_(info->scope()),
|
||||||
globals_(0, info->zone()),
|
globals_builder_(new (zone()) GlobalDeclarationsBuilder(info->isolate(),
|
||||||
|
info->zone())),
|
||||||
|
global_declarations_(0, info->zone()),
|
||||||
execution_control_(nullptr),
|
execution_control_(nullptr),
|
||||||
execution_context_(nullptr),
|
execution_context_(nullptr),
|
||||||
execution_result_(nullptr),
|
execution_result_(nullptr),
|
||||||
@ -553,6 +602,20 @@ BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() {
|
Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() {
|
||||||
|
GenerateBytecode();
|
||||||
|
|
||||||
|
// Build global declaration pair arrays.
|
||||||
|
for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) {
|
||||||
|
Handle<FixedArray> declarations =
|
||||||
|
globals_builder->AllocateDeclarationPairs();
|
||||||
|
builder()->InsertConstantPoolEntryAt(globals_builder->constant_pool_entry(),
|
||||||
|
declarations);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder()->ToBytecodeArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BytecodeGenerator::GenerateBytecode() {
|
||||||
// Initialize the incoming context.
|
// Initialize the incoming context.
|
||||||
ContextScope incoming_context(this, scope(), false);
|
ContextScope incoming_context(this, scope(), false);
|
||||||
|
|
||||||
@ -572,9 +635,9 @@ Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() {
|
|||||||
VisitNewLocalFunctionContext();
|
VisitNewLocalFunctionContext();
|
||||||
ContextScope local_function_context(this, scope(), false);
|
ContextScope local_function_context(this, scope(), false);
|
||||||
VisitBuildLocalActivationContext();
|
VisitBuildLocalActivationContext();
|
||||||
MakeBytecodeBody();
|
GenerateBytecodeBody();
|
||||||
} else {
|
} else {
|
||||||
MakeBytecodeBody();
|
GenerateBytecodeBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
// In generator functions, we may not have visited every yield in the AST
|
// In generator functions, we may not have visited every yield in the AST
|
||||||
@ -586,10 +649,9 @@ Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
builder()->EnsureReturn();
|
builder()->EnsureReturn();
|
||||||
return builder()->ToBytecodeArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BytecodeGenerator::MakeBytecodeBody() {
|
void BytecodeGenerator::GenerateBytecodeBody() {
|
||||||
// Build the arguments object if it is used.
|
// Build the arguments object if it is used.
|
||||||
VisitArgumentsObject(scope()->arguments());
|
VisitArgumentsObject(scope()->arguments());
|
||||||
|
|
||||||
@ -723,9 +785,8 @@ void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
|
|||||||
case VariableLocation::UNALLOCATED: {
|
case VariableLocation::UNALLOCATED: {
|
||||||
DCHECK(!variable->binding_needs_init());
|
DCHECK(!variable->binding_needs_init());
|
||||||
FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot();
|
FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot();
|
||||||
DCHECK(!slot.IsInvalid());
|
globals_builder()->AddDeclaration(
|
||||||
globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate()));
|
slot, isolate()->factory()->undefined_value());
|
||||||
globals()->push_back(isolate()->factory()->undefined_value());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VariableLocation::LOCAL:
|
case VariableLocation::LOCAL:
|
||||||
@ -773,9 +834,7 @@ void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
|
|||||||
// Check for stack-overflow exception.
|
// Check for stack-overflow exception.
|
||||||
if (function.is_null()) return SetStackOverflow();
|
if (function.is_null()) return SetStackOverflow();
|
||||||
FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot();
|
FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot();
|
||||||
DCHECK(!slot.IsInvalid());
|
globals_builder()->AddDeclaration(slot, function);
|
||||||
globals()->push_back(handle(Smi::FromInt(slot.ToInt()), isolate()));
|
|
||||||
globals()->push_back(function);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VariableLocation::PARAMETER:
|
case VariableLocation::PARAMETER:
|
||||||
@ -810,34 +869,35 @@ void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
|
|||||||
void BytecodeGenerator::VisitDeclarations(
|
void BytecodeGenerator::VisitDeclarations(
|
||||||
ZoneList<Declaration*>* declarations) {
|
ZoneList<Declaration*>* declarations) {
|
||||||
RegisterAllocationScope register_scope(this);
|
RegisterAllocationScope register_scope(this);
|
||||||
DCHECK(globals()->empty());
|
DCHECK(globals_builder()->empty());
|
||||||
for (int i = 0; i < declarations->length(); i++) {
|
for (int i = 0; i < declarations->length(); i++) {
|
||||||
RegisterAllocationScope register_scope(this);
|
RegisterAllocationScope register_scope(this);
|
||||||
Visit(declarations->at(i));
|
Visit(declarations->at(i));
|
||||||
}
|
}
|
||||||
if (globals()->empty()) return;
|
if (globals_builder()->empty()) return;
|
||||||
int array_index = 0;
|
|
||||||
Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
|
globals_builder()->set_constant_pool_entry(
|
||||||
static_cast<int>(globals()->size()), TENURED);
|
builder()->AllocateConstantPoolEntry());
|
||||||
for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
|
|
||||||
int encoded_flags = info()->GetDeclareGlobalsFlags();
|
int encoded_flags = info()->GetDeclareGlobalsFlags();
|
||||||
|
|
||||||
register_allocator()->PrepareForConsecutiveAllocations(3);
|
register_allocator()->PrepareForConsecutiveAllocations(3);
|
||||||
|
|
||||||
Register pairs = register_allocator()->NextConsecutiveRegister();
|
Register pairs = register_allocator()->NextConsecutiveRegister();
|
||||||
builder()->LoadLiteral(data);
|
|
||||||
builder()->StoreAccumulatorInRegister(pairs);
|
|
||||||
|
|
||||||
Register flags = register_allocator()->NextConsecutiveRegister();
|
Register flags = register_allocator()->NextConsecutiveRegister();
|
||||||
builder()->LoadLiteral(Smi::FromInt(encoded_flags));
|
|
||||||
builder()->StoreAccumulatorInRegister(flags);
|
|
||||||
DCHECK(flags.index() == pairs.index() + 1);
|
|
||||||
|
|
||||||
Register function = register_allocator()->NextConsecutiveRegister();
|
Register function = register_allocator()->NextConsecutiveRegister();
|
||||||
builder()->MoveRegister(Register::function_closure(), function);
|
|
||||||
|
|
||||||
builder()->CallRuntime(Runtime::kDeclareGlobalsForInterpreter, pairs, 3);
|
// Emit code to declare globals.
|
||||||
globals()->clear();
|
builder()
|
||||||
|
->LoadConstantPoolEntry(globals_builder()->constant_pool_entry())
|
||||||
|
.StoreAccumulatorInRegister(pairs)
|
||||||
|
.LoadLiteral(Smi::FromInt(encoded_flags))
|
||||||
|
.StoreAccumulatorInRegister(flags)
|
||||||
|
.MoveRegister(Register::function_closure(), function)
|
||||||
|
.CallRuntime(Runtime::kDeclareGlobalsForInterpreter, pairs, 3);
|
||||||
|
|
||||||
|
// Push and reset globals builder.
|
||||||
|
global_declarations_.push_back(globals_builder());
|
||||||
|
globals_builder_ = new (zone()) GlobalDeclarationsBuilder(isolate(), zone());
|
||||||
}
|
}
|
||||||
|
|
||||||
void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
|
void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
|
||||||
|
@ -35,6 +35,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
|
|||||||
void VisitStatements(ZoneList<Statement*>* statments);
|
void VisitStatements(ZoneList<Statement*>* statments);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class AccumulatorResultScope;
|
||||||
class ContextScope;
|
class ContextScope;
|
||||||
class ControlScope;
|
class ControlScope;
|
||||||
class ControlScopeForBreakable;
|
class ControlScopeForBreakable;
|
||||||
@ -44,11 +45,12 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
|
|||||||
class ControlScopeForTryFinally;
|
class ControlScopeForTryFinally;
|
||||||
class ExpressionResultScope;
|
class ExpressionResultScope;
|
||||||
class EffectResultScope;
|
class EffectResultScope;
|
||||||
class AccumulatorResultScope;
|
class GlobalDeclarationsBuilder;
|
||||||
class RegisterResultScope;
|
class RegisterResultScope;
|
||||||
class RegisterAllocationScope;
|
class RegisterAllocationScope;
|
||||||
|
|
||||||
void MakeBytecodeBody();
|
void GenerateBytecode();
|
||||||
|
void GenerateBytecodeBody();
|
||||||
|
|
||||||
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
|
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
|
||||||
|
|
||||||
@ -196,7 +198,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
|
|||||||
return register_allocator_;
|
return register_allocator_;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZoneVector<Handle<Object>>* globals() { return &globals_; }
|
GlobalDeclarationsBuilder* globals_builder() { return globals_builder_; }
|
||||||
inline LanguageMode language_mode() const;
|
inline LanguageMode language_mode() const;
|
||||||
int feedback_index(FeedbackVectorSlot slot) const;
|
int feedback_index(FeedbackVectorSlot slot) const;
|
||||||
|
|
||||||
@ -205,7 +207,8 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
|
|||||||
BytecodeArrayBuilder* builder_;
|
BytecodeArrayBuilder* builder_;
|
||||||
CompilationInfo* info_;
|
CompilationInfo* info_;
|
||||||
Scope* scope_;
|
Scope* scope_;
|
||||||
ZoneVector<Handle<Object>> globals_;
|
GlobalDeclarationsBuilder* globals_builder_;
|
||||||
|
ZoneVector<GlobalDeclarationsBuilder*> global_declarations_;
|
||||||
ControlScope* execution_control_;
|
ControlScope* execution_control_;
|
||||||
ContextScope* execution_context_;
|
ContextScope* execution_context_;
|
||||||
ExpressionResultScope* execution_result_;
|
ExpressionResultScope* execution_result_;
|
||||||
|
@ -46,6 +46,13 @@ Handle<Object> ConstantArrayBuilder::ConstantArraySlice::At(
|
|||||||
return constants_[index - start_index()];
|
return constants_[index - start_index()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConstantArrayBuilder::ConstantArraySlice::InsertAt(size_t index,
|
||||||
|
Handle<Object> object) {
|
||||||
|
DCHECK_GE(index, start_index());
|
||||||
|
DCHECK_LT(index, start_index() + size());
|
||||||
|
constants_[index - start_index()] = object;
|
||||||
|
}
|
||||||
|
|
||||||
STATIC_CONST_MEMBER_DEFINITION const size_t ConstantArrayBuilder::k8BitCapacity;
|
STATIC_CONST_MEMBER_DEFINITION const size_t ConstantArrayBuilder::k8BitCapacity;
|
||||||
STATIC_CONST_MEMBER_DEFINITION const size_t
|
STATIC_CONST_MEMBER_DEFINITION const size_t
|
||||||
ConstantArrayBuilder::k16BitCapacity;
|
ConstantArrayBuilder::k16BitCapacity;
|
||||||
@ -73,9 +80,9 @@ size_t ConstantArrayBuilder::size() const {
|
|||||||
return idx_slice_[0]->size();
|
return idx_slice_[0]->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ConstantArrayBuilder::ConstantArraySlice*
|
ConstantArrayBuilder::ConstantArraySlice* ConstantArrayBuilder::IndexToSlice(
|
||||||
ConstantArrayBuilder::IndexToSlice(size_t index) const {
|
size_t index) const {
|
||||||
for (const ConstantArraySlice* slice : idx_slice_) {
|
for (ConstantArraySlice* slice : idx_slice_) {
|
||||||
if (index <= slice->max_index()) {
|
if (index <= slice->max_index()) {
|
||||||
return slice;
|
return slice;
|
||||||
}
|
}
|
||||||
@ -129,30 +136,23 @@ size_t ConstantArrayBuilder::Insert(Handle<Object> object) {
|
|||||||
ConstantArrayBuilder::index_t ConstantArrayBuilder::AllocateEntry(
|
ConstantArrayBuilder::index_t ConstantArrayBuilder::AllocateEntry(
|
||||||
Handle<Object> object) {
|
Handle<Object> object) {
|
||||||
DCHECK(!object->IsOddball());
|
DCHECK(!object->IsOddball());
|
||||||
|
index_t index = AllocateIndex(object);
|
||||||
index_t* entry = constants_map()->Get(object);
|
index_t* entry = constants_map()->Get(object);
|
||||||
|
*entry = index;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstantArrayBuilder::index_t ConstantArrayBuilder::AllocateIndex(
|
||||||
|
Handle<Object> object) {
|
||||||
for (size_t i = 0; i < arraysize(idx_slice_); ++i) {
|
for (size_t i = 0; i < arraysize(idx_slice_); ++i) {
|
||||||
if (idx_slice_[i]->available() > 0) {
|
if (idx_slice_[i]->available() > 0) {
|
||||||
size_t index = idx_slice_[i]->Allocate(object);
|
return static_cast<index_t>(idx_slice_[i]->Allocate(object));
|
||||||
*entry = static_cast<index_t>(index);
|
|
||||||
return *entry;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return kMaxUInt32;
|
return kMaxUInt32;
|
||||||
}
|
}
|
||||||
|
|
||||||
OperandSize ConstantArrayBuilder::CreateReservedEntry() {
|
|
||||||
for (size_t i = 0; i < arraysize(idx_slice_); ++i) {
|
|
||||||
if (idx_slice_[i]->available() > 0) {
|
|
||||||
idx_slice_[i]->Reserve();
|
|
||||||
return idx_slice_[i]->operand_size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UNREACHABLE();
|
|
||||||
return OperandSize::kNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConstantArrayBuilder::ConstantArraySlice*
|
ConstantArrayBuilder::ConstantArraySlice*
|
||||||
ConstantArrayBuilder::OperandSizeToSlice(OperandSize operand_size) const {
|
ConstantArrayBuilder::OperandSizeToSlice(OperandSize operand_size) const {
|
||||||
ConstantArraySlice* slice = nullptr;
|
ConstantArraySlice* slice = nullptr;
|
||||||
@ -174,6 +174,28 @@ ConstantArrayBuilder::OperandSizeToSlice(OperandSize operand_size) const {
|
|||||||
return slice;
|
return slice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ConstantArrayBuilder::AllocateEntry() {
|
||||||
|
return AllocateIndex(isolate_->factory()->the_hole_value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConstantArrayBuilder::InsertAllocatedEntry(size_t index,
|
||||||
|
Handle<Object> object) {
|
||||||
|
DCHECK_EQ(isolate_->heap()->the_hole_value(), *At(index));
|
||||||
|
ConstantArraySlice* slice = IndexToSlice(index);
|
||||||
|
slice->InsertAt(index, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
OperandSize ConstantArrayBuilder::CreateReservedEntry() {
|
||||||
|
for (size_t i = 0; i < arraysize(idx_slice_); ++i) {
|
||||||
|
if (idx_slice_[i]->available() > 0) {
|
||||||
|
idx_slice_[i]->Reserve();
|
||||||
|
return idx_slice_[i]->operand_size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
return OperandSize::kNone;
|
||||||
|
}
|
||||||
|
|
||||||
size_t ConstantArrayBuilder::CommitReservedEntry(OperandSize operand_size,
|
size_t ConstantArrayBuilder::CommitReservedEntry(OperandSize operand_size,
|
||||||
Handle<Object> object) {
|
Handle<Object> object) {
|
||||||
DiscardReservedEntry(operand_size);
|
DiscardReservedEntry(operand_size);
|
||||||
|
@ -48,6 +48,13 @@ class ConstantArrayBuilder final BASE_EMBEDDED {
|
|||||||
// present. Returns the array index associated with the object.
|
// present. Returns the array index associated with the object.
|
||||||
size_t Insert(Handle<Object> object);
|
size_t Insert(Handle<Object> object);
|
||||||
|
|
||||||
|
// Allocates an empty entry and returns the array index associated with the
|
||||||
|
// reservation. Entry can be inserted by calling InsertReservedEntry().
|
||||||
|
size_t AllocateEntry();
|
||||||
|
|
||||||
|
// Inserts the given object into an allocated entry.
|
||||||
|
void InsertAllocatedEntry(size_t index, Handle<Object> object);
|
||||||
|
|
||||||
// Creates a reserved entry in the constant pool and returns
|
// Creates a reserved entry in the constant pool and returns
|
||||||
// the size of the operand that'll be required to hold the entry
|
// the size of the operand that'll be required to hold the entry
|
||||||
// when committed.
|
// when committed.
|
||||||
@ -64,6 +71,7 @@ class ConstantArrayBuilder final BASE_EMBEDDED {
|
|||||||
typedef uint32_t index_t;
|
typedef uint32_t index_t;
|
||||||
|
|
||||||
index_t AllocateEntry(Handle<Object> object);
|
index_t AllocateEntry(Handle<Object> object);
|
||||||
|
index_t AllocateIndex(Handle<Object> object);
|
||||||
|
|
||||||
struct ConstantArraySlice final : public ZoneObject {
|
struct ConstantArraySlice final : public ZoneObject {
|
||||||
ConstantArraySlice(Zone* zone, size_t start_index, size_t capacity,
|
ConstantArraySlice(Zone* zone, size_t start_index, size_t capacity,
|
||||||
@ -72,6 +80,7 @@ class ConstantArrayBuilder final BASE_EMBEDDED {
|
|||||||
void Unreserve();
|
void Unreserve();
|
||||||
size_t Allocate(Handle<Object> object);
|
size_t Allocate(Handle<Object> object);
|
||||||
Handle<Object> At(size_t index) const;
|
Handle<Object> At(size_t index) const;
|
||||||
|
void InsertAt(size_t index, Handle<Object> object);
|
||||||
|
|
||||||
inline size_t available() const { return capacity() - reserved() - size(); }
|
inline size_t available() const { return capacity() - reserved() - size(); }
|
||||||
inline size_t reserved() const { return reserved_; }
|
inline size_t reserved() const { return reserved_; }
|
||||||
@ -91,7 +100,7 @@ class ConstantArrayBuilder final BASE_EMBEDDED {
|
|||||||
DISALLOW_COPY_AND_ASSIGN(ConstantArraySlice);
|
DISALLOW_COPY_AND_ASSIGN(ConstantArraySlice);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ConstantArraySlice* IndexToSlice(size_t index) const;
|
ConstantArraySlice* IndexToSlice(size_t index) const;
|
||||||
ConstantArraySlice* OperandSizeToSlice(OperandSize operand_size) const;
|
ConstantArraySlice* OperandSizeToSlice(OperandSize operand_size) const;
|
||||||
|
|
||||||
IdentityMap<index_t>* constants_map() { return &constants_map_; }
|
IdentityMap<index_t>* constants_map() { return &constants_map_; }
|
||||||
|
@ -283,6 +283,40 @@ TEST_F(ConstantArrayBuilderTest, ReservationsAtAllScales) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ConstantArrayBuilderTest, AllocateEntriesWithFixedReservations) {
|
||||||
|
ConstantArrayBuilder builder(isolate(), zone());
|
||||||
|
for (size_t i = 0; i < k16BitCapacity; i++) {
|
||||||
|
if ((i % 2) == 0) {
|
||||||
|
CHECK_EQ(i, builder.AllocateEntry());
|
||||||
|
} else {
|
||||||
|
builder.Insert(handle(Smi::FromInt(static_cast<int>(i)), isolate()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHECK_EQ(builder.size(), k16BitCapacity);
|
||||||
|
|
||||||
|
// Check values before reserved entries are inserted.
|
||||||
|
for (size_t i = 0; i < k16BitCapacity; i++) {
|
||||||
|
if ((i % 2) == 0) {
|
||||||
|
// Check reserved values are the hole.
|
||||||
|
Handle<Object> empty = builder.At(i);
|
||||||
|
CHECK(empty->SameValue(isolate()->heap()->the_hole_value()));
|
||||||
|
} else {
|
||||||
|
CHECK_EQ(Handle<Smi>::cast(builder.At(i))->value(), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert reserved entries.
|
||||||
|
for (size_t i = 0; i < k16BitCapacity; i += 2) {
|
||||||
|
builder.InsertAllocatedEntry(
|
||||||
|
i, handle(Smi::FromInt(static_cast<int>(i)), isolate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check values after reserved entries are inserted.
|
||||||
|
for (size_t i = 0; i < k16BitCapacity; i++) {
|
||||||
|
CHECK_EQ(Handle<Smi>::cast(builder.At(i))->value(), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace interpreter
|
} // namespace interpreter
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
Loading…
Reference in New Issue
Block a user