Commit ef93854a authored by oth's avatar oth Committed by Commit bot

[interpreter] Move temporary register allocator into own file.

Moves the temporary register allocator out of the bytecode array
builder into TemporaryRegisterAllocator class and adds unittests.
Particular must be taken around the translation window boundary
motivating the addition of tests.

Also adds a Clear() method to IdentityMap() which is called by
the destructor. This allows classes to hold an IdentityMap if
they are zone allocated. Classes must call Clear() before the zone
is re-cycled or face v8 heap corruption.

BUG=v8:4280,v8:4675
LOG=N

Review URL: https://codereview.chromium.org/1651133002

Cr-Commit-Position: refs/heads/master@{#33686}
parent d8fd30b5
...@@ -14,11 +14,18 @@ namespace internal { ...@@ -14,11 +14,18 @@ namespace internal {
static const int kInitialIdentityMapSize = 4; static const int kInitialIdentityMapSize = 4;
static const int kResizeFactor = 4; static const int kResizeFactor = 4;
IdentityMapBase::~IdentityMapBase() { IdentityMapBase::~IdentityMapBase() { Clear(); }
if (keys_) heap_->UnregisterStrongRoots(keys_);
void IdentityMapBase::Clear() {
if (keys_) {
heap_->UnregisterStrongRoots(keys_);
keys_ = nullptr;
values_ = nullptr;
size_ = 0;
mask_ = 0;
}
} }
IdentityMapBase::RawEntry IdentityMapBase::Lookup(Object* key) { IdentityMapBase::RawEntry IdentityMapBase::Lookup(Object* key) {
int index = LookupIndex(key); int index = LookupIndex(key);
return index >= 0 ? &values_[index] : nullptr; return index >= 0 ? &values_[index] : nullptr;
......
...@@ -36,6 +36,7 @@ class IdentityMapBase { ...@@ -36,6 +36,7 @@ class IdentityMapBase {
RawEntry GetEntry(Object* key); RawEntry GetEntry(Object* key);
RawEntry FindEntry(Object* key); RawEntry FindEntry(Object* key);
void Clear();
private: private:
// Internal implementation should not be called directly by subclasses. // Internal implementation should not be called directly by subclasses.
...@@ -85,6 +86,9 @@ class IdentityMap : public IdentityMapBase { ...@@ -85,6 +86,9 @@ class IdentityMap : public IdentityMapBase {
// Set the value for the given key. // Set the value for the given key.
void Set(Handle<Object> key, V v) { Set(*key, v); } void Set(Handle<Object> key, V v) { Set(*key, v); }
void Set(Object* key, V v) { *(reinterpret_cast<V*>(GetEntry(key))) = v; } void Set(Object* key, V v) { *(reinterpret_cast<V*>(GetEntry(key))) = v; }
// Removes all elements from the map.
void Clear() { IdentityMapBase::Clear(); }
}; };
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -64,7 +64,9 @@ class BytecodeArrayBuilder::PreviousBytecodeHelper BASE_EMBEDDED { ...@@ -64,7 +64,9 @@ class BytecodeArrayBuilder::PreviousBytecodeHelper BASE_EMBEDDED {
DISALLOW_COPY_AND_ASSIGN(PreviousBytecodeHelper); DISALLOW_COPY_AND_ASSIGN(PreviousBytecodeHelper);
}; };
BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone) BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone,
int parameter_count,
int context_count, int locals_count)
: isolate_(isolate), : isolate_(isolate),
zone_(zone), zone_(zone),
bytecodes_(zone), bytecodes_(zone),
...@@ -75,32 +77,17 @@ BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone) ...@@ -75,32 +77,17 @@ BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone)
last_bytecode_start_(~0), last_bytecode_start_(~0),
exit_seen_in_block_(false), exit_seen_in_block_(false),
unbound_jumps_(0), unbound_jumps_(0),
parameter_count_(-1), parameter_count_(parameter_count),
local_register_count_(-1), local_register_count_(locals_count),
context_register_count_(-1), context_register_count_(context_count),
temporary_register_count_(0), temporary_allocator_(zone, fixed_register_count()),
free_temporaries_(zone), register_translator_(this) {
register_translator_(this) {} DCHECK_GE(parameter_count_, 0);
DCHECK_GE(context_register_count_, 0);
BytecodeArrayBuilder::~BytecodeArrayBuilder() { DCHECK_EQ(0, unbound_jumps_); }
void BytecodeArrayBuilder::set_locals_count(int number_of_locals) {
local_register_count_ = number_of_locals;
DCHECK_LE(context_register_count_, 0);
}
void BytecodeArrayBuilder::set_parameter_count(int number_of_parameters) {
parameter_count_ = number_of_parameters;
}
void BytecodeArrayBuilder::set_context_count(int number_of_contexts) {
context_register_count_ = number_of_contexts;
DCHECK_GE(local_register_count_, 0); DCHECK_GE(local_register_count_, 0);
} }
BytecodeArrayBuilder::~BytecodeArrayBuilder() { DCHECK_EQ(0, unbound_jumps_); }
Register BytecodeArrayBuilder::first_context_register() const { Register BytecodeArrayBuilder::first_context_register() const {
DCHECK_GT(context_register_count_, 0); DCHECK_GT(context_register_count_, 0);
...@@ -114,18 +101,6 @@ Register BytecodeArrayBuilder::last_context_register() const { ...@@ -114,18 +101,6 @@ Register BytecodeArrayBuilder::last_context_register() const {
} }
Register BytecodeArrayBuilder::first_temporary_register() const {
DCHECK_GT(temporary_register_count_, 0);
return Register(fixed_register_count());
}
Register BytecodeArrayBuilder::last_temporary_register() const {
DCHECK_GT(temporary_register_count_, 0);
return Register(fixed_register_count() + temporary_register_count_ - 1);
}
Register BytecodeArrayBuilder::Parameter(int parameter_index) const { Register BytecodeArrayBuilder::Parameter(int parameter_index) const {
DCHECK_GE(parameter_index, 0); DCHECK_GE(parameter_index, 0);
return Register::FromParameterIndex(parameter_index, parameter_count()); return Register::FromParameterIndex(parameter_index, parameter_count());
...@@ -137,12 +112,6 @@ bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const { ...@@ -137,12 +112,6 @@ bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const {
} }
bool BytecodeArrayBuilder::RegisterIsTemporary(Register reg) const {
return temporary_register_count_ > 0 && first_temporary_register() <= reg &&
reg <= last_temporary_register();
}
Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() {
DCHECK_EQ(bytecode_generated_, false); DCHECK_EQ(bytecode_generated_, false);
EnsureReturn(); EnsureReturn();
...@@ -1208,148 +1177,10 @@ size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { ...@@ -1208,148 +1177,10 @@ size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) {
return constant_array_builder()->Insert(object); return constant_array_builder()->Insert(object);
} }
void BytecodeArrayBuilder::ForgeTemporaryRegister() {
temporary_register_count_++;
}
int BytecodeArrayBuilder::BorrowTemporaryRegister() {
if (free_temporaries_.empty()) {
ForgeTemporaryRegister();
return last_temporary_register().index();
} else {
auto pos = free_temporaries_.begin();
int retval = *pos;
free_temporaries_.erase(pos);
return retval;
}
}
int BytecodeArrayBuilder::BorrowTemporaryRegisterNotInRange(int start_index,
int end_index) {
auto index = free_temporaries_.lower_bound(start_index);
if (index == free_temporaries_.begin()) {
// If start_index is the first free register, check for a register
// greater than end_index.
index = free_temporaries_.upper_bound(end_index);
if (index == free_temporaries_.end()) {
ForgeTemporaryRegister();
return last_temporary_register().index();
}
} else {
// If there is a free register < start_index
index--;
}
int retval = *index;
free_temporaries_.erase(index);
return retval;
}
void BytecodeArrayBuilder::BorrowConsecutiveTemporaryRegister(int reg_index) {
DCHECK(free_temporaries_.find(reg_index) != free_temporaries_.end());
free_temporaries_.erase(reg_index);
}
void BytecodeArrayBuilder::ReturnTemporaryRegister(int reg_index) {
DCHECK(free_temporaries_.find(reg_index) == free_temporaries_.end());
free_temporaries_.insert(reg_index);
}
int BytecodeArrayBuilder::PrepareForConsecutiveTemporaryRegisters(
size_t count) {
if (count == 0) {
return -1;
}
// TODO(oth): replace use of set<> here for free_temporaries with a
// more efficient structure. And/or partition into two searches -
// one before the translation window and one after.
// A run will require at least |count| free temporaries.
while (free_temporaries_.size() < count) {
ForgeTemporaryRegister();
free_temporaries_.insert(last_temporary_register().index());
}
// Search within existing temporaries for a run.
auto start = free_temporaries_.begin();
size_t run_length = 0;
for (auto run_end = start; run_end != free_temporaries_.end(); run_end++) {
int expected = *start + static_cast<int>(run_length);
if (*run_end != expected) {
start = run_end;
run_length = 0;
}
Register reg_start(*start);
Register reg_expected(expected);
if (RegisterTranslator::DistanceToTranslationWindow(reg_start) > 0 &&
RegisterTranslator::DistanceToTranslationWindow(reg_expected) <= 0) {
// Run straddles the lower edge of the translation window. Registers
// after the start of this boundary are displaced by the register
// translator to provide a hole for translation. Runs either side
// of the boundary are fine.
start = run_end;
run_length = 0;
}
if (++run_length == count) {
return *start;
}
}
// Continue run if possible across existing last temporary.
if (temporary_register_count_ > 0 &&
(start == free_temporaries_.end() ||
*start + static_cast<int>(run_length) !=
last_temporary_register().index() + 1)) {
run_length = 0;
}
// Pad temporaries if extended run would cross translation boundary.
Register reg_first(*start);
Register reg_last(*start + static_cast<int>(count) - 1);
DCHECK_GT(RegisterTranslator::DistanceToTranslationWindow(reg_first),
RegisterTranslator::DistanceToTranslationWindow(reg_last));
while (RegisterTranslator::DistanceToTranslationWindow(reg_first) > 0 &&
RegisterTranslator::DistanceToTranslationWindow(reg_last) <= 0) {
ForgeTemporaryRegister();
free_temporaries_.insert(last_temporary_register().index());
start = --free_temporaries_.end();
reg_first = Register(*start);
reg_last = Register(*start + static_cast<int>(count) - 1);
run_length = 0;
}
// Ensure enough registers for run.
while (run_length++ < count) {
ForgeTemporaryRegister();
free_temporaries_.insert(last_temporary_register().index());
}
int run_start =
last_temporary_register().index() - static_cast<int>(count) + 1;
DCHECK(RegisterTranslator::DistanceToTranslationWindow(Register(run_start)) <=
0 ||
RegisterTranslator::DistanceToTranslationWindow(
Register(run_start + static_cast<int>(count) - 1)) > 0);
return run_start;
}
bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const {
if (temporary_register_count_ > 0) { return temporary_register_allocator()->RegisterIsLive(reg);
DCHECK(reg.index() >= first_temporary_register().index() &&
reg.index() <= last_temporary_register().index());
return free_temporaries_.find(reg.index()) == free_temporaries_.end();
} else {
return false;
}
} }
bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index, bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index,
uint32_t operand_value) const { uint32_t operand_value) const {
OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index); OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_ #define V8_INTERPRETER_BYTECODE_ARRAY_BUILDER_H_
#include "src/ast/ast.h" #include "src/ast/ast.h"
#include "src/interpreter/bytecode-register-allocator.h"
#include "src/interpreter/bytecodes.h" #include "src/interpreter/bytecodes.h"
#include "src/interpreter/constant-array-builder.h" #include "src/interpreter/constant-array-builder.h"
#include "src/interpreter/handler-table-builder.h" #include "src/interpreter/handler-table-builder.h"
...@@ -26,29 +27,27 @@ class Register; ...@@ -26,29 +27,27 @@ class Register;
// when rest parameters implementation has settled down. // when rest parameters implementation has settled down.
enum class CreateArgumentsType { kMappedArguments, kUnmappedArguments }; enum class CreateArgumentsType { kMappedArguments, kUnmappedArguments };
class BytecodeArrayBuilder final : private RegisterMover { class BytecodeArrayBuilder final : public ZoneObject, private RegisterMover {
public: public:
BytecodeArrayBuilder(Isolate* isolate, Zone* zone); BytecodeArrayBuilder(Isolate* isolate, Zone* zone, int parameter_count,
int context_count, int locals_count);
~BytecodeArrayBuilder(); ~BytecodeArrayBuilder();
Handle<BytecodeArray> ToBytecodeArray(); Handle<BytecodeArray> ToBytecodeArray();
// Set the number of parameters expected by function. // Get the number of parameters expected by function.
void set_parameter_count(int number_of_params);
int parameter_count() const { int parameter_count() const {
DCHECK_GE(parameter_count_, 0); DCHECK_GE(parameter_count_, 0);
return parameter_count_; return parameter_count_;
} }
// Set the number of locals required for bytecode array. // Get the number of locals required for bytecode array.
void set_locals_count(int number_of_locals);
int locals_count() const { int locals_count() const {
DCHECK_GE(local_register_count_, 0); DCHECK_GE(local_register_count_, 0);
return local_register_count_; return local_register_count_;
} }
// Set number of contexts required for bytecode array. // Get number of contexts required for bytecode array.
void set_context_count(int number_of_contexts);
int context_count() const { int context_count() const {
DCHECK_GE(context_register_count_, 0); DCHECK_GE(context_register_count_, 0);
return context_register_count_; return context_register_count_;
...@@ -62,7 +61,11 @@ class BytecodeArrayBuilder final : private RegisterMover { ...@@ -62,7 +61,11 @@ class BytecodeArrayBuilder final : private RegisterMover {
// Returns the number of fixed and temporary registers. // Returns the number of fixed and temporary registers.
int fixed_and_temporary_register_count() const { int fixed_and_temporary_register_count() const {
return fixed_register_count() + temporary_register_count_; return fixed_register_count() + temporary_register_count();
}
int temporary_register_count() const {
return temporary_register_allocator()->allocation_count();
} }
// Returns the number of registers used for translating wide // Returns the number of registers used for translating wide
...@@ -78,8 +81,8 @@ class BytecodeArrayBuilder final : private RegisterMover { ...@@ -78,8 +81,8 @@ class BytecodeArrayBuilder final : private RegisterMover {
// local. // local.
bool RegisterIsParameterOrLocal(Register reg) const; bool RegisterIsParameterOrLocal(Register reg) const;
// Return true if the register |reg| represents a temporary register. // Returns true if the register |reg| is a live temporary register.
bool RegisterIsTemporary(Register reg) const; bool TemporaryRegisterIsLive(Register reg) const;
// Constant loads to accumulator. // Constant loads to accumulator.
BytecodeArrayBuilder& LoadLiteral(v8::internal::Smi* value); BytecodeArrayBuilder& LoadLiteral(v8::internal::Smi* value);
...@@ -251,6 +254,12 @@ class BytecodeArrayBuilder final : private RegisterMover { ...@@ -251,6 +254,12 @@ class BytecodeArrayBuilder final : private RegisterMover {
// Accessors // Accessors
Zone* zone() const { return zone_; } Zone* zone() const { return zone_; }
TemporaryRegisterAllocator* temporary_register_allocator() {
return &temporary_allocator_;
}
const TemporaryRegisterAllocator* temporary_register_allocator() const {
return &temporary_allocator_;
}
private: private:
class PreviousBytecodeHelper; class PreviousBytecodeHelper;
...@@ -318,18 +327,6 @@ class BytecodeArrayBuilder final : private RegisterMover { ...@@ -318,18 +327,6 @@ class BytecodeArrayBuilder final : private RegisterMover {
bool NeedToBooleanCast(); bool NeedToBooleanCast();
bool IsRegisterInAccumulator(Register reg); bool IsRegisterInAccumulator(Register reg);
// Temporary register management.
void ForgeTemporaryRegister();
int BorrowTemporaryRegister();
int BorrowTemporaryRegisterNotInRange(int start_index, int end_index);
void ReturnTemporaryRegister(int reg_index);
int PrepareForConsecutiveTemporaryRegisters(size_t count);
void BorrowConsecutiveTemporaryRegister(int reg_index);
bool TemporaryRegisterIsLive(Register reg) const;
Register first_temporary_register() const;
Register last_temporary_register() const;
// Gets a constant pool entry for the |object|. // Gets a constant pool entry for the |object|.
size_t GetConstantPoolEntry(Handle<Object> object); size_t GetConstantPoolEntry(Handle<Object> object);
...@@ -360,8 +357,7 @@ class BytecodeArrayBuilder final : private RegisterMover { ...@@ -360,8 +357,7 @@ class BytecodeArrayBuilder final : private RegisterMover {
int parameter_count_; int parameter_count_;
int local_register_count_; int local_register_count_;
int context_register_count_; int context_register_count_;
int temporary_register_count_; TemporaryRegisterAllocator temporary_allocator_;
ZoneSet<int> free_temporaries_;
RegisterTranslator register_translator_; RegisterTranslator register_translator_;
DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBuilder); DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBuilder);
......
...@@ -89,15 +89,27 @@ Register BytecodeArrayIterator::GetRegisterOperand(int operand_index) const { ...@@ -89,15 +89,27 @@ Register BytecodeArrayIterator::GetRegisterOperand(int operand_index) const {
Bytecodes::GetOperandType(current_bytecode(), operand_index); Bytecodes::GetOperandType(current_bytecode(), operand_index);
DCHECK(Bytecodes::IsRegisterOperandType(operand_type)); DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
uint32_t operand = GetRawOperand(operand_index, operand_type); uint32_t operand = GetRawOperand(operand_index, operand_type);
Register reg;
switch (Bytecodes::GetOperandSize(current_bytecode(), operand_index)) { switch (Bytecodes::GetOperandSize(current_bytecode(), operand_index)) {
case OperandSize::kByte: case OperandSize::kByte:
return Register::FromOperand(static_cast<uint8_t>(operand)); reg = Register::FromOperand(static_cast<uint8_t>(operand));
break;
case OperandSize::kShort: case OperandSize::kShort:
return Register::FromWideOperand(static_cast<uint16_t>(operand)); reg = Register::FromWideOperand(static_cast<uint16_t>(operand));
break;
case OperandSize::kNone: case OperandSize::kNone:
UNREACHABLE(); UNREACHABLE();
reg = Register::invalid_value();
break;
} }
return Register(); DCHECK_GE(reg.index(),
Register::FromParameterIndex(0, bytecode_array()->parameter_count())
.index());
DCHECK(reg.index() < bytecode_array()->register_count() ||
(reg.index() == 0 &&
Bytecodes::IsMaybeRegisterOperandType(
Bytecodes::GetOperandType(current_bytecode(), operand_index))));
return reg;
} }
int BytecodeArrayIterator::GetRegisterOperandRange(int operand_index) const { int BytecodeArrayIterator::GetRegisterOperandRange(int operand_index) const {
...@@ -121,8 +133,7 @@ int BytecodeArrayIterator::GetRegisterOperandRange(int operand_index) const { ...@@ -121,8 +133,7 @@ int BytecodeArrayIterator::GetRegisterOperandRange(int operand_index) const {
// reciever. // reciever.
OperandType next_operand_type = OperandType next_operand_type =
Bytecodes::GetOperandType(current_bytecode(), operand_index + 1); Bytecodes::GetOperandType(current_bytecode(), operand_index + 1);
if (next_operand_type == OperandType::kRegCount8 || if (Bytecodes::IsRegisterCountOperandType(next_operand_type)) {
next_operand_type == OperandType::kRegCount16) {
return GetCountOperand(operand_index + 1); return GetCountOperand(operand_index + 1);
} }
} }
......
...@@ -373,7 +373,8 @@ class BytecodeGenerator::RegisterAllocationScope { ...@@ -373,7 +373,8 @@ class BytecodeGenerator::RegisterAllocationScope {
explicit RegisterAllocationScope(BytecodeGenerator* generator) explicit RegisterAllocationScope(BytecodeGenerator* generator)
: generator_(generator), : generator_(generator),
outer_(generator->register_allocator()), outer_(generator->register_allocator()),
allocator_(builder()) { allocator_(builder()->zone(),
builder()->temporary_register_allocator()) {
generator_->set_register_allocator(this); generator_->set_register_allocator(this);
} }
...@@ -395,11 +396,11 @@ class BytecodeGenerator::RegisterAllocationScope { ...@@ -395,11 +396,11 @@ class BytecodeGenerator::RegisterAllocationScope {
// walk the full context chain and compute the list of consecutive // walk the full context chain and compute the list of consecutive
// reservations in the innerscopes. // reservations in the innerscopes.
UNIMPLEMENTED(); UNIMPLEMENTED();
return Register(-1); return Register::invalid_value();
} }
} }
void PrepareForConsecutiveAllocations(size_t count) { void PrepareForConsecutiveAllocations(int count) {
allocator_.PrepareForConsecutiveAllocations(count); allocator_.PrepareForConsecutiveAllocations(count);
} }
...@@ -520,7 +521,7 @@ class BytecodeGenerator::RegisterResultScope final ...@@ -520,7 +521,7 @@ class BytecodeGenerator::RegisterResultScope final
virtual void SetResultInRegister(Register reg) { virtual void SetResultInRegister(Register reg) {
DCHECK(builder()->RegisterIsParameterOrLocal(reg) || DCHECK(builder()->RegisterIsParameterOrLocal(reg) ||
(builder()->RegisterIsTemporary(reg) && (builder()->TemporaryRegisterIsLive(reg) &&
!allocator()->RegisterIsAllocatedInThisScope(reg))); !allocator()->RegisterIsAllocatedInThisScope(reg)));
result_register_ = reg; result_register_ = reg;
set_result_identified(); set_result_identified();
...@@ -532,11 +533,10 @@ class BytecodeGenerator::RegisterResultScope final ...@@ -532,11 +533,10 @@ class BytecodeGenerator::RegisterResultScope final
Register result_register_; Register result_register_;
}; };
BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone)
: isolate_(isolate), : isolate_(isolate),
zone_(zone), zone_(zone),
builder_(isolate, zone), builder_(nullptr),
info_(nullptr), info_(nullptr),
scope_(nullptr), scope_(nullptr),
globals_(0, zone), globals_(0, zone),
...@@ -552,16 +552,17 @@ Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { ...@@ -552,16 +552,17 @@ Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
set_info(info); set_info(info);
set_scope(info->scope()); set_scope(info->scope());
// Initialize bytecode array builder.
set_builder(new (zone()) BytecodeArrayBuilder(
isolate(), zone(), info->num_parameters_including_this(),
scope()->MaxNestedContextChainLength(), scope()->num_stack_slots()));
// Initialize the incoming context. // Initialize the incoming context.
ContextScope incoming_context(this, scope(), false); ContextScope incoming_context(this, scope(), false);
// Initialize control scope. // Initialize control scope.
ControlScopeForTopLevel control(this); ControlScopeForTopLevel control(this);
builder()->set_parameter_count(info->num_parameters_including_this());
builder()->set_locals_count(scope()->num_stack_slots());
builder()->set_context_count(scope()->MaxNestedContextChainLength());
// Build function context only if there are context allocated variables. // Build function context only if there are context allocated variables.
if (scope()->NeedsContext()) { if (scope()->NeedsContext()) {
// Push a new inner context scope for the function. // Push a new inner context scope for the function.
...@@ -575,7 +576,7 @@ Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { ...@@ -575,7 +576,7 @@ Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
set_scope(nullptr); set_scope(nullptr);
set_info(nullptr); set_info(nullptr);
return builder_.ToBytecodeArray(); return builder()->ToBytecodeArray();
} }
......
...@@ -105,7 +105,8 @@ class BytecodeGenerator final : public AstVisitor { ...@@ -105,7 +105,8 @@ class BytecodeGenerator final : public AstVisitor {
void RecordStoreToRegister(Register reg); void RecordStoreToRegister(Register reg);
Register LoadFromAliasedRegister(Register reg); Register LoadFromAliasedRegister(Register reg);
inline BytecodeArrayBuilder* builder() { return &builder_; } inline void set_builder(BytecodeArrayBuilder* builder) { builder_ = builder; }
inline BytecodeArrayBuilder* builder() const { return builder_; }
inline Isolate* isolate() const { return isolate_; } inline Isolate* isolate() const { return isolate_; }
inline Zone* zone() const { return zone_; } inline Zone* zone() const { return zone_; }
...@@ -142,7 +143,7 @@ class BytecodeGenerator final : public AstVisitor { ...@@ -142,7 +143,7 @@ class BytecodeGenerator final : public AstVisitor {
Isolate* isolate_; Isolate* isolate_;
Zone* zone_; Zone* zone_;
BytecodeArrayBuilder builder_; BytecodeArrayBuilder* builder_;
CompilationInfo* info_; CompilationInfo* info_;
Scope* scope_; Scope* scope_;
ZoneVector<Handle<Object>> globals_; ZoneVector<Handle<Object>> globals_;
......
...@@ -10,17 +10,173 @@ namespace v8 { ...@@ -10,17 +10,173 @@ namespace v8 {
namespace internal { namespace internal {
namespace interpreter { namespace interpreter {
TemporaryRegisterAllocator::TemporaryRegisterAllocator(Zone* zone,
int allocation_base)
: free_temporaries_(zone),
allocation_base_(allocation_base),
allocation_count_(0) {}
Register TemporaryRegisterAllocator::first_temporary_register() const {
DCHECK(allocation_count() > 0);
return Register(allocation_base());
}
Register TemporaryRegisterAllocator::last_temporary_register() const {
DCHECK(allocation_count() > 0);
return Register(allocation_base() + allocation_count() - 1);
}
int TemporaryRegisterAllocator::AllocateTemporaryRegister() {
allocation_count_ += 1;
return allocation_base() + allocation_count() - 1;
}
int TemporaryRegisterAllocator::BorrowTemporaryRegister() {
if (free_temporaries_.empty()) {
return AllocateTemporaryRegister();
} else {
auto pos = free_temporaries_.begin();
int retval = *pos;
free_temporaries_.erase(pos);
return retval;
}
}
int TemporaryRegisterAllocator::BorrowTemporaryRegisterNotInRange(
int start_index, int end_index) {
if (free_temporaries_.empty()) {
int next_allocation = allocation_base() + allocation_count();
while (next_allocation >= start_index && next_allocation <= end_index) {
free_temporaries_.insert(AllocateTemporaryRegister());
next_allocation += 1;
}
return AllocateTemporaryRegister();
}
ZoneSet<int>::iterator index = free_temporaries_.lower_bound(start_index);
if (index == free_temporaries_.begin()) {
// If start_index is the first free register, check for a register
// greater than end_index.
index = free_temporaries_.upper_bound(end_index);
if (index == free_temporaries_.end()) {
return AllocateTemporaryRegister();
}
} else {
// If there is a free register < start_index
index--;
}
int retval = *index;
free_temporaries_.erase(index);
return retval;
}
int TemporaryRegisterAllocator::PrepareForConsecutiveTemporaryRegisters(
size_t count) {
if (count == 0) {
return -1;
}
// TODO(oth): replace use of set<> here for free_temporaries with a
// more efficient structure. And/or partition into two searches -
// one before the translation window and one after.
// A run will require at least |count| free temporaries.
while (free_temporaries_.size() < count) {
free_temporaries_.insert(AllocateTemporaryRegister());
}
// Search within existing temporaries for a run.
auto start = free_temporaries_.begin();
size_t run_length = 0;
for (auto run_end = start; run_end != free_temporaries_.end(); run_end++) {
int expected = *start + static_cast<int>(run_length);
if (*run_end != expected) {
start = run_end;
run_length = 0;
}
Register reg_start(*start);
Register reg_expected(expected);
if (RegisterTranslator::DistanceToTranslationWindow(reg_start) > 0 &&
RegisterTranslator::DistanceToTranslationWindow(reg_expected) <= 0) {
// Run straddles the lower edge of the translation window. Registers
// after the start of this boundary are displaced by the register
// translator to provide a hole for translation. Runs either side
// of the boundary are fine.
start = run_end;
run_length = 0;
}
if (++run_length == count) {
return *start;
}
}
// Continue run if possible across existing last temporary.
if (allocation_count_ > 0 && (start == free_temporaries_.end() ||
*start + static_cast<int>(run_length) !=
last_temporary_register().index() + 1)) {
run_length = 0;
}
// Pad temporaries if extended run would cross translation boundary.
Register reg_first(*start);
Register reg_last(*start + static_cast<int>(count) - 1);
DCHECK_GT(RegisterTranslator::DistanceToTranslationWindow(reg_first),
RegisterTranslator::DistanceToTranslationWindow(reg_last));
while (RegisterTranslator::DistanceToTranslationWindow(reg_first) > 0 &&
RegisterTranslator::DistanceToTranslationWindow(reg_last) <= 0) {
auto pos_insert_pair =
free_temporaries_.insert(AllocateTemporaryRegister());
reg_first = Register(*pos_insert_pair.first);
reg_last = Register(reg_first.index() + static_cast<int>(count) - 1);
run_length = 0;
}
// Ensure enough registers for run.
while (run_length++ < count) {
free_temporaries_.insert(AllocateTemporaryRegister());
}
int run_start =
last_temporary_register().index() - static_cast<int>(count) + 1;
DCHECK(RegisterTranslator::DistanceToTranslationWindow(Register(run_start)) <=
0 ||
RegisterTranslator::DistanceToTranslationWindow(
Register(run_start + static_cast<int>(count) - 1)) > 0);
return run_start;
}
bool TemporaryRegisterAllocator::RegisterIsLive(Register reg) const {
if (allocation_count_ > 0) {
DCHECK(reg >= first_temporary_register() &&
reg <= last_temporary_register());
return free_temporaries_.find(reg.index()) == free_temporaries_.end();
} else {
return false;
}
}
void TemporaryRegisterAllocator::BorrowConsecutiveTemporaryRegister(
int reg_index) {
DCHECK(free_temporaries_.find(reg_index) != free_temporaries_.end());
free_temporaries_.erase(reg_index);
}
void TemporaryRegisterAllocator::ReturnTemporaryRegister(int reg_index) {
DCHECK(free_temporaries_.find(reg_index) == free_temporaries_.end());
free_temporaries_.insert(reg_index);
}
BytecodeRegisterAllocator::BytecodeRegisterAllocator( BytecodeRegisterAllocator::BytecodeRegisterAllocator(
BytecodeArrayBuilder* builder) Zone* zone, TemporaryRegisterAllocator* allocator)
: builder_(builder), : base_allocator_(allocator),
allocated_(builder->zone()), allocated_(zone),
next_consecutive_register_(-1), next_consecutive_register_(-1),
next_consecutive_count_(-1) {} next_consecutive_count_(-1) {}
BytecodeRegisterAllocator::~BytecodeRegisterAllocator() { BytecodeRegisterAllocator::~BytecodeRegisterAllocator() {
for (auto i = allocated_.rbegin(); i != allocated_.rend(); i++) { for (auto i = allocated_.rbegin(); i != allocated_.rend(); i++) {
builder_->ReturnTemporaryRegister(*i); base_allocator()->ReturnTemporaryRegister(*i);
} }
allocated_.clear(); allocated_.clear();
} }
...@@ -29,9 +185,9 @@ BytecodeRegisterAllocator::~BytecodeRegisterAllocator() { ...@@ -29,9 +185,9 @@ BytecodeRegisterAllocator::~BytecodeRegisterAllocator() {
Register BytecodeRegisterAllocator::NewRegister() { Register BytecodeRegisterAllocator::NewRegister() {
int allocated = -1; int allocated = -1;
if (next_consecutive_count_ <= 0) { if (next_consecutive_count_ <= 0) {
allocated = builder_->BorrowTemporaryRegister(); allocated = base_allocator()->BorrowTemporaryRegister();
} else { } else {
allocated = builder_->BorrowTemporaryRegisterNotInRange( allocated = base_allocator()->BorrowTemporaryRegisterNotInRange(
next_consecutive_register_, next_consecutive_register_,
next_consecutive_register_ + next_consecutive_count_ - 1); next_consecutive_register_ + next_consecutive_count_ - 1);
} }
...@@ -52,7 +208,7 @@ bool BytecodeRegisterAllocator::RegisterIsAllocatedInThisScope( ...@@ -52,7 +208,7 @@ bool BytecodeRegisterAllocator::RegisterIsAllocatedInThisScope(
void BytecodeRegisterAllocator::PrepareForConsecutiveAllocations(size_t count) { void BytecodeRegisterAllocator::PrepareForConsecutiveAllocations(size_t count) {
if (static_cast<int>(count) > next_consecutive_count_) { if (static_cast<int>(count) > next_consecutive_count_) {
next_consecutive_register_ = next_consecutive_register_ =
builder_->PrepareForConsecutiveTemporaryRegisters(count); base_allocator()->PrepareForConsecutiveTemporaryRegisters(count);
next_consecutive_count_ = static_cast<int>(count); next_consecutive_count_ = static_cast<int>(count);
} }
} }
...@@ -61,7 +217,8 @@ void BytecodeRegisterAllocator::PrepareForConsecutiveAllocations(size_t count) { ...@@ -61,7 +217,8 @@ void BytecodeRegisterAllocator::PrepareForConsecutiveAllocations(size_t count) {
Register BytecodeRegisterAllocator::NextConsecutiveRegister() { Register BytecodeRegisterAllocator::NextConsecutiveRegister() {
DCHECK_GE(next_consecutive_register_, 0); DCHECK_GE(next_consecutive_register_, 0);
DCHECK_GT(next_consecutive_count_, 0); DCHECK_GT(next_consecutive_count_, 0);
builder_->BorrowConsecutiveTemporaryRegister(next_consecutive_register_); base_allocator()->BorrowConsecutiveTemporaryRegister(
next_consecutive_register_);
allocated_.push_back(next_consecutive_register_); allocated_.push_back(next_consecutive_register_);
next_consecutive_count_--; next_consecutive_count_--;
return Register(next_consecutive_register_++); return Register(next_consecutive_register_++);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef V8_INTERPRETER_BYTECODE_REGISTER_ALLOCATOR_H_ #ifndef V8_INTERPRETER_BYTECODE_REGISTER_ALLOCATOR_H_
#define V8_INTERPRETER_BYTECODE_REGISTER_ALLOCATOR_H_ #define V8_INTERPRETER_BYTECODE_REGISTER_ALLOCATOR_H_
#include "src/interpreter/bytecodes.h"
#include "src/zone-containers.h" #include "src/zone-containers.h"
namespace v8 { namespace v8 {
...@@ -14,11 +15,62 @@ namespace interpreter { ...@@ -14,11 +15,62 @@ namespace interpreter {
class BytecodeArrayBuilder; class BytecodeArrayBuilder;
class Register; class Register;
class TemporaryRegisterAllocator final {
public:
TemporaryRegisterAllocator(Zone* zone, int start_index);
// Borrow a temporary register.
int BorrowTemporaryRegister();
// Borrow a temporary register from the register range outside of
// |start_index| to |end_index|.
int BorrowTemporaryRegisterNotInRange(int start_index, int end_index);
// Return a temporary register when no longer used.
void ReturnTemporaryRegister(int reg_index);
// Ensure a run of consecutive registers is available. Each register in
// the range should be borrowed with BorrowConsecutiveTemporaryRegister().
// Returns the start index of the run.
int PrepareForConsecutiveTemporaryRegisters(size_t count);
// Borrow a register from a range prepared with
// PrepareForConsecutiveTemporaryRegisters().
void BorrowConsecutiveTemporaryRegister(int reg_index);
// Returns true if |reg| is a temporary register and is currently
// borrowed.
bool RegisterIsLive(Register reg) const;
// Returns the first register in the range of temporary registers.
Register first_temporary_register() const;
// Returns the last register in the range of temporary registers.
Register last_temporary_register() const;
// Returns the start index of temporary register allocations.
int allocation_base() const { return allocation_base_; }
// Returns the number of temporary register allocations made.
int allocation_count() const { return allocation_count_; }
private:
// Allocate a temporary register.
int AllocateTemporaryRegister();
ZoneSet<int> free_temporaries_;
int allocation_base_;
int allocation_count_;
DISALLOW_COPY_AND_ASSIGN(TemporaryRegisterAllocator);
};
// A class than allows the instantiator to allocate temporary registers that are // A class than allows the instantiator to allocate temporary registers that are
// cleaned up when scope is closed. // cleaned up when scope is closed.
class BytecodeRegisterAllocator { class BytecodeRegisterAllocator final {
public: public:
explicit BytecodeRegisterAllocator(BytecodeArrayBuilder* builder); explicit BytecodeRegisterAllocator(Zone* zone,
TemporaryRegisterAllocator* allocator);
~BytecodeRegisterAllocator(); ~BytecodeRegisterAllocator();
Register NewRegister(); Register NewRegister();
...@@ -30,10 +82,9 @@ class BytecodeRegisterAllocator { ...@@ -30,10 +82,9 @@ class BytecodeRegisterAllocator {
bool HasConsecutiveAllocations() const { return next_consecutive_count_ > 0; } bool HasConsecutiveAllocations() const { return next_consecutive_count_ > 0; }
private: private:
void* operator new(size_t size); TemporaryRegisterAllocator* base_allocator() const { return base_allocator_; }
void operator delete(void* p);
BytecodeArrayBuilder* builder_; TemporaryRegisterAllocator* base_allocator_;
ZoneVector<int> allocated_; ZoneVector<int> allocated_;
int next_consecutive_register_; int next_consecutive_register_;
int next_consecutive_count_; int next_consecutive_count_;
......
...@@ -262,6 +262,16 @@ bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) { ...@@ -262,6 +262,16 @@ bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) {
return bytecode == Bytecode::kReturn || IsJump(bytecode); return bytecode == Bytecode::kReturn || IsJump(bytecode);
} }
bool Bytecodes::IsMaybeRegisterOperandType(OperandType operand_type) {
return (operand_type == OperandType::kMaybeReg8 ||
operand_type == OperandType::kMaybeReg16);
}
bool Bytecodes::IsRegisterCountOperandType(OperandType operand_type) {
return (operand_type == OperandType::kRegCount8 ||
operand_type == OperandType::kRegCount16);
}
// static // static
bool Bytecodes::IsRegisterOperandType(OperandType operand_type) { bool Bytecodes::IsRegisterOperandType(OperandType operand_type) {
switch (operand_type) { switch (operand_type) {
......
...@@ -318,6 +318,9 @@ class Register { ...@@ -318,6 +318,9 @@ class Register {
static int MaxRegisterIndex(); static int MaxRegisterIndex();
static int MaxRegisterIndexForByteOperand(); static int MaxRegisterIndexForByteOperand();
// Returns an invalid register.
static Register invalid_value() { return Register(); }
// Returns the register for the function's closure object. // Returns the register for the function's closure object.
static Register function_closure(); static Register function_closure();
bool is_function_closure() const; bool is_function_closure() const;
...@@ -453,6 +456,14 @@ class Bytecodes { ...@@ -453,6 +456,14 @@ class Bytecodes {
// Returns true if the bytecode is a conditional jump, a jump, or a return. // Returns true if the bytecode is a conditional jump, a jump, or a return.
static bool IsJumpOrReturn(Bytecode bytecode); static bool IsJumpOrReturn(Bytecode bytecode);
// Returns true if |operand_type| is a maybe register operand
// (kMaybeReg8/kMaybeReg16).
static bool IsMaybeRegisterOperandType(OperandType operand_type);
// Returns true if |operand_type| is a register count operand
// (kRegCount8/kRegCount16).
static bool IsRegisterCountOperandType(OperandType operand_type);
// Returns true if |operand_type| is any type of register operand. // Returns true if |operand_type| is any type of register operand.
static bool IsRegisterOperandType(OperandType operand_type); static bool IsRegisterOperandType(OperandType operand_type);
......
...@@ -85,19 +85,19 @@ Handle<Object> ConstantArrayBuilder::At(size_t index) const { ...@@ -85,19 +85,19 @@ Handle<Object> ConstantArrayBuilder::At(size_t index) const {
} }
} }
Handle<FixedArray> ConstantArrayBuilder::ToFixedArray() {
Handle<FixedArray> ConstantArrayBuilder::ToFixedArray() const {
Handle<FixedArray> fixed_array = isolate_->factory()->NewFixedArray( Handle<FixedArray> fixed_array = isolate_->factory()->NewFixedArray(
static_cast<int>(size()), PretenureFlag::TENURED); static_cast<int>(size()), PretenureFlag::TENURED);
for (int i = 0; i < fixed_array->length(); i++) { for (int i = 0; i < fixed_array->length(); i++) {
fixed_array->set(i, *At(static_cast<size_t>(i))); fixed_array->set(i, *At(static_cast<size_t>(i)));
} }
constants_map()->Clear();
return fixed_array; return fixed_array;
} }
size_t ConstantArrayBuilder::Insert(Handle<Object> object) { size_t ConstantArrayBuilder::Insert(Handle<Object> object) {
index_t* entry = constants_map_.Find(object); index_t* entry = constants_map()->Find(object);
return (entry == nullptr) ? AllocateEntry(object) : *entry; return (entry == nullptr) ? AllocateEntry(object) : *entry;
} }
...@@ -106,7 +106,7 @@ ConstantArrayBuilder::index_t ConstantArrayBuilder::AllocateEntry( ...@@ -106,7 +106,7 @@ ConstantArrayBuilder::index_t ConstantArrayBuilder::AllocateEntry(
Handle<Object> object) { Handle<Object> object) {
DCHECK(!object->IsOddball()); DCHECK(!object->IsOddball());
size_t index; size_t index;
index_t* entry = constants_map_.Get(object); index_t* entry = constants_map()->Get(object);
if (idx8_slice_.available() > 0) { if (idx8_slice_.available() > 0) {
index = idx8_slice_.Allocate(object); index = idx8_slice_.Allocate(object);
} else { } else {
...@@ -136,7 +136,7 @@ size_t ConstantArrayBuilder::CommitReservedEntry(OperandSize operand_size, ...@@ -136,7 +136,7 @@ size_t ConstantArrayBuilder::CommitReservedEntry(OperandSize operand_size,
Handle<Object> object) { Handle<Object> object) {
DiscardReservedEntry(operand_size); DiscardReservedEntry(operand_size);
size_t index; size_t index;
index_t* entry = constants_map_.Find(object); index_t* entry = constants_map()->Find(object);
if (nullptr == entry) { if (nullptr == entry) {
index = AllocateEntry(object); index = AllocateEntry(object);
} else { } else {
......
...@@ -16,8 +16,11 @@ class Isolate; ...@@ -16,8 +16,11 @@ class Isolate;
namespace interpreter { namespace interpreter {
// A helper class for constructing constant arrays for the interpreter. // A helper class for constructing constant arrays for the
class ConstantArrayBuilder final : public ZoneObject { // interpreter. Each instance of this class is intended to be used to
// generate exactly one FixedArray of constants via the ToFixedArray
// method.
class ConstantArrayBuilder final BASE_EMBEDDED {
public: public:
// Capacity of the 8-bit operand slice. // Capacity of the 8-bit operand slice.
static const size_t kLowCapacity = 1u << kBitsPerByte; static const size_t kLowCapacity = 1u << kBitsPerByte;
...@@ -31,7 +34,7 @@ class ConstantArrayBuilder final : public ZoneObject { ...@@ -31,7 +34,7 @@ class ConstantArrayBuilder final : public ZoneObject {
ConstantArrayBuilder(Isolate* isolate, Zone* zone); ConstantArrayBuilder(Isolate* isolate, Zone* zone);
// Generate a fixed array of constants based on inserted objects. // Generate a fixed array of constants based on inserted objects.
Handle<FixedArray> ToFixedArray() const; Handle<FixedArray> ToFixedArray();
// Returns the object in the constant pool array that at index // Returns the object in the constant pool array that at index
// |index|. // |index|.
...@@ -83,6 +86,8 @@ class ConstantArrayBuilder final : public ZoneObject { ...@@ -83,6 +86,8 @@ class ConstantArrayBuilder final : public ZoneObject {
DISALLOW_COPY_AND_ASSIGN(ConstantArraySlice); DISALLOW_COPY_AND_ASSIGN(ConstantArraySlice);
}; };
IdentityMap<index_t>* constants_map() { return &constants_map_; }
Isolate* isolate_; Isolate* isolate_;
ConstantArraySlice idx8_slice_; ConstantArraySlice idx8_slice_;
ConstantArraySlice idx16_slice_; ConstantArraySlice idx16_slice_;
......
...@@ -2559,8 +2559,6 @@ TEST(BytecodeGraphBuilderForOf) { ...@@ -2559,8 +2559,6 @@ TEST(BytecodeGraphBuilderForOf) {
TEST(JumpWithConstantsAndWideConstants) { TEST(JumpWithConstantsAndWideConstants) {
HandleAndZoneScope scope;
auto isolate = scope.main_isolate();
const int kStep = 19; const int kStep = 19;
int start = 7; int start = 7;
for (int constants = start; constants < 256 + 3 * kStep; constants += kStep) { for (int constants = start; constants < 256 + 3 * kStep; constants += kStep) {
...@@ -2585,6 +2583,9 @@ TEST(JumpWithConstantsAndWideConstants) { ...@@ -2585,6 +2583,9 @@ TEST(JumpWithConstantsAndWideConstants) {
script_os << "}\n"; script_os << "}\n";
script_os << kFunctionName << "(0);\n"; script_os << kFunctionName << "(0);\n";
std::string script(script_os.str()); std::string script(script_os.str());
HandleAndZoneScope scope;
auto isolate = scope.main_isolate();
auto factory = isolate->factory(); auto factory = isolate->factory();
auto zone = scope.main_zone(); auto zone = scope.main_zone();
for (int a = 0; a < 3; a++) { for (int a = 0; a < 3; a++) {
......
...@@ -7276,9 +7276,6 @@ TEST(DeleteLookupSlotInEval) { ...@@ -7276,9 +7276,6 @@ TEST(DeleteLookupSlotInEval) {
} }
TEST(WideRegisters) { TEST(WideRegisters) {
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
// Prepare prologue that creates frame for lots of registers. // Prepare prologue that creates frame for lots of registers.
std::ostringstream os; std::ostringstream os;
for (size_t i = 0; i < 157; ++i) { for (size_t i = 0; i < 157; ++i) {
...@@ -7493,6 +7490,9 @@ TEST(WideRegisters) { ...@@ -7493,6 +7490,9 @@ TEST(WideRegisters) {
B(Return), // B(Return), //
}}}; }}};
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
for (size_t i = 0; i < arraysize(snippets); ++i) { for (size_t i = 0; i < arraysize(snippets); ++i) {
std::string body = prologue + snippets[i].code_snippet; std::string body = prologue + snippets[i].code_snippet;
Handle<BytecodeArray> bytecode_array = Handle<BytecodeArray> bytecode_array =
......
...@@ -163,10 +163,8 @@ TEST(InterpreterReturn) { ...@@ -163,10 +163,8 @@ TEST(InterpreterReturn) {
Handle<Object> undefined_value = Handle<Object> undefined_value =
handles.main_isolate()->factory()->undefined_value(); handles.main_isolate()->factory()->undefined_value();
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(0); 0, 0);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.Return(); builder.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
...@@ -182,10 +180,8 @@ TEST(InterpreterLoadUndefined) { ...@@ -182,10 +180,8 @@ TEST(InterpreterLoadUndefined) {
Handle<Object> undefined_value = Handle<Object> undefined_value =
handles.main_isolate()->factory()->undefined_value(); handles.main_isolate()->factory()->undefined_value();
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(0); 0, 0);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadUndefined().Return(); builder.LoadUndefined().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
...@@ -200,10 +196,8 @@ TEST(InterpreterLoadNull) { ...@@ -200,10 +196,8 @@ TEST(InterpreterLoadNull) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
Handle<Object> null_value = handles.main_isolate()->factory()->null_value(); Handle<Object> null_value = handles.main_isolate()->factory()->null_value();
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(0); 0, 0);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadNull().Return(); builder.LoadNull().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
...@@ -219,10 +213,8 @@ TEST(InterpreterLoadTheHole) { ...@@ -219,10 +213,8 @@ TEST(InterpreterLoadTheHole) {
Handle<Object> the_hole_value = Handle<Object> the_hole_value =
handles.main_isolate()->factory()->the_hole_value(); handles.main_isolate()->factory()->the_hole_value();
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(0); 0, 0);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadTheHole().Return(); builder.LoadTheHole().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
...@@ -237,10 +229,8 @@ TEST(InterpreterLoadTrue) { ...@@ -237,10 +229,8 @@ TEST(InterpreterLoadTrue) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
Handle<Object> true_value = handles.main_isolate()->factory()->true_value(); Handle<Object> true_value = handles.main_isolate()->factory()->true_value();
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(0); 0, 0);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadTrue().Return(); builder.LoadTrue().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
...@@ -255,10 +245,8 @@ TEST(InterpreterLoadFalse) { ...@@ -255,10 +245,8 @@ TEST(InterpreterLoadFalse) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
Handle<Object> false_value = handles.main_isolate()->factory()->false_value(); Handle<Object> false_value = handles.main_isolate()->factory()->false_value();
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(0); 0, 0);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadFalse().Return(); builder.LoadFalse().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
...@@ -275,10 +263,8 @@ TEST(InterpreterLoadLiteral) { ...@@ -275,10 +263,8 @@ TEST(InterpreterLoadLiteral) {
// Small Smis. // Small Smis.
for (int i = -128; i < 128; i++) { for (int i = -128; i < 128; i++) {
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(0); 0, 0);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadLiteral(Smi::FromInt(i)).Return(); builder.LoadLiteral(Smi::FromInt(i)).Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
...@@ -290,10 +276,8 @@ TEST(InterpreterLoadLiteral) { ...@@ -290,10 +276,8 @@ TEST(InterpreterLoadLiteral) {
// Large Smis. // Large Smis.
{ {
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(0); 0, 0);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadLiteral(Smi::FromInt(0x12345678)).Return(); builder.LoadLiteral(Smi::FromInt(0x12345678)).Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
...@@ -305,10 +289,8 @@ TEST(InterpreterLoadLiteral) { ...@@ -305,10 +289,8 @@ TEST(InterpreterLoadLiteral) {
// Heap numbers. // Heap numbers.
{ {
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(0); 0, 0);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadLiteral(factory->NewHeapNumber(-2.1e19)).Return(); builder.LoadLiteral(factory->NewHeapNumber(-2.1e19)).Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
...@@ -320,10 +302,8 @@ TEST(InterpreterLoadLiteral) { ...@@ -320,10 +302,8 @@ TEST(InterpreterLoadLiteral) {
// Strings. // Strings.
{ {
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(0); 0, 0);
builder.set_context_count(0);
builder.set_parameter_count(1);
Handle<i::String> string = factory->NewStringFromAsciiChecked("String"); Handle<i::String> string = factory->NewStringFromAsciiChecked("String");
builder.LoadLiteral(string).Return(); builder.LoadLiteral(string).Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
...@@ -340,10 +320,8 @@ TEST(InterpreterLoadStoreRegisters) { ...@@ -340,10 +320,8 @@ TEST(InterpreterLoadStoreRegisters) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
Handle<Object> true_value = handles.main_isolate()->factory()->true_value(); Handle<Object> true_value = handles.main_isolate()->factory()->true_value();
for (int i = 0; i <= kMaxInt8; i++) { for (int i = 0; i <= kMaxInt8; i++) {
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(i + 1); 0, i + 1);
builder.set_context_count(0);
builder.set_parameter_count(1);
Register reg(i); Register reg(i);
builder.LoadTrue() builder.LoadTrue()
.StoreAccumulatorInRegister(reg) .StoreAccumulatorInRegister(reg)
...@@ -426,10 +404,7 @@ TEST(InterpreterShiftOpsSmi) { ...@@ -426,10 +404,7 @@ TEST(InterpreterShiftOpsSmi) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory(); i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(), BytecodeArrayBuilder builder(handles.main_isolate(),
handles.main_zone()); handles.main_zone(), 1, 0, 1);
builder.set_locals_count(1);
builder.set_context_count(0);
builder.set_parameter_count(1);
Register reg(0); Register reg(0);
int lhs = lhs_inputs[l]; int lhs = lhs_inputs[l];
int rhs = rhs_inputs[r]; int rhs = rhs_inputs[r];
...@@ -461,10 +436,7 @@ TEST(InterpreterBinaryOpsSmi) { ...@@ -461,10 +436,7 @@ TEST(InterpreterBinaryOpsSmi) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory(); i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(), BytecodeArrayBuilder builder(handles.main_isolate(),
handles.main_zone()); handles.main_zone(), 1, 0, 1);
builder.set_locals_count(1);
builder.set_context_count(0);
builder.set_parameter_count(1);
Register reg(0); Register reg(0);
int lhs = lhs_inputs[l]; int lhs = lhs_inputs[l];
int rhs = rhs_inputs[r]; int rhs = rhs_inputs[r];
...@@ -497,10 +469,7 @@ TEST(InterpreterBinaryOpsHeapNumber) { ...@@ -497,10 +469,7 @@ TEST(InterpreterBinaryOpsHeapNumber) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory(); i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(), BytecodeArrayBuilder builder(handles.main_isolate(),
handles.main_zone()); handles.main_zone(), 1, 0, 1);
builder.set_locals_count(1);
builder.set_context_count(0);
builder.set_parameter_count(1);
Register reg(0); Register reg(0);
double lhs = lhs_inputs[l]; double lhs = lhs_inputs[l];
double rhs = rhs_inputs[r]; double rhs = rhs_inputs[r];
...@@ -556,10 +525,8 @@ TEST(InterpreterStringAdd) { ...@@ -556,10 +525,8 @@ TEST(InterpreterStringAdd) {
}; };
for (size_t i = 0; i < arraysize(test_cases); i++) { for (size_t i = 0; i < arraysize(test_cases); i++) {
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(1); 0, 1);
builder.set_context_count(0);
builder.set_parameter_count(1);
Register reg(0); Register reg(0);
builder.LoadLiteral(test_cases[i].lhs) builder.LoadLiteral(test_cases[i].lhs)
.StoreAccumulatorInRegister(reg) .StoreAccumulatorInRegister(reg)
...@@ -578,10 +545,8 @@ TEST(InterpreterStringAdd) { ...@@ -578,10 +545,8 @@ TEST(InterpreterStringAdd) {
TEST(InterpreterParameter1) { TEST(InterpreterParameter1) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(0); 0, 0);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadAccumulatorWithRegister(builder.Parameter(0)).Return(); builder.LoadAccumulatorWithRegister(builder.Parameter(0)).Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
...@@ -602,10 +567,8 @@ TEST(InterpreterParameter1) { ...@@ -602,10 +567,8 @@ TEST(InterpreterParameter1) {
TEST(InterpreterParameter8) { TEST(InterpreterParameter8) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 8,
builder.set_locals_count(0); 0, 0);
builder.set_context_count(0);
builder.set_parameter_count(8);
builder.LoadAccumulatorWithRegister(builder.Parameter(0)) builder.LoadAccumulatorWithRegister(builder.Parameter(0))
.BinaryOperation(Token::Value::ADD, builder.Parameter(1), Strength::WEAK) .BinaryOperation(Token::Value::ADD, builder.Parameter(1), Strength::WEAK)
.BinaryOperation(Token::Value::ADD, builder.Parameter(2), Strength::WEAK) .BinaryOperation(Token::Value::ADD, builder.Parameter(2), Strength::WEAK)
...@@ -639,10 +602,8 @@ TEST(InterpreterParameter8) { ...@@ -639,10 +602,8 @@ TEST(InterpreterParameter8) {
TEST(InterpreterParameter1Assign) { TEST(InterpreterParameter1Assign) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(0); 0, 0);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadLiteral(Smi::FromInt(5)) builder.LoadLiteral(Smi::FromInt(5))
.StoreAccumulatorInRegister(builder.Parameter(0)) .StoreAccumulatorInRegister(builder.Parameter(0))
.LoadAccumulatorWithRegister(builder.Parameter(0)) .LoadAccumulatorWithRegister(builder.Parameter(0))
...@@ -769,10 +730,8 @@ TEST(InterpreterLoadNamedProperty) { ...@@ -769,10 +730,8 @@ TEST(InterpreterLoadNamedProperty) {
Handle<i::String> name = factory->NewStringFromAsciiChecked("val"); Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
name = factory->string_table()->LookupString(isolate, name); name = factory->string_table()->LookupString(isolate, name);
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(0); 0, 0);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot), builder.LoadNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot),
i::SLOPPY) i::SLOPPY)
.Return(); .Return();
...@@ -825,10 +784,8 @@ TEST(InterpreterLoadKeyedProperty) { ...@@ -825,10 +784,8 @@ TEST(InterpreterLoadKeyedProperty) {
Handle<i::String> key = factory->NewStringFromAsciiChecked("key"); Handle<i::String> key = factory->NewStringFromAsciiChecked("key");
key = factory->string_table()->LookupString(isolate, key); key = factory->string_table()->LookupString(isolate, key);
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(1); 0, 1);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadLiteral(key) builder.LoadLiteral(key)
.LoadKeyedProperty(builder.Parameter(0), vector->GetIndex(slot), .LoadKeyedProperty(builder.Parameter(0), vector->GetIndex(slot),
i::STRICT) i::STRICT)
...@@ -870,10 +827,8 @@ TEST(InterpreterStoreNamedProperty) { ...@@ -870,10 +827,8 @@ TEST(InterpreterStoreNamedProperty) {
Handle<i::String> name = factory->NewStringFromAsciiChecked("val"); Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
name = factory->string_table()->LookupString(isolate, name); name = factory->string_table()->LookupString(isolate, name);
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(0); 0, 0);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadLiteral(Smi::FromInt(999)) builder.LoadLiteral(Smi::FromInt(999))
.StoreNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot), .StoreNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot),
i::STRICT) i::STRICT)
...@@ -931,10 +886,8 @@ TEST(InterpreterStoreKeyedProperty) { ...@@ -931,10 +886,8 @@ TEST(InterpreterStoreKeyedProperty) {
Handle<i::String> name = factory->NewStringFromAsciiChecked("val"); Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
name = factory->string_table()->LookupString(isolate, name); name = factory->string_table()->LookupString(isolate, name);
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(1); 0, 1);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadLiteral(name) builder.LoadLiteral(name)
.StoreAccumulatorInRegister(Register(0)) .StoreAccumulatorInRegister(Register(0))
.LoadLiteral(Smi::FromInt(999)) .LoadLiteral(Smi::FromInt(999))
...@@ -984,10 +937,8 @@ TEST(InterpreterCall) { ...@@ -984,10 +937,8 @@ TEST(InterpreterCall) {
// Check with no args. // Check with no args.
{ {
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(1); 0, 1);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY) builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
.StoreAccumulatorInRegister(Register(0)) .StoreAccumulatorInRegister(Register(0))
.Call(Register(0), builder.Parameter(0), 0, 0) .Call(Register(0), builder.Parameter(0), 0, 0)
...@@ -1005,10 +956,8 @@ TEST(InterpreterCall) { ...@@ -1005,10 +956,8 @@ TEST(InterpreterCall) {
// Check that receiver is passed properly. // Check that receiver is passed properly.
{ {
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(1); 0, 1);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY) builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
.StoreAccumulatorInRegister(Register(0)) .StoreAccumulatorInRegister(Register(0))
.Call(Register(0), builder.Parameter(0), 0, 0) .Call(Register(0), builder.Parameter(0), 0, 0)
...@@ -1029,10 +978,8 @@ TEST(InterpreterCall) { ...@@ -1029,10 +978,8 @@ TEST(InterpreterCall) {
// Check with two parameters (+ receiver). // Check with two parameters (+ receiver).
{ {
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(4); 0, 4);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY) builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
.StoreAccumulatorInRegister(Register(0)) .StoreAccumulatorInRegister(Register(0))
.LoadAccumulatorWithRegister(builder.Parameter(0)) .LoadAccumulatorWithRegister(builder.Parameter(0))
...@@ -1058,10 +1005,8 @@ TEST(InterpreterCall) { ...@@ -1058,10 +1005,8 @@ TEST(InterpreterCall) {
// Check with 10 parameters (+ receiver). // Check with 10 parameters (+ receiver).
{ {
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(12); 0, 12);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY) builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
.StoreAccumulatorInRegister(Register(0)) .StoreAccumulatorInRegister(Register(0))
.LoadAccumulatorWithRegister(builder.Parameter(0)) .LoadAccumulatorWithRegister(builder.Parameter(0))
...@@ -1131,10 +1076,8 @@ static BytecodeArrayBuilder& IncrementRegister(BytecodeArrayBuilder& builder, ...@@ -1131,10 +1076,8 @@ static BytecodeArrayBuilder& IncrementRegister(BytecodeArrayBuilder& builder,
TEST(InterpreterJumps) { TEST(InterpreterJumps) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
builder.set_locals_count(2); 0, 2);
builder.set_context_count(0);
builder.set_parameter_count(0);
Register reg(0), scratch(1); Register reg(0), scratch(1);
BytecodeLabel label[3]; BytecodeLabel label[3];
...@@ -1160,10 +1103,8 @@ TEST(InterpreterJumps) { ...@@ -1160,10 +1103,8 @@ TEST(InterpreterJumps) {
TEST(InterpreterConditionalJumps) { TEST(InterpreterConditionalJumps) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
builder.set_locals_count(2); 0, 2);
builder.set_context_count(0);
builder.set_parameter_count(0);
Register reg(0), scratch(1); Register reg(0), scratch(1);
BytecodeLabel label[2]; BytecodeLabel label[2];
BytecodeLabel done, done1; BytecodeLabel done, done1;
...@@ -1196,10 +1137,8 @@ TEST(InterpreterConditionalJumps) { ...@@ -1196,10 +1137,8 @@ TEST(InterpreterConditionalJumps) {
TEST(InterpreterConditionalJumps2) { TEST(InterpreterConditionalJumps2) {
// TODO(oth): Add tests for all conditional jumps near and far. // TODO(oth): Add tests for all conditional jumps near and far.
HandleAndZoneScope handles; HandleAndZoneScope handles;
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
builder.set_locals_count(2); 0, 2);
builder.set_context_count(0);
builder.set_parameter_count(0);
Register reg(0), scratch(1); Register reg(0), scratch(1);
BytecodeLabel label[2]; BytecodeLabel label[2];
BytecodeLabel done, done1; BytecodeLabel done, done1;
...@@ -1284,11 +1223,8 @@ TEST(InterpreterSmiComparisons) { ...@@ -1284,11 +1223,8 @@ TEST(InterpreterSmiComparisons) {
for (size_t j = 0; j < arraysize(inputs); j++) { for (size_t j = 0; j < arraysize(inputs); j++) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
BytecodeArrayBuilder builder(handles.main_isolate(), BytecodeArrayBuilder builder(handles.main_isolate(),
handles.main_zone()); handles.main_zone(), 0, 0, 1);
Register r0(0); Register r0(0);
builder.set_locals_count(1);
builder.set_context_count(0);
builder.set_parameter_count(0);
builder.LoadLiteral(Smi::FromInt(inputs[i])) builder.LoadLiteral(Smi::FromInt(inputs[i]))
.StoreAccumulatorInRegister(r0) .StoreAccumulatorInRegister(r0)
.LoadLiteral(Smi::FromInt(inputs[j])) .LoadLiteral(Smi::FromInt(inputs[j]))
...@@ -1323,11 +1259,8 @@ TEST(InterpreterHeapNumberComparisons) { ...@@ -1323,11 +1259,8 @@ TEST(InterpreterHeapNumberComparisons) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory(); i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(), BytecodeArrayBuilder builder(handles.main_isolate(),
handles.main_zone()); handles.main_zone(), 0, 0, 1);
Register r0(0); Register r0(0);
builder.set_locals_count(1);
builder.set_context_count(0);
builder.set_parameter_count(0);
builder.LoadLiteral(factory->NewHeapNumber(inputs[i])) builder.LoadLiteral(factory->NewHeapNumber(inputs[i]))
.StoreAccumulatorInRegister(r0) .StoreAccumulatorInRegister(r0)
.LoadLiteral(factory->NewHeapNumber(inputs[j])) .LoadLiteral(factory->NewHeapNumber(inputs[j]))
...@@ -1359,11 +1292,8 @@ TEST(InterpreterStringComparisons) { ...@@ -1359,11 +1292,8 @@ TEST(InterpreterStringComparisons) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory(); i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(), BytecodeArrayBuilder builder(handles.main_isolate(),
handles.main_zone()); handles.main_zone(), 0, 0, 1);
Register r0(0); Register r0(0);
builder.set_locals_count(1);
builder.set_context_count(0);
builder.set_parameter_count(0);
builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs)) builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs))
.StoreAccumulatorInRegister(r0) .StoreAccumulatorInRegister(r0)
.LoadLiteral(factory->NewStringFromAsciiChecked(rhs)) .LoadLiteral(factory->NewStringFromAsciiChecked(rhs))
...@@ -1406,11 +1336,8 @@ TEST(InterpreterMixedComparisons) { ...@@ -1406,11 +1336,8 @@ TEST(InterpreterMixedComparisons) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory(); i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(), BytecodeArrayBuilder builder(handles.main_isolate(),
handles.main_zone()); handles.main_zone(), 0, 0, 1);
Register r0(0); Register r0(0);
builder.set_locals_count(1);
builder.set_context_count(0);
builder.set_parameter_count(0);
if (pass == 0) { if (pass == 0) {
// Comparison with HeapNumber on the lhs and String on the rhs // Comparison with HeapNumber on the lhs and String on the rhs
builder.LoadLiteral(factory->NewNumber(lhs)) builder.LoadLiteral(factory->NewNumber(lhs))
...@@ -1451,11 +1378,9 @@ TEST(InterpreterInstanceOf) { ...@@ -1451,11 +1378,9 @@ TEST(InterpreterInstanceOf) {
Handle<i::Object> cases[] = {Handle<i::Object>::cast(instance), other}; Handle<i::Object> cases[] = {Handle<i::Object>::cast(instance), other};
for (size_t i = 0; i < arraysize(cases); i++) { for (size_t i = 0; i < arraysize(cases); i++) {
bool expected_value = (i == 0); bool expected_value = (i == 0);
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
0, 1);
Register r0(0); Register r0(0);
builder.set_locals_count(1);
builder.set_context_count(0);
builder.set_parameter_count(0);
builder.LoadLiteral(cases[i]); builder.LoadLiteral(cases[i]);
builder.StoreAccumulatorInRegister(r0) builder.StoreAccumulatorInRegister(r0)
.LoadLiteral(func) .LoadLiteral(func)
...@@ -1482,11 +1407,9 @@ TEST(InterpreterTestIn) { ...@@ -1482,11 +1407,9 @@ TEST(InterpreterTestIn) {
const char* properties[] = {"length", "fuzzle", "x", "0"}; const char* properties[] = {"length", "fuzzle", "x", "0"};
for (size_t i = 0; i < arraysize(properties); i++) { for (size_t i = 0; i < arraysize(properties); i++) {
bool expected_value = (i == 0); bool expected_value = (i == 0);
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
0, 1);
Register r0(0); Register r0(0);
builder.set_locals_count(1);
builder.set_context_count(0);
builder.set_parameter_count(0);
builder.LoadLiteral(factory->NewStringFromAsciiChecked(properties[i])) builder.LoadLiteral(factory->NewStringFromAsciiChecked(properties[i]))
.StoreAccumulatorInRegister(r0) .StoreAccumulatorInRegister(r0)
.LoadLiteral(Handle<Object>::cast(array)) .LoadLiteral(Handle<Object>::cast(array))
...@@ -1507,11 +1430,9 @@ TEST(InterpreterUnaryNot) { ...@@ -1507,11 +1430,9 @@ TEST(InterpreterUnaryNot) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
for (size_t i = 1; i < 10; i++) { for (size_t i = 1; i < 10; i++) {
bool expected_value = ((i & 1) == 1); bool expected_value = ((i & 1) == 1);
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
0, 0);
Register r0(0); Register r0(0);
builder.set_locals_count(0);
builder.set_context_count(0);
builder.set_parameter_count(0);
builder.LoadFalse(); builder.LoadFalse();
for (size_t j = 0; j < i; j++) { for (size_t j = 0; j < i; j++) {
builder.LogicalNot(); builder.LogicalNot();
...@@ -1570,11 +1491,9 @@ TEST(InterpreterUnaryNotNonBoolean) { ...@@ -1570,11 +1491,9 @@ TEST(InterpreterUnaryNotNonBoolean) {
}; };
for (size_t i = 0; i < arraysize(object_type_tuples); i++) { for (size_t i = 0; i < arraysize(object_type_tuples); i++) {
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
0, 0);
Register r0(0); Register r0(0);
builder.set_locals_count(0);
builder.set_context_count(0);
builder.set_parameter_count(0);
LoadAny(&builder, factory, object_type_tuples[i].first); LoadAny(&builder, factory, object_type_tuples[i].first);
builder.LogicalNot(); builder.LogicalNot();
builder.Return(); builder.Return();
...@@ -1618,10 +1537,8 @@ TEST(InterpreterTypeof) { ...@@ -1618,10 +1537,8 @@ TEST(InterpreterTypeof) {
TEST(InterpreterCallRuntime) { TEST(InterpreterCallRuntime) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
builder.set_locals_count(2); 0, 2);
builder.set_context_count(0);
builder.set_parameter_count(1);
builder.LoadLiteral(Smi::FromInt(15)) builder.LoadLiteral(Smi::FromInt(15))
.StoreAccumulatorInRegister(Register(0)) .StoreAccumulatorInRegister(Register(0))
.LoadLiteral(Smi::FromInt(40)) .LoadLiteral(Smi::FromInt(40))
...@@ -3445,10 +3362,10 @@ TEST(InterpreterDeleteLookupSlot) { ...@@ -3445,10 +3362,10 @@ TEST(InterpreterDeleteLookupSlot) {
TEST(JumpWithConstantsAndWideConstants) { TEST(JumpWithConstantsAndWideConstants) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
auto isolate = handles.main_isolate();
auto factory = isolate->factory();
const int kStep = 13; const int kStep = 13;
for (int constants = 3; constants < 256 + 3 * kStep; constants += kStep) { for (int constants = 11; constants < 256 + 3 * kStep; constants += kStep) {
auto isolate = handles.main_isolate();
auto factory = isolate->factory();
std::ostringstream filler_os; std::ostringstream filler_os;
// Generate a string that consumes constant pool entries and // Generate a string that consumes constant pool entries and
// spread out branch distances in script below. // spread out branch distances in script below.
...@@ -3471,8 +3388,8 @@ TEST(JumpWithConstantsAndWideConstants) { ...@@ -3471,8 +3388,8 @@ TEST(JumpWithConstantsAndWideConstants) {
for (int a = 0; a < 3; a++) { for (int a = 0; a < 3; a++) {
InterpreterTester tester(handles.main_isolate(), script.c_str()); InterpreterTester tester(handles.main_isolate(), script.c_str());
auto callable = tester.GetCallable<Handle<Object>>(); auto callable = tester.GetCallable<Handle<Object>>();
Handle<Object> return_val = Handle<Object> argument = factory->NewNumberFromInt(a);
callable(factory->NewNumberFromInt(a)).ToHandleChecked(); Handle<Object> return_val = callable(argument).ToHandleChecked();
static const int results[] = {11, 12, 2}; static const int results[] = {11, 12, 2};
CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]); CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]);
} }
...@@ -3523,7 +3440,6 @@ TEST(InterpreterEval) { ...@@ -3523,7 +3440,6 @@ TEST(InterpreterEval) {
std::string source(InterpreterTester::SourceForBody(eval[i].first)); std::string source(InterpreterTester::SourceForBody(eval[i].first));
InterpreterTester tester(handles.main_isolate(), source.c_str()); InterpreterTester tester(handles.main_isolate(), source.c_str());
auto callable = tester.GetCallable<>(); auto callable = tester.GetCallable<>();
Handle<i::Object> return_value = callable().ToHandleChecked(); Handle<i::Object> return_value = callable().ToHandleChecked();
CHECK(return_value->SameValue(*eval[i].second)); CHECK(return_value->SameValue(*eval[i].second));
} }
......
...@@ -21,11 +21,8 @@ class BytecodeArrayBuilderTest : public TestWithIsolateAndZone { ...@@ -21,11 +21,8 @@ class BytecodeArrayBuilderTest : public TestWithIsolateAndZone {
TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
BytecodeArrayBuilder builder(isolate(), zone()); BytecodeArrayBuilder builder(isolate(), zone(), 0, 1, 131);
builder.set_locals_count(131);
builder.set_context_count(1);
builder.set_parameter_count(0);
CHECK_EQ(builder.locals_count(), 131); CHECK_EQ(builder.locals_count(), 131);
CHECK_EQ(builder.context_count(), 1); CHECK_EQ(builder.context_count(), 1);
CHECK_EQ(builder.fixed_register_count(), 132); CHECK_EQ(builder.fixed_register_count(), 132);
...@@ -312,12 +309,9 @@ TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) { ...@@ -312,12 +309,9 @@ TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) {
for (int locals = 0; locals < 5; locals++) { for (int locals = 0; locals < 5; locals++) {
for (int contexts = 0; contexts < 4; contexts++) { for (int contexts = 0; contexts < 4; contexts++) {
for (int temps = 0; temps < 3; temps++) { for (int temps = 0; temps < 3; temps++) {
BytecodeArrayBuilder builder(isolate(), zone()); BytecodeArrayBuilder builder(isolate(), zone(), 0, contexts, locals);
builder.set_parameter_count(0); BytecodeRegisterAllocator temporaries(
builder.set_locals_count(locals); zone(), builder.temporary_register_allocator());
builder.set_context_count(contexts);
BytecodeRegisterAllocator temporaries(&builder);
for (int i = 0; i < temps; i++) { for (int i = 0; i < temps; i++) {
builder.StoreAccumulatorInRegister(temporaries.NewRegister()); builder.StoreAccumulatorInRegister(temporaries.NewRegister());
} }
...@@ -348,11 +342,7 @@ TEST_F(BytecodeArrayBuilderTest, RegisterValues) { ...@@ -348,11 +342,7 @@ TEST_F(BytecodeArrayBuilderTest, RegisterValues) {
TEST_F(BytecodeArrayBuilderTest, Parameters) { TEST_F(BytecodeArrayBuilderTest, Parameters) {
BytecodeArrayBuilder builder(isolate(), zone()); BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 0);
builder.set_parameter_count(10);
builder.set_locals_count(0);
builder.set_context_count(0);
Register param0(builder.Parameter(0)); Register param0(builder.Parameter(0));
Register param9(builder.Parameter(9)); Register param9(builder.Parameter(9));
CHECK_EQ(param9.index() - param0.index(), 9); CHECK_EQ(param9.index() - param0.index(), 9);
...@@ -360,12 +350,9 @@ TEST_F(BytecodeArrayBuilderTest, Parameters) { ...@@ -360,12 +350,9 @@ TEST_F(BytecodeArrayBuilderTest, Parameters) {
TEST_F(BytecodeArrayBuilderTest, RegisterType) { TEST_F(BytecodeArrayBuilderTest, RegisterType) {
BytecodeArrayBuilder builder(isolate(), zone()); BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 3);
builder.set_parameter_count(10); BytecodeRegisterAllocator register_allocator(
builder.set_locals_count(3); zone(), builder.temporary_register_allocator());
builder.set_context_count(0);
BytecodeRegisterAllocator register_allocator(&builder);
Register temp0 = register_allocator.NewRegister(); Register temp0 = register_allocator.NewRegister();
Register param0(builder.Parameter(0)); Register param0(builder.Parameter(0));
Register param9(builder.Parameter(9)); Register param9(builder.Parameter(9));
...@@ -386,11 +373,7 @@ TEST_F(BytecodeArrayBuilderTest, RegisterType) { ...@@ -386,11 +373,7 @@ TEST_F(BytecodeArrayBuilderTest, RegisterType) {
TEST_F(BytecodeArrayBuilderTest, Constants) { TEST_F(BytecodeArrayBuilderTest, Constants) {
BytecodeArrayBuilder builder(isolate(), zone()); BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
builder.set_parameter_count(0);
builder.set_locals_count(0);
builder.set_context_count(0);
Factory* factory = isolate()->factory(); Factory* factory = isolate()->factory();
Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(3.14); Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(3.14);
Handle<HeapObject> heap_num_2 = factory->NewHeapNumber(5.2); Handle<HeapObject> heap_num_2 = factory->NewHeapNumber(5.2);
...@@ -412,11 +395,7 @@ TEST_F(BytecodeArrayBuilderTest, Constants) { ...@@ -412,11 +395,7 @@ TEST_F(BytecodeArrayBuilderTest, Constants) {
TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
static const int kFarJumpDistance = 256; static const int kFarJumpDistance = 256;
BytecodeArrayBuilder builder(isolate(), zone()); BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1);
builder.set_parameter_count(0);
builder.set_locals_count(1);
builder.set_context_count(0);
Register reg(0); Register reg(0);
BytecodeLabel far0, far1, far2, far3, far4; BytecodeLabel far0, far1, far2, far3, far4;
BytecodeLabel near0, near1, near2, near3, near4; BytecodeLabel near0, near1, near2, near3, near4;
...@@ -528,10 +507,7 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { ...@@ -528,10 +507,7 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
BytecodeArrayBuilder builder(isolate(), zone()); BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1);
builder.set_parameter_count(0);
builder.set_locals_count(1);
builder.set_context_count(0);
Register reg(0); Register reg(0);
BytecodeLabel label0, label1, label2, label3, label4; BytecodeLabel label0, label1, label2, label3, label4;
...@@ -624,10 +600,7 @@ TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { ...@@ -624,10 +600,7 @@ TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
TEST_F(BytecodeArrayBuilderTest, LabelReuse) { TEST_F(BytecodeArrayBuilderTest, LabelReuse) {
BytecodeArrayBuilder builder(isolate(), zone()); BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
builder.set_parameter_count(0);
builder.set_locals_count(0);
builder.set_context_count(0);
// Labels can only have 1 forward reference, but // Labels can only have 1 forward reference, but
// can be referred to mulitple times once bound. // can be referred to mulitple times once bound.
...@@ -655,16 +628,11 @@ TEST_F(BytecodeArrayBuilderTest, LabelReuse) { ...@@ -655,16 +628,11 @@ TEST_F(BytecodeArrayBuilderTest, LabelReuse) {
TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) { TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) {
static const int kRepeats = 3; static const int kRepeats = 3;
BytecodeArrayBuilder builder(isolate(), zone()); BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
builder.set_parameter_count(0);
builder.set_locals_count(0);
builder.set_context_count(0);
for (int i = 0; i < kRepeats; i++) { for (int i = 0; i < kRepeats; i++) {
BytecodeLabel label; BytecodeLabel label;
builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label); builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label);
} }
builder.Return(); builder.Return();
Handle<BytecodeArray> array = builder.ToBytecodeArray(); Handle<BytecodeArray> array = builder.ToBytecodeArray();
......
...@@ -22,11 +22,7 @@ class BytecodeArrayIteratorTest : public TestWithIsolateAndZone { ...@@ -22,11 +22,7 @@ class BytecodeArrayIteratorTest : public TestWithIsolateAndZone {
TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) { TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
// Use a builder to create an array with containing multiple bytecodes // Use a builder to create an array with containing multiple bytecodes
// with 0, 1 and 2 operands. // with 0, 1 and 2 operands.
BytecodeArrayBuilder builder(isolate(), zone()); BytecodeArrayBuilder builder(isolate(), zone(), 3, 2, 0);
builder.set_parameter_count(3);
builder.set_locals_count(2);
builder.set_context_count(0);
Factory* factory = isolate()->factory(); Factory* factory = isolate()->factory();
Handle<HeapObject> heap_num_0 = factory->NewHeapNumber(2.718); Handle<HeapObject> heap_num_0 = factory->NewHeapNumber(2.718);
Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(2147483647); Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(2147483647);
......
...@@ -12,51 +12,219 @@ namespace v8 { ...@@ -12,51 +12,219 @@ namespace v8 {
namespace internal { namespace internal {
namespace interpreter { namespace interpreter {
class TemporaryRegisterAllocatorTest : public TestWithIsolateAndZone {
public:
TemporaryRegisterAllocatorTest() : allocator_(zone(), 0) {}
~TemporaryRegisterAllocatorTest() override {}
TemporaryRegisterAllocator* allocator() { return &allocator_; }
private:
TemporaryRegisterAllocator allocator_;
};
TEST_F(TemporaryRegisterAllocatorTest, FirstAllocation) {
CHECK_EQ(allocator()->allocation_count(), 0);
int reg0_index = allocator()->BorrowTemporaryRegister();
CHECK_EQ(reg0_index, 0);
CHECK_EQ(allocator()->allocation_count(), 1);
CHECK(allocator()->RegisterIsLive(Register(reg0_index)));
allocator()->ReturnTemporaryRegister(reg0_index);
CHECK(!allocator()->RegisterIsLive(Register(reg0_index)));
CHECK_EQ(allocator()->allocation_count(), 1);
CHECK(allocator()->first_temporary_register() == Register(0));
CHECK(allocator()->last_temporary_register() == Register(0));
}
TEST_F(TemporaryRegisterAllocatorTest, SimpleAllocations) {
for (int i = 0; i < 13; i++) {
int reg_index = allocator()->BorrowTemporaryRegister();
CHECK_EQ(reg_index, i);
CHECK_EQ(allocator()->allocation_count(), i + 1);
}
for (int i = 0; i < 13; i++) {
CHECK(allocator()->RegisterIsLive(Register(i)));
allocator()->ReturnTemporaryRegister(i);
CHECK(!allocator()->RegisterIsLive(Register(i)));
int reg_index = allocator()->BorrowTemporaryRegister();
CHECK_EQ(reg_index, i);
CHECK_EQ(allocator()->allocation_count(), 13);
}
for (int i = 0; i < 13; i++) {
CHECK(allocator()->RegisterIsLive(Register(i)));
allocator()->ReturnTemporaryRegister(i);
CHECK(!allocator()->RegisterIsLive(Register(i)));
}
}
TEST_F(TemporaryRegisterAllocatorTest, SimpleRangeAllocation) {
static const int kRunLength = 7;
int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
CHECK(!allocator()->RegisterIsLive(Register(start)));
for (int i = 0; i < kRunLength; i++) {
CHECK(!allocator()->RegisterIsLive(Register(start + i)));
allocator()->BorrowConsecutiveTemporaryRegister(start + i);
CHECK(allocator()->RegisterIsLive(Register(start + i)));
}
}
TEST_F(TemporaryRegisterAllocatorTest, RangeAllocationAbuttingFree) {
static const int kFreeCount = 3;
static const int kRunLength = 6;
for (int i = 0; i < kFreeCount; i++) {
int to_free = allocator()->BorrowTemporaryRegister();
CHECK_EQ(to_free, i);
}
for (int i = 0; i < kFreeCount; i++) {
allocator()->ReturnTemporaryRegister(i);
}
int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
CHECK(!allocator()->RegisterIsLive(Register(start)));
for (int i = 0; i < kRunLength; i++) {
CHECK(!allocator()->RegisterIsLive(Register(start + i)));
allocator()->BorrowConsecutiveTemporaryRegister(start + i);
CHECK(allocator()->RegisterIsLive(Register(start + i)));
}
}
TEST_F(TemporaryRegisterAllocatorTest, RangeAllocationAbuttingHole) {
static const int kPreAllocatedCount = 7;
static const int kPreAllocatedFreeCount = 6;
static const int kRunLength = 8;
for (int i = 0; i < kPreAllocatedCount; i++) {
int to_free = allocator()->BorrowTemporaryRegister();
CHECK_EQ(to_free, i);
}
for (int i = 0; i < kPreAllocatedFreeCount; i++) {
allocator()->ReturnTemporaryRegister(i);
}
int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
CHECK(!allocator()->RegisterIsLive(Register(start)));
CHECK_EQ(start, kPreAllocatedCount);
for (int i = 0; i < kRunLength; i++) {
CHECK(!allocator()->RegisterIsLive(Register(start + i)));
allocator()->BorrowConsecutiveTemporaryRegister(start + i);
CHECK(allocator()->RegisterIsLive(Register(start + i)));
}
}
TEST_F(TemporaryRegisterAllocatorTest, RangeAllocationAvailableInTemporaries) {
static const int kNotRunLength = 13;
static const int kRunLength = 8;
// Allocate big batch
for (int i = 0; i < kNotRunLength * 2 + kRunLength; i++) {
int allocated = allocator()->BorrowTemporaryRegister();
CHECK_EQ(allocated, i);
}
// Free every other register either side of target.
for (int i = 0; i < kNotRunLength; i++) {
if ((i & 2) == 1) {
allocator()->ReturnTemporaryRegister(i);
allocator()->ReturnTemporaryRegister(kNotRunLength + kRunLength + i);
}
}
// Free all registers for target.
for (int i = kNotRunLength; i < kNotRunLength + kRunLength; i++) {
allocator()->ReturnTemporaryRegister(i);
}
int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
CHECK_EQ(start, kNotRunLength);
for (int i = 0; i < kRunLength; i++) {
CHECK(!allocator()->RegisterIsLive(Register(start + i)));
allocator()->BorrowConsecutiveTemporaryRegister(start + i);
CHECK(allocator()->RegisterIsLive(Register(start + i)));
}
}
TEST_F(TemporaryRegisterAllocatorTest, RangeAvoidsTranslationBoundary) {
int boundary = RegisterTranslator::DistanceToTranslationWindow(Register(0));
int limit = boundary + 64;
for (int run_length = 2; run_length < 32; run_length += 7) {
ZoneVector<int> run_starts(zone());
for (int start = 0; start < limit; start += run_length) {
int run_start =
allocator()->PrepareForConsecutiveTemporaryRegisters(run_length);
run_starts.push_back(run_start);
for (int i = 0; i < run_length; i++) {
allocator()->BorrowConsecutiveTemporaryRegister(run_start + i);
}
CHECK(run_start >= boundary || run_start + run_length <= boundary);
}
for (size_t batch = 0; batch < run_starts.size(); batch++) {
for (int i = run_starts[batch]; i < run_starts[batch] + run_length; i++) {
allocator()->ReturnTemporaryRegister(i);
}
}
}
}
TEST_F(TemporaryRegisterAllocatorTest, NotInRange) {
for (int i = 0; i < 10; i++) {
int reg = allocator()->BorrowTemporaryRegisterNotInRange(2, 5);
CHECK(reg == i || (reg > 2 && reg == i + 4));
}
for (int i = 0; i < 10; i++) {
if (i < 2) {
allocator()->ReturnTemporaryRegister(i);
} else {
allocator()->ReturnTemporaryRegister(i + 4);
}
}
int reg0 = allocator()->BorrowTemporaryRegisterNotInRange(0, 3);
CHECK_EQ(reg0, 4);
int reg1 = allocator()->BorrowTemporaryRegisterNotInRange(3, 10);
CHECK_EQ(reg1, 2);
int reg2 = allocator()->BorrowTemporaryRegisterNotInRange(2, 6);
CHECK_EQ(reg2, 1);
allocator()->ReturnTemporaryRegister(reg0);
allocator()->ReturnTemporaryRegister(reg1);
allocator()->ReturnTemporaryRegister(reg2);
}
class BytecodeRegisterAllocatorTest : public TestWithIsolateAndZone { class BytecodeRegisterAllocatorTest : public TestWithIsolateAndZone {
public: public:
BytecodeRegisterAllocatorTest() {} BytecodeRegisterAllocatorTest() {}
~BytecodeRegisterAllocatorTest() override {} ~BytecodeRegisterAllocatorTest() override {}
}; };
TEST_F(BytecodeRegisterAllocatorTest, TemporariesRecycled) { TEST_F(BytecodeRegisterAllocatorTest, TemporariesRecycled) {
BytecodeArrayBuilder builder(isolate(), zone()); BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
builder.set_parameter_count(0);
builder.set_locals_count(0);
builder.set_context_count(0);
int first; int first;
{ {
BytecodeRegisterAllocator temporaries(&builder); BytecodeRegisterAllocator allocator(zone(),
first = temporaries.NewRegister().index(); builder.temporary_register_allocator());
temporaries.NewRegister(); first = allocator.NewRegister().index();
temporaries.NewRegister(); allocator.NewRegister();
temporaries.NewRegister(); allocator.NewRegister();
allocator.NewRegister();
} }
int second; int second;
{ {
BytecodeRegisterAllocator temporaries(&builder); BytecodeRegisterAllocator allocator(zone(),
second = temporaries.NewRegister().index(); builder.temporary_register_allocator());
second = allocator.NewRegister().index();
} }
CHECK_EQ(first, second); CHECK_EQ(first, second);
} }
TEST_F(BytecodeRegisterAllocatorTest, ConsecutiveRegisters) { TEST_F(BytecodeRegisterAllocatorTest, ConsecutiveRegisters) {
BytecodeArrayBuilder builder(isolate(), zone()); BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
builder.set_parameter_count(0); BytecodeRegisterAllocator allocator(zone(),
builder.set_locals_count(0); builder.temporary_register_allocator());
builder.set_context_count(0); allocator.PrepareForConsecutiveAllocations(4);
Register reg0 = allocator.NextConsecutiveRegister();
BytecodeRegisterAllocator temporaries(&builder); Register other = allocator.NewRegister();
temporaries.PrepareForConsecutiveAllocations(4); Register reg1 = allocator.NextConsecutiveRegister();
Register reg0 = temporaries.NextConsecutiveRegister(); Register reg2 = allocator.NextConsecutiveRegister();
Register other = temporaries.NewRegister(); Register reg3 = allocator.NextConsecutiveRegister();
Register reg1 = temporaries.NextConsecutiveRegister();
Register reg2 = temporaries.NextConsecutiveRegister();
Register reg3 = temporaries.NextConsecutiveRegister();
USE(other); USE(other);
CHECK(Register::AreContiguous(reg0, reg1, reg2, reg3)); CHECK(Register::AreContiguous(reg0, reg1, reg2, reg3));
......
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