| Index: src/interpreter/bytecode-generator.cc
|
| diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
|
| index 268b9fd79a1282e64e661dfc28222b309fcc646d..959e15514976132c32a0292e367ba17ea3b23d5e 100644
|
| --- a/src/interpreter/bytecode-generator.cc
|
| +++ b/src/interpreter/bytecode-generator.cc
|
| @@ -6,6 +6,7 @@
|
|
|
| #include "src/ast/scopes.h"
|
| #include "src/compiler.h"
|
| +#include "src/interpreter/bytecode-register-allocator.h"
|
| #include "src/interpreter/control-flow-builders.h"
|
| #include "src/objects.h"
|
| #include "src/parsing/parser.h"
|
| @@ -177,39 +178,24 @@ void BytecodeGenerator::ControlScope::PerformCommand(Command command,
|
| }
|
|
|
|
|
| -// Scoped base class for determining where the result of an expression
|
| -// is stored.
|
| -class BytecodeGenerator::ExpressionResultScope {
|
| +class BytecodeGenerator::RegisterAllocationScope {
|
| public:
|
| - ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind)
|
| + explicit RegisterAllocationScope(BytecodeGenerator* generator)
|
| : generator_(generator),
|
| - kind_(kind),
|
| - outer_(generator->execution_result()),
|
| - allocator_(builder()),
|
| - result_identified_(false) {
|
| - generator_->set_execution_result(this);
|
| + outer_(generator->register_allocator()),
|
| + allocator_(builder()) {
|
| + generator_->set_register_allocator(this);
|
| }
|
|
|
| - virtual ~ExpressionResultScope() {
|
| - generator_->set_execution_result(outer_);
|
| - DCHECK(result_identified());
|
| + virtual ~RegisterAllocationScope() {
|
| + generator_->set_register_allocator(outer_);
|
| }
|
|
|
| - bool IsEffect() const { return kind_ == Expression::kEffect; }
|
| - bool IsValue() const { return kind_ == Expression::kValue; }
|
| -
|
| - virtual void SetResultInAccumulator() = 0;
|
| - virtual void SetResultInRegister(Register reg) = 0;
|
| -
|
| - BytecodeGenerator* generator() const { return generator_; }
|
| - BytecodeArrayBuilder* builder() const { return generator()->builder(); }
|
| - ExpressionResultScope* outer() const { return outer_; }
|
| -
|
| Register NewRegister() {
|
| - ExpressionResultScope* current_scope = generator()->execution_result();
|
| + RegisterAllocationScope* current_scope = generator()->register_allocator();
|
| if ((current_scope == this) ||
|
| (current_scope->outer() == this &&
|
| - !current_scope->allocator_.hasConsecutiveAllocations())) {
|
| + !current_scope->allocator_.HasConsecutiveAllocations())) {
|
| // Regular case - Allocating registers in current or outer context.
|
| // VisitForRegisterValue allocates register in outer context.
|
| return allocator_.NewRegister();
|
| @@ -231,7 +217,53 @@ class BytecodeGenerator::ExpressionResultScope {
|
| return allocator_.NextConsecutiveRegister();
|
| }
|
|
|
| + bool RegisterIsAllocatedInThisScope(Register reg) const {
|
| + return allocator_.RegisterIsAllocatedInThisScope(reg);
|
| + }
|
| +
|
| + RegisterAllocationScope* outer() const { return outer_; }
|
| +
|
| + private:
|
| + BytecodeGenerator* generator() const { return generator_; }
|
| + BytecodeArrayBuilder* builder() const { return generator_->builder(); }
|
| +
|
| + BytecodeGenerator* generator_;
|
| + RegisterAllocationScope* outer_;
|
| + BytecodeRegisterAllocator allocator_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope);
|
| +};
|
| +
|
| +
|
| +// Scoped base class for determining where the result of an expression
|
| +// is stored.
|
| +class BytecodeGenerator::ExpressionResultScope {
|
| + public:
|
| + ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind)
|
| + : generator_(generator),
|
| + kind_(kind),
|
| + outer_(generator->execution_result()),
|
| + allocator_(generator),
|
| + result_identified_(false) {
|
| + generator_->set_execution_result(this);
|
| + }
|
| +
|
| + virtual ~ExpressionResultScope() {
|
| + generator_->set_execution_result(outer_);
|
| + DCHECK(result_identified());
|
| + }
|
| +
|
| + bool IsEffect() const { return kind_ == Expression::kEffect; }
|
| + bool IsValue() const { return kind_ == Expression::kValue; }
|
| +
|
| + virtual void SetResultInAccumulator() = 0;
|
| + virtual void SetResultInRegister(Register reg) = 0;
|
| +
|
| protected:
|
| + ExpressionResultScope* outer() const { return outer_; }
|
| + BytecodeArrayBuilder* builder() const { return generator_->builder(); }
|
| + const RegisterAllocationScope* allocator() const { return &allocator_; }
|
| +
|
| void set_result_identified() {
|
| DCHECK(!result_identified());
|
| result_identified_ = true;
|
| @@ -239,13 +271,11 @@ class BytecodeGenerator::ExpressionResultScope {
|
|
|
| bool result_identified() const { return result_identified_; }
|
|
|
| - const TemporaryRegisterScope* allocator() const { return &allocator_; }
|
| -
|
| private:
|
| BytecodeGenerator* generator_;
|
| Expression::Context kind_;
|
| ExpressionResultScope* outer_;
|
| - TemporaryRegisterScope allocator_;
|
| + RegisterAllocationScope allocator_;
|
| bool result_identified_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope);
|
| @@ -293,7 +323,7 @@ class BytecodeGenerator::RegisterResultScope final
|
| : ExpressionResultScope(generator, Expression::kValue) {}
|
|
|
| virtual void SetResultInAccumulator() {
|
| - result_register_ = outer()->NewRegister();
|
| + result_register_ = allocator()->outer()->NewRegister();
|
| builder()->StoreAccumulatorInRegister(result_register_);
|
| set_result_identified();
|
| }
|
| @@ -322,7 +352,8 @@ BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone)
|
| globals_(0, zone),
|
| execution_control_(nullptr),
|
| execution_context_(nullptr),
|
| - execution_result_(nullptr) {
|
| + execution_result_(nullptr),
|
| + register_allocator_(nullptr) {
|
| InitializeAstVisitor(isolate);
|
| }
|
|
|
| @@ -500,6 +531,7 @@ void BytecodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) {
|
|
|
| void BytecodeGenerator::VisitDeclarations(
|
| ZoneList<Declaration*>* declarations) {
|
| + RegisterAllocationScope register_scope(this);
|
| DCHECK(globals()->empty());
|
| AstVisitor::VisitDeclarations(declarations);
|
| if (globals()->empty()) return;
|
| @@ -511,12 +543,11 @@ void BytecodeGenerator::VisitDeclarations(
|
| DeclareGlobalsNativeFlag::encode(info()->is_native()) |
|
| DeclareGlobalsLanguageMode::encode(language_mode());
|
|
|
| - TemporaryRegisterScope temporary_register_scope(builder());
|
| - Register pairs = temporary_register_scope.NewRegister();
|
| + Register pairs = register_allocator()->NewRegister();
|
| builder()->LoadLiteral(data);
|
| builder()->StoreAccumulatorInRegister(pairs);
|
|
|
| - Register flags = temporary_register_scope.NewRegister();
|
| + Register flags = register_allocator()->NewRegister();
|
| builder()->LoadLiteral(Smi::FromInt(encoded_flags));
|
| builder()->StoreAccumulatorInRegister(flags);
|
| DCHECK(flags.index() == pairs.index() + 1);
|
| @@ -526,8 +557,18 @@ void BytecodeGenerator::VisitDeclarations(
|
| }
|
|
|
|
|
| +void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
|
| + for (int i = 0; i < statements->length(); i++) {
|
| + // Allocate an outer register allocations scope for the statement.
|
| + RegisterAllocationScope allocation_scope(this);
|
| + Statement* stmt = statements->at(i);
|
| + Visit(stmt);
|
| + if (stmt->IsJump()) break;
|
| + }
|
| +}
|
| +
|
| +
|
| void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
|
| - EffectResultScope statement_result_scope(this);
|
| VisitForEffect(stmt->expression());
|
| }
|
|
|
| @@ -582,7 +623,6 @@ void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
|
|
|
|
|
| void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
|
| - EffectResultScope statement_result_scope(this);
|
| VisitForAccumulatorValue(stmt->expression());
|
| builder()->Return();
|
| }
|
| @@ -596,7 +636,6 @@ void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
|
| void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
| // We need this scope because we visit for register values. We have to
|
| // maintain a execution result scope where registers can be allocated.
|
| - EffectResultScope effect_results_scope(this);
|
| ZoneList<CaseClause*>* clauses = stmt->cases();
|
| SwitchBuilder switch_builder(builder(), clauses->length());
|
| ControlScopeForBreakable scope(this, stmt, &switch_builder);
|
| @@ -735,8 +774,8 @@ void BytecodeGenerator::VisitForInAssignment(Expression* expr,
|
| break;
|
| }
|
| case NAMED_PROPERTY: {
|
| - TemporaryRegisterScope temporary_register_scope(builder());
|
| - Register value = temporary_register_scope.NewRegister();
|
| + RegisterAllocationScope register_scope(this);
|
| + Register value = register_allocator()->NewRegister();
|
| builder()->StoreAccumulatorInRegister(value);
|
| Register object = VisitForRegisterValue(property->obj());
|
| Handle<String> name = property->key()->AsLiteral()->AsPropertyName();
|
| @@ -746,8 +785,8 @@ void BytecodeGenerator::VisitForInAssignment(Expression* expr,
|
| break;
|
| }
|
| case KEYED_PROPERTY: {
|
| - TemporaryRegisterScope temporary_register_scope(builder());
|
| - Register value = temporary_register_scope.NewRegister();
|
| + RegisterAllocationScope register_scope(this);
|
| + Register value = register_allocator()->NewRegister();
|
| builder()->StoreAccumulatorInRegister(value);
|
| Register object = VisitForRegisterValue(property->obj());
|
| Register key = VisitForRegisterValue(property->key());
|
| @@ -764,7 +803,6 @@ void BytecodeGenerator::VisitForInAssignment(Expression* expr,
|
|
|
|
|
| void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
| - EffectResultScope statement_result_scope(this);
|
| if (stmt->subject()->IsNullLiteral() ||
|
| stmt->subject()->IsUndefinedLiteral(isolate())) {
|
| // ForIn generates lots of code, skip if it wouldn't produce any effects.
|
| @@ -779,17 +817,17 @@ void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
| VisitForAccumulatorValue(stmt->subject());
|
| builder()->JumpIfUndefined(&subject_undefined_label);
|
| builder()->JumpIfNull(&subject_null_label);
|
| - Register receiver = execution_result()->NewRegister();
|
| + Register receiver = register_allocator()->NewRegister();
|
| builder()->CastAccumulatorToJSObject();
|
| builder()->JumpIfNull(¬_object_label);
|
| builder()->StoreAccumulatorInRegister(receiver);
|
| - Register cache_type = execution_result()->NewRegister();
|
| - Register cache_array = execution_result()->NewRegister();
|
| - Register cache_length = execution_result()->NewRegister();
|
| + Register cache_type = register_allocator()->NewRegister();
|
| + Register cache_array = register_allocator()->NewRegister();
|
| + Register cache_length = register_allocator()->NewRegister();
|
| builder()->ForInPrepare(cache_type, cache_array, cache_length);
|
|
|
| // Set up loop counter
|
| - Register index = execution_result()->NewRegister();
|
| + Register index = register_allocator()->NewRegister();
|
| builder()->LoadLiteral(Smi::FromInt(0));
|
| builder()->StoreAccumulatorInRegister(index);
|
|
|
| @@ -915,7 +953,6 @@ void BytecodeGenerator::VisitLiteral(Literal* expr) {
|
|
|
| void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
|
| // Materialize a regular expression literal.
|
| - TemporaryRegisterScope temporary_register_scope(builder());
|
| builder()->CreateRegExpLiteral(expr->pattern(), expr->literal_index(),
|
| expr->flags());
|
| execution_result()->SetResultInAccumulator();
|
| @@ -927,8 +964,6 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
| builder()->CreateObjectLiteral(expr->constant_properties(),
|
| expr->literal_index(),
|
| expr->ComputeFlags(true));
|
| -
|
| - TemporaryRegisterScope temporary_register_scope(builder());
|
| Register literal;
|
|
|
| // Store computed values into the literal.
|
| @@ -936,17 +971,17 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
| int property_index = 0;
|
| AccessorTable accessor_table(zone());
|
| for (; property_index < expr->properties()->length(); property_index++) {
|
| - TemporaryRegisterScope inner_temporary_register_scope(builder());
|
| ObjectLiteral::Property* property = expr->properties()->at(property_index);
|
| if (property->is_computed_name()) break;
|
| if (property->IsCompileTimeValue()) continue;
|
|
|
| if (literal_in_accumulator) {
|
| - literal = temporary_register_scope.NewRegister();
|
| + literal = register_allocator()->NewRegister();
|
| builder()->StoreAccumulatorInRegister(literal);
|
| literal_in_accumulator = false;
|
| }
|
|
|
| + RegisterAllocationScope inner_register_scope(this);
|
| Literal* literal_key = property->key()->AsLiteral();
|
| switch (property->kind()) {
|
| case ObjectLiteral::Property::CONSTANT:
|
| @@ -967,16 +1002,13 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
| VisitForEffect(property->value());
|
| }
|
| } else {
|
| - inner_temporary_register_scope.PrepareForConsecutiveAllocations(3);
|
| - Register key =
|
| - inner_temporary_register_scope.NextConsecutiveRegister();
|
| - Register value =
|
| - inner_temporary_register_scope.NextConsecutiveRegister();
|
| - Register language =
|
| - inner_temporary_register_scope.NextConsecutiveRegister();
|
| + register_allocator()->PrepareForConsecutiveAllocations(3);
|
| + Register key = register_allocator()->NextConsecutiveRegister();
|
| + Register value = register_allocator()->NextConsecutiveRegister();
|
| + Register language = register_allocator()->NextConsecutiveRegister();
|
| // TODO(oth): This is problematic - can't assume contiguous here.
|
| - // literal is allocated in temporary_register_scope, whereas
|
| - // key, value, language are in another.
|
| + // literal is allocated in outer register scope, whereas key, value,
|
| + // language are in another.
|
| DCHECK(Register::AreContiguous(literal, key, value, language));
|
| VisitForAccumulatorValue(property->key());
|
| builder()->StoreAccumulatorInRegister(key);
|
| @@ -993,10 +1025,9 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
| break;
|
| }
|
| case ObjectLiteral::Property::PROTOTYPE: {
|
| - inner_temporary_register_scope.PrepareForConsecutiveAllocations(1);
|
| + register_allocator()->PrepareForConsecutiveAllocations(1);
|
| DCHECK(property->emit_store());
|
| - Register value =
|
| - inner_temporary_register_scope.NextConsecutiveRegister();
|
| + Register value = register_allocator()->NextConsecutiveRegister();
|
| DCHECK(Register::AreContiguous(literal, value));
|
| VisitForAccumulatorValue(property->value());
|
| builder()->StoreAccumulatorInRegister(value).CallRuntime(
|
| @@ -1020,12 +1051,12 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
| // corresponding getters and setters.
|
| for (AccessorTable::Iterator it = accessor_table.begin();
|
| it != accessor_table.end(); ++it) {
|
| - TemporaryRegisterScope inner_temporary_register_scope(builder());
|
| - inner_temporary_register_scope.PrepareForConsecutiveAllocations(4);
|
| - Register name = inner_temporary_register_scope.NextConsecutiveRegister();
|
| - Register getter = inner_temporary_register_scope.NextConsecutiveRegister();
|
| - Register setter = inner_temporary_register_scope.NextConsecutiveRegister();
|
| - Register attr = inner_temporary_register_scope.NextConsecutiveRegister();
|
| + RegisterAllocationScope inner_register_scope(this);
|
| + register_allocator()->PrepareForConsecutiveAllocations(4);
|
| + Register name = register_allocator()->NextConsecutiveRegister();
|
| + Register getter = register_allocator()->NextConsecutiveRegister();
|
| + Register setter = register_allocator()->NextConsecutiveRegister();
|
| + Register attr = register_allocator()->NextConsecutiveRegister();
|
| DCHECK(Register::AreContiguous(literal, name, getter, setter, attr));
|
| VisitForAccumulatorValue(it->first);
|
| builder()->StoreAccumulatorInRegister(name);
|
| @@ -1047,19 +1078,17 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
| // compile them into a series of "SetOwnProperty" runtime calls. This will
|
| // preserve insertion order.
|
| for (; property_index < expr->properties()->length(); property_index++) {
|
| - ObjectLiteral::Property* property = expr->properties()->at(property_index);
|
| -
|
| if (literal_in_accumulator) {
|
| - temporary_register_scope.PrepareForConsecutiveAllocations(4);
|
| - literal = temporary_register_scope.NextConsecutiveRegister();
|
| + literal = register_allocator()->NewRegister();
|
| builder()->StoreAccumulatorInRegister(literal);
|
| literal_in_accumulator = false;
|
| }
|
|
|
| + ObjectLiteral::Property* property = expr->properties()->at(property_index);
|
| + RegisterAllocationScope inner_register_scope(this);
|
| if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
|
| DCHECK(property->emit_store());
|
| - TemporaryRegisterScope inner_temporary_register_scope(builder());
|
| - Register value = inner_temporary_register_scope.NewRegister();
|
| + Register value = register_allocator()->NewRegister();
|
| DCHECK(Register::AreContiguous(literal, value));
|
| VisitForAccumulatorValue(property->value());
|
| builder()->StoreAccumulatorInRegister(value).CallRuntime(
|
| @@ -1067,11 +1096,10 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
| continue;
|
| }
|
|
|
| - TemporaryRegisterScope inner_temporary_register_scope(builder());
|
| - inner_temporary_register_scope.PrepareForConsecutiveAllocations(3);
|
| - Register key = inner_temporary_register_scope.NextConsecutiveRegister();
|
| - Register value = inner_temporary_register_scope.NextConsecutiveRegister();
|
| - Register attr = inner_temporary_register_scope.NextConsecutiveRegister();
|
| + register_allocator()->PrepareForConsecutiveAllocations(3);
|
| + Register key = register_allocator()->NextConsecutiveRegister();
|
| + Register value = register_allocator()->NextConsecutiveRegister();
|
| + Register attr = register_allocator()->NextConsecutiveRegister();
|
| DCHECK(Register::AreContiguous(literal, key, value, attr));
|
|
|
| VisitForAccumulatorValue(property->key());
|
| @@ -1119,8 +1147,6 @@ void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
| builder()->CreateArrayLiteral(expr->constant_elements(),
|
| expr->literal_index(),
|
| expr->ComputeFlags(true));
|
| -
|
| - TemporaryRegisterScope temporary_register_scope(builder());
|
| Register index, literal;
|
|
|
| // Evaluate all the non-constant subexpressions and store them into the
|
| @@ -1136,8 +1162,8 @@ void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
| }
|
|
|
| if (literal_in_accumulator) {
|
| - index = temporary_register_scope.NewRegister();
|
| - literal = temporary_register_scope.NewRegister();
|
| + index = register_allocator()->NewRegister();
|
| + literal = register_allocator()->NewRegister();
|
| builder()->StoreAccumulatorInRegister(literal);
|
| literal_in_accumulator = false;
|
| }
|
| @@ -1196,7 +1222,7 @@ void BytecodeGenerator::VisitVariableLoad(Variable* variable,
|
| if (context) {
|
| context_reg = context->reg();
|
| } else {
|
| - context_reg = execution_result()->NewRegister();
|
| + context_reg = register_allocator()->NewRegister();
|
| // Walk the context chain to find the context at the given depth.
|
| // TODO(rmcilroy): Perform this work in a bytecode handler once we have
|
| // a generic mechanism for performing jumps in interpreter.cc.
|
| @@ -1271,8 +1297,8 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
|
| if (context) {
|
| context_reg = context->reg();
|
| } else {
|
| - Register value_temp = execution_result()->NewRegister();
|
| - context_reg = execution_result()->NewRegister();
|
| + Register value_temp = register_allocator()->NewRegister();
|
| + context_reg = register_allocator()->NewRegister();
|
| // Walk the context chain to find the context at the given depth.
|
| // TODO(rmcilroy): Perform this work in a bytecode handler once we have
|
| // a generic mechanism for performing jumps in interpreter.cc.
|
| @@ -1324,7 +1350,7 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
|
| if (expr->is_compound()) {
|
| // Use VisitForAccumulator and store to register so that the key is
|
| // still in the accumulator for loading the old value below.
|
| - key = execution_result()->NewRegister();
|
| + key = register_allocator()->NewRegister();
|
| VisitForAccumulatorValue(property->key());
|
| builder()->StoreAccumulatorInRegister(key);
|
| } else {
|
| @@ -1350,7 +1376,7 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
|
| }
|
| case NAMED_PROPERTY: {
|
| FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
|
| - old_value = execution_result()->NewRegister();
|
| + old_value = register_allocator()->NewRegister();
|
| builder()
|
| ->LoadNamedProperty(object, name, feedback_index(slot),
|
| language_mode())
|
| @@ -1361,7 +1387,7 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
|
| // Key is already in accumulator at this point due to evaluating the
|
| // LHS above.
|
| FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
|
| - old_value = execution_result()->NewRegister();
|
| + old_value = register_allocator()->NewRegister();
|
| builder()
|
| ->LoadKeyedProperty(object, feedback_index(slot), language_mode())
|
| .StoreAccumulatorInRegister(old_value);
|
| @@ -1467,16 +1493,16 @@ Register BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args) {
|
| // less calls to NextConsecutiveRegister(). Otherwise, the arguments
|
| // here will be consecutive, but they will not be consecutive with
|
| // earlier consecutive allocations made by the caller.
|
| - execution_result()->PrepareForConsecutiveAllocations(args->length());
|
| + register_allocator()->PrepareForConsecutiveAllocations(args->length());
|
|
|
| // Visit for first argument that goes into returned register
|
| - Register first_arg = execution_result()->NextConsecutiveRegister();
|
| + Register first_arg = register_allocator()->NextConsecutiveRegister();
|
| VisitForAccumulatorValue(args->at(0));
|
| builder()->StoreAccumulatorInRegister(first_arg);
|
|
|
| // Visit remaining arguments
|
| for (int i = 1; i < static_cast<int>(args->length()); i++) {
|
| - Register ith_arg = execution_result()->NextConsecutiveRegister();
|
| + Register ith_arg = register_allocator()->NextConsecutiveRegister();
|
| VisitForAccumulatorValue(args->at(i));
|
| builder()->StoreAccumulatorInRegister(ith_arg);
|
| DCHECK(ith_arg.index() - i == first_arg.index());
|
| @@ -1497,9 +1523,9 @@ void BytecodeGenerator::VisitCall(Call* expr) {
|
| // kLoadLookupSlot. Future optimizations could avoid this there are no
|
| // arguments or the receiver and arguments are already consecutive.
|
| ZoneList<Expression*>* args = expr->arguments();
|
| - execution_result()->PrepareForConsecutiveAllocations(args->length() + 2);
|
| - Register callee = execution_result()->NextConsecutiveRegister();
|
| - Register receiver = execution_result()->NextConsecutiveRegister();
|
| + register_allocator()->PrepareForConsecutiveAllocations(args->length() + 2);
|
| + Register callee = register_allocator()->NextConsecutiveRegister();
|
| + Register receiver = register_allocator()->NextConsecutiveRegister();
|
|
|
| switch (call_type) {
|
| case Call::NAMED_PROPERTY_CALL:
|
| @@ -1524,10 +1550,10 @@ void BytecodeGenerator::VisitCall(Call* expr) {
|
| case Call::LOOKUP_SLOT_CALL:
|
| case Call::POSSIBLY_EVAL_CALL: {
|
| if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) {
|
| - TemporaryRegisterScope temporary_register_scope(builder());
|
| - temporary_register_scope.PrepareForConsecutiveAllocations(2);
|
| - Register context = temporary_register_scope.NextConsecutiveRegister();
|
| - Register name = temporary_register_scope.NextConsecutiveRegister();
|
| + RegisterAllocationScope inner_register_scope(this);
|
| + register_allocator()->PrepareForConsecutiveAllocations(2);
|
| + Register context = register_allocator()->NextConsecutiveRegister();
|
| + Register name = register_allocator()->NextConsecutiveRegister();
|
|
|
| // Call LoadLookupSlot to get the callee and receiver.
|
| DCHECK(Register::AreContiguous(callee, receiver));
|
| @@ -1562,14 +1588,13 @@ void BytecodeGenerator::VisitCall(Call* expr) {
|
| // Resolve callee for a potential direct eval call. This block will mutate the
|
| // callee value.
|
| if (call_type == Call::POSSIBLY_EVAL_CALL && args->length() > 0) {
|
| - TemporaryRegisterScope temporary_register_scope(builder());
|
| - temporary_register_scope.PrepareForConsecutiveAllocations(5);
|
| - Register callee_for_eval =
|
| - temporary_register_scope.NextConsecutiveRegister();
|
| - Register source = temporary_register_scope.NextConsecutiveRegister();
|
| - Register function = temporary_register_scope.NextConsecutiveRegister();
|
| - Register language = temporary_register_scope.NextConsecutiveRegister();
|
| - Register position = temporary_register_scope.NextConsecutiveRegister();
|
| + RegisterAllocationScope inner_register_scope(this);
|
| + register_allocator()->PrepareForConsecutiveAllocations(5);
|
| + Register callee_for_eval = register_allocator()->NextConsecutiveRegister();
|
| + Register source = register_allocator()->NextConsecutiveRegister();
|
| + Register function = register_allocator()->NextConsecutiveRegister();
|
| + Register language = register_allocator()->NextConsecutiveRegister();
|
| + Register position = register_allocator()->NextConsecutiveRegister();
|
|
|
| // Set up arguments for ResolvePossiblyDirectEval by copying callee, source
|
| // strings and function closure, and loading language and
|
| @@ -1598,7 +1623,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
|
|
|
|
|
| void BytecodeGenerator::VisitCallNew(CallNew* expr) {
|
| - Register constructor = execution_result()->NewRegister();
|
| + Register constructor = register_allocator()->NewRegister();
|
| VisitForAccumulatorValue(expr->expression());
|
| builder()->StoreAccumulatorInRegister(constructor);
|
|
|
| @@ -1614,8 +1639,8 @@ void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
| Register receiver;
|
| if (expr->is_jsruntime()) {
|
| // Allocate a register for the receiver and load it with undefined.
|
| - execution_result()->PrepareForConsecutiveAllocations(args->length() + 1);
|
| - receiver = execution_result()->NextConsecutiveRegister();
|
| + register_allocator()->PrepareForConsecutiveAllocations(args->length() + 1);
|
| + receiver = register_allocator()->NextConsecutiveRegister();
|
| builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
|
| }
|
| // Evaluate all arguments to the runtime call.
|
| @@ -1705,8 +1730,8 @@ void BytecodeGenerator::VisitDelete(UnaryOperation* expr) {
|
| case VariableLocation::GLOBAL:
|
| case VariableLocation::UNALLOCATED: {
|
| // Global var, let, const or variables not explicitly declared.
|
| - Register native_context = execution_result()->NewRegister();
|
| - Register global_object = execution_result()->NewRegister();
|
| + Register native_context = register_allocator()->NewRegister();
|
| + Register global_object = register_allocator()->NewRegister();
|
| builder()
|
| ->LoadContextSlot(execution_context()->reg(),
|
| Context::NATIVE_CONTEXT_INDEX)
|
| @@ -1778,7 +1803,7 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
|
| obj = VisitForRegisterValue(property->obj());
|
| // Use visit for accumulator here since we need the key in the accumulator
|
| // for the LoadKeyedProperty.
|
| - key = execution_result()->NewRegister();
|
| + key = register_allocator()->NewRegister();
|
| VisitForAccumulatorValue(property->key());
|
| builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty(
|
| obj, feedback_index(slot), language_mode());
|
| @@ -1796,7 +1821,7 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|
|
| // Save result for postfix expressions.
|
| if (is_postfix) {
|
| - old_value = execution_result()->outer()->NewRegister();
|
| + old_value = register_allocator()->outer()->NewRegister();
|
| builder()->StoreAccumulatorInRegister(old_value);
|
| }
|
|
|
| @@ -1949,9 +1974,9 @@ void BytecodeGenerator::VisitNewLocalFunctionContext() {
|
|
|
| // Allocate a new local context.
|
| if (scope->is_script_scope()) {
|
| - TemporaryRegisterScope temporary_register_scope(builder());
|
| - Register closure = temporary_register_scope.NewRegister();
|
| - Register scope_info = temporary_register_scope.NewRegister();
|
| + RegisterAllocationScope register_scope(this);
|
| + Register closure = register_allocator()->NewRegister();
|
| + Register scope_info = register_allocator()->NewRegister();
|
| DCHECK(Register::AreContiguous(closure, scope_info));
|
| builder()
|
| ->LoadAccumulatorWithRegister(Register::function_closure())
|
| @@ -2001,10 +2026,9 @@ void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) {
|
| DCHECK(scope->is_block_scope());
|
|
|
| // Allocate a new local block context.
|
| - TemporaryRegisterScope temporary_register_scope(builder());
|
| - temporary_register_scope.PrepareForConsecutiveAllocations(2);
|
| - Register scope_info = temporary_register_scope.NextConsecutiveRegister();
|
| - Register closure = temporary_register_scope.NextConsecutiveRegister();
|
| + register_allocator()->PrepareForConsecutiveAllocations(2);
|
| + Register scope_info = register_allocator()->NextConsecutiveRegister();
|
| + Register closure = register_allocator()->NextConsecutiveRegister();
|
|
|
| builder()
|
| ->LoadLiteral(scope->GetScopeInfo(isolate()))
|
| @@ -2084,7 +2108,7 @@ void BytecodeGenerator::VisitFunctionClosureForContext() {
|
| closure_scope->is_module_scope()) {
|
| // Contexts nested in the native context have a canonical empty function as
|
| // their closure, not the anonymous closure containing the global code.
|
| - Register native_context = execution_result()->NewRegister();
|
| + Register native_context = register_allocator()->NewRegister();
|
| builder()
|
| ->LoadContextSlot(execution_context()->reg(),
|
| Context::NATIVE_CONTEXT_INDEX)
|
|
|