| Index: src/interpreter/bytecode-generator.cc
|
| diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
|
| index 0f07fc0794bc6d1d16e1870c60875ddbed759931..c7d333f0a534fc194c367304cbd8dafe99706248 100644
|
| --- a/src/interpreter/bytecode-generator.cc
|
| +++ b/src/interpreter/bytecode-generator.cc
|
| @@ -374,75 +374,35 @@ class BytecodeGenerator::RegisterAllocationScope {
|
| public:
|
| explicit RegisterAllocationScope(BytecodeGenerator* generator)
|
| : generator_(generator),
|
| - outer_(generator->register_allocator()),
|
| - allocator_(builder()->zone(),
|
| - builder()->temporary_register_allocator()) {
|
| - generator_->set_register_allocator(this);
|
| - }
|
| + outer_next_register_index_(
|
| + generator->register_allocator()->next_register_index()) {}
|
|
|
| virtual ~RegisterAllocationScope() {
|
| - generator_->set_register_allocator(outer_);
|
| - }
|
| -
|
| - Register NewRegister() {
|
| - RegisterAllocationScope* current_scope = generator()->register_allocator();
|
| - if ((current_scope == this) ||
|
| - (current_scope->outer() == this &&
|
| - !current_scope->allocator_.HasConsecutiveAllocations())) {
|
| - // Regular case - Allocating registers in current or outer context.
|
| - // VisitForRegisterValue allocates register in outer context.
|
| - return allocator_.NewRegister();
|
| - } else {
|
| - // If it is required to allocate a register other than current or outer
|
| - // scopes, allocate a new temporary register. It might be expensive to
|
| - // walk the full context chain and compute the list of consecutive
|
| - // reservations in the innerscopes.
|
| - UNIMPLEMENTED();
|
| - return Register::invalid_value();
|
| - }
|
| - }
|
| -
|
| - void PrepareForConsecutiveAllocations(int count) {
|
| - allocator_.PrepareForConsecutiveAllocations(count);
|
| - }
|
| -
|
| - Register NextConsecutiveRegister() {
|
| - return allocator_.NextConsecutiveRegister();
|
| + generator_->register_allocator()->ReleaseRegisters(
|
| + outer_next_register_index_);
|
| }
|
|
|
| - 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_;
|
| + int outer_next_register_index_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope);
|
| };
|
|
|
| -// Scoped base class for determining where the result of an expression
|
| -// is stored.
|
| +// Scoped base class for determining how the result of an expression will be
|
| +// used.
|
| class BytecodeGenerator::ExpressionResultScope {
|
| public:
|
| ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind)
|
| : generator_(generator),
|
| kind_(kind),
|
| outer_(generator->execution_result()),
|
| - allocator_(generator),
|
| - result_identified_(false) {
|
| + allocator_(generator) {
|
| generator_->set_execution_result(this);
|
| }
|
|
|
| virtual ~ExpressionResultScope() {
|
| generator_->set_execution_result(outer_);
|
| - DCHECK(result_identified() || generator_->HasStackOverflow());
|
| }
|
|
|
| bool IsEffect() const { return kind_ == Expression::kEffect; }
|
| @@ -454,28 +414,11 @@ class BytecodeGenerator::ExpressionResultScope {
|
| return reinterpret_cast<TestResultScope*>(this);
|
| }
|
|
|
| - virtual void SetResultInAccumulator() = 0;
|
| - virtual void SetResultInRegister(Register reg) = 0;
|
| -
|
| - protected:
|
| - ExpressionResultScope* outer() const { return outer_; }
|
| - BytecodeArrayBuilder* builder() const { return generator_->builder(); }
|
| - BytecodeGenerator* generator() const { return generator_; }
|
| - const RegisterAllocationScope* allocator() const { return &allocator_; }
|
| -
|
| - void set_result_identified() {
|
| - DCHECK(!result_identified());
|
| - result_identified_ = true;
|
| - }
|
| -
|
| - bool result_identified() const { return result_identified_; }
|
| -
|
| private:
|
| BytecodeGenerator* generator_;
|
| Expression::Context kind_;
|
| ExpressionResultScope* outer_;
|
| RegisterAllocationScope allocator_;
|
| - bool result_identified_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope);
|
| };
|
| @@ -486,61 +429,15 @@ class BytecodeGenerator::EffectResultScope final
|
| : public ExpressionResultScope {
|
| public:
|
| explicit EffectResultScope(BytecodeGenerator* generator)
|
| - : ExpressionResultScope(generator, Expression::kEffect) {
|
| - set_result_identified();
|
| - }
|
| -
|
| - virtual void SetResultInAccumulator() {}
|
| - virtual void SetResultInRegister(Register reg) {}
|
| + : ExpressionResultScope(generator, Expression::kEffect) {}
|
| };
|
|
|
| // Scoped class used when the result of the current expression to be
|
| -// evaluated should go into the interpreter's accumulator register.
|
| -class BytecodeGenerator::AccumulatorResultScope final
|
| - : public ExpressionResultScope {
|
| +// evaluated should go into the interpreter's accumulator.
|
| +class BytecodeGenerator::ValueResultScope final : public ExpressionResultScope {
|
| public:
|
| - explicit AccumulatorResultScope(BytecodeGenerator* generator)
|
| + explicit ValueResultScope(BytecodeGenerator* generator)
|
| : ExpressionResultScope(generator, Expression::kValue) {}
|
| -
|
| - virtual void SetResultInAccumulator() { set_result_identified(); }
|
| -
|
| - virtual void SetResultInRegister(Register reg) {
|
| - builder()->LoadAccumulatorWithRegister(reg);
|
| - set_result_identified();
|
| - }
|
| -};
|
| -
|
| -// Scoped class used when the result of the current expression to be
|
| -// evaluated should go into an interpreter register.
|
| -class BytecodeGenerator::RegisterResultScope final
|
| - : public ExpressionResultScope {
|
| - public:
|
| - explicit RegisterResultScope(BytecodeGenerator* generator)
|
| - : ExpressionResultScope(generator, Expression::kValue) {}
|
| -
|
| - virtual void SetResultInAccumulator() {
|
| - result_register_ = allocator()->outer()->NewRegister();
|
| - builder()->StoreAccumulatorInRegister(result_register_);
|
| - set_result_identified();
|
| - }
|
| -
|
| - virtual void SetResultInRegister(Register reg) {
|
| - DCHECK(builder()->RegisterIsParameterOrLocal(reg) ||
|
| - (builder()->TemporaryRegisterIsLive(reg) &&
|
| - !allocator()->RegisterIsAllocatedInThisScope(reg)));
|
| - result_register_ = reg;
|
| - set_result_identified();
|
| - }
|
| -
|
| - Register ResultRegister() {
|
| - if (generator()->HasStackOverflow() && !result_identified()) {
|
| - SetResultInAccumulator();
|
| - }
|
| - return result_register_;
|
| - }
|
| -
|
| - private:
|
| - Register result_register_;
|
| };
|
|
|
| // Scoped class used when the result of the current expression to be
|
| @@ -555,18 +452,10 @@ class BytecodeGenerator::TestResultScope final : public ExpressionResultScope {
|
| fallthrough_(fallthrough),
|
| result_consumed_by_test_(false) {}
|
|
|
| - virtual void SetResultInAccumulator() { set_result_identified(); }
|
| -
|
| - virtual void SetResultInRegister(Register reg) {
|
| - builder()->LoadAccumulatorWithRegister(reg);
|
| - set_result_identified();
|
| - }
|
| -
|
| // Used when code special cases for TestResultScope and consumes any
|
| // possible value by testing and jumping to a then/else label.
|
| void SetResultConsumedByTest() {
|
| result_consumed_by_test_ = true;
|
| - set_result_identified();
|
| }
|
|
|
| bool ResultConsumedByTest() { return result_consumed_by_test_; }
|
| @@ -678,7 +567,6 @@ BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
|
| execution_control_(nullptr),
|
| execution_context_(nullptr),
|
| execution_result_(nullptr),
|
| - register_allocator_(nullptr),
|
| generator_resume_points_(info->literal()->yield_count(), info->zone()),
|
| generator_state_(),
|
| loop_depth_(0),
|
| @@ -928,7 +816,7 @@ void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
|
| builder()
|
| ->LoadLiteral(variable->name())
|
| .StoreAccumulatorInRegister(name)
|
| - .CallRuntime(Runtime::kDeclareEvalVar, name, 1);
|
| + .CallRuntime(Runtime::kDeclareEvalVar, name);
|
| break;
|
| }
|
| case VariableLocation::MODULE:
|
| @@ -966,14 +854,13 @@ void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
|
| break;
|
| }
|
| case VariableLocation::LOOKUP: {
|
| - register_allocator()->PrepareForConsecutiveAllocations(2);
|
| - Register name = register_allocator()->NextConsecutiveRegister();
|
| - Register literal = register_allocator()->NextConsecutiveRegister();
|
| - builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name);
|
| -
|
| + RegisterList args = register_allocator()->NewRegisterList(2);
|
| + builder()
|
| + ->LoadLiteral(variable->name())
|
| + .StoreAccumulatorInRegister(args[0]);
|
| VisitForAccumulatorValue(decl->fun());
|
| - builder()->StoreAccumulatorInRegister(literal).CallRuntime(
|
| - Runtime::kDeclareEvalFunction, name, 2);
|
| + builder()->StoreAccumulatorInRegister(args[1]).CallRuntime(
|
| + Runtime::kDeclareEvalFunction, args);
|
| break;
|
| }
|
| case VariableLocation::MODULE:
|
| @@ -1000,20 +887,15 @@ void BytecodeGenerator::VisitDeclarations(
|
| builder()->AllocateConstantPoolEntry());
|
| int encoded_flags = info()->GetDeclareGlobalsFlags();
|
|
|
| - register_allocator()->PrepareForConsecutiveAllocations(3);
|
| -
|
| - Register pairs = register_allocator()->NextConsecutiveRegister();
|
| - Register flags = register_allocator()->NextConsecutiveRegister();
|
| - Register function = register_allocator()->NextConsecutiveRegister();
|
| -
|
| // Emit code to declare globals.
|
| + RegisterList args = register_allocator()->NewRegisterList(3);
|
| builder()
|
| ->LoadConstantPoolEntry(globals_builder()->constant_pool_entry())
|
| - .StoreAccumulatorInRegister(pairs)
|
| + .StoreAccumulatorInRegister(args[0])
|
| .LoadLiteral(Smi::FromInt(encoded_flags))
|
| - .StoreAccumulatorInRegister(flags)
|
| - .MoveRegister(Register::function_closure(), function)
|
| - .CallRuntime(Runtime::kDeclareGlobalsForInterpreter, pairs, 3);
|
| + .StoreAccumulatorInRegister(args[1])
|
| + .MoveRegister(Register::function_closure(), args[2])
|
| + .CallRuntime(Runtime::kDeclareGlobalsForInterpreter, args);
|
|
|
| // Push and reset globals builder.
|
| global_declarations_.push_back(globals_builder());
|
| @@ -1268,36 +1150,28 @@ void BytecodeGenerator::VisitForInAssignment(Expression* expr,
|
| }
|
| case NAMED_SUPER_PROPERTY: {
|
| RegisterAllocationScope register_scope(this);
|
| - register_allocator()->PrepareForConsecutiveAllocations(4);
|
| - Register receiver = register_allocator()->NextConsecutiveRegister();
|
| - Register home_object = register_allocator()->NextConsecutiveRegister();
|
| - Register name = register_allocator()->NextConsecutiveRegister();
|
| - Register value = register_allocator()->NextConsecutiveRegister();
|
| - builder()->StoreAccumulatorInRegister(value);
|
| + RegisterList args = register_allocator()->NewRegisterList(4);
|
| + builder()->StoreAccumulatorInRegister(args[3]);
|
| SuperPropertyReference* super_property =
|
| property->obj()->AsSuperPropertyReference();
|
| - VisitForRegisterValue(super_property->this_var(), receiver);
|
| - VisitForRegisterValue(super_property->home_object(), home_object);
|
| + VisitForRegisterValue(super_property->this_var(), args[0]);
|
| + VisitForRegisterValue(super_property->home_object(), args[1]);
|
| builder()
|
| ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
|
| - .StoreAccumulatorInRegister(name);
|
| - BuildNamedSuperPropertyStore(receiver, home_object, name, value);
|
| + .StoreAccumulatorInRegister(args[2])
|
| + .CallRuntime(StoreToSuperRuntimeId(), args);
|
| break;
|
| }
|
| case KEYED_SUPER_PROPERTY: {
|
| RegisterAllocationScope register_scope(this);
|
| - register_allocator()->PrepareForConsecutiveAllocations(4);
|
| - Register receiver = register_allocator()->NextConsecutiveRegister();
|
| - Register home_object = register_allocator()->NextConsecutiveRegister();
|
| - Register key = register_allocator()->NextConsecutiveRegister();
|
| - Register value = register_allocator()->NextConsecutiveRegister();
|
| - builder()->StoreAccumulatorInRegister(value);
|
| + RegisterList args = register_allocator()->NewRegisterList(4);
|
| + builder()->StoreAccumulatorInRegister(args[3]);
|
| SuperPropertyReference* super_property =
|
| property->obj()->AsSuperPropertyReference();
|
| - VisitForRegisterValue(super_property->this_var(), receiver);
|
| - VisitForRegisterValue(super_property->home_object(), home_object);
|
| - VisitForRegisterValue(property->key(), key);
|
| - BuildKeyedSuperPropertyStore(receiver, home_object, key, value);
|
| + VisitForRegisterValue(super_property->this_var(), args[0]);
|
| + VisitForRegisterValue(super_property->home_object(), args[1]);
|
| + VisitForRegisterValue(property->key(), args[2]);
|
| + builder()->CallRuntime(StoreKeyedToSuperRuntimeId(), args);
|
| break;
|
| }
|
| }
|
| @@ -1321,13 +1195,10 @@ void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
| Register receiver = register_allocator()->NewRegister();
|
| builder()->ConvertAccumulatorToObject(receiver);
|
|
|
| - register_allocator()->PrepareForConsecutiveAllocations(3);
|
| - Register cache_type = register_allocator()->NextConsecutiveRegister();
|
| - Register cache_array = register_allocator()->NextConsecutiveRegister();
|
| - Register cache_length = register_allocator()->NextConsecutiveRegister();
|
| // Used as kRegTriple and kRegPair in ForInPrepare and ForInNext.
|
| - USE(cache_array);
|
| - builder()->ForInPrepare(receiver, cache_type);
|
| + RegisterList triple = register_allocator()->NewRegisterList(3);
|
| + Register cache_length = triple[2];
|
| + builder()->ForInPrepare(receiver, triple.first_register());
|
|
|
| // Set up loop counter
|
| Register index = register_allocator()->NewRegister();
|
| @@ -1339,9 +1210,9 @@ void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
| builder()->SetExpressionAsStatementPosition(stmt->each());
|
| builder()->ForInContinue(index, cache_length);
|
| loop_builder.BreakIfFalse();
|
| - DCHECK(Register::AreContiguous(cache_type, cache_array));
|
| FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
|
| - builder()->ForInNext(receiver, index, cache_type, feedback_index(slot));
|
| + builder()->ForInNext(receiver, index, triple.first_register(),
|
| + feedback_index(slot));
|
| loop_builder.ContinueIfUndefined();
|
| VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot());
|
| VisitIterationBody(stmt, &loop_builder);
|
| @@ -1373,7 +1244,6 @@ void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
|
|
|
| void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
| TryCatchBuilder try_control_builder(builder(), stmt->catch_prediction());
|
| - Register no_reg;
|
|
|
| // Preserve the context in a dedicated register, so that it can be restored
|
| // when the handler is entered by the stack-unwinding machinery.
|
| @@ -1396,7 +1266,7 @@ void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
|
|
| // If requested, clear message object as we enter the catch block.
|
| if (stmt->clear_pending_message()) {
|
| - builder()->CallRuntime(Runtime::kInterpreterClearPendingMessage, no_reg, 0);
|
| + builder()->CallRuntime(Runtime::kInterpreterClearPendingMessage);
|
| }
|
|
|
| // Load the catch context into the accumulator.
|
| @@ -1409,7 +1279,6 @@ void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
|
|
| void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
| TryFinallyBuilder try_control_builder(builder(), stmt->catch_prediction());
|
| - Register no_reg;
|
|
|
| // We keep a record of all paths that enter the finally-block to be able to
|
| // dispatch to the correct continuation point after the statements in the
|
| @@ -1457,7 +1326,7 @@ void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
|
|
| // Clear message object as we enter the finally block.
|
| builder()
|
| - ->CallRuntime(Runtime::kInterpreterClearPendingMessage, no_reg, 0)
|
| + ->CallRuntime(Runtime::kInterpreterClearPendingMessage)
|
| .StoreAccumulatorInRegister(message);
|
|
|
| // Evaluate the finally-block.
|
| @@ -1465,7 +1334,7 @@ void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
| try_control_builder.EndFinally();
|
|
|
| // Pending message object is restored on exit.
|
| - builder()->CallRuntime(Runtime::kInterpreterSetPendingMessage, message, 1);
|
| + builder()->CallRuntime(Runtime::kInterpreterSetPendingMessage, message);
|
|
|
| // Dynamic dispatch after the finally-block.
|
| commands.ApplyDeferredCommands();
|
| @@ -1482,16 +1351,15 @@ void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
|
| size_t entry = builder()->AllocateConstantPoolEntry();
|
| builder()->CreateClosure(entry, flags);
|
| function_literals_.push_back(std::make_pair(expr, entry));
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
|
| VisitClassLiteralForRuntimeDefinition(expr);
|
|
|
| // Load the "prototype" from the constructor.
|
| - register_allocator()->PrepareForConsecutiveAllocations(2);
|
| - Register literal = register_allocator()->NextConsecutiveRegister();
|
| - Register prototype = register_allocator()->NextConsecutiveRegister();
|
| + RegisterList args = register_allocator()->NewRegisterList(2);
|
| + Register literal = args[0];
|
| + Register prototype = args[1];
|
| FeedbackVectorSlot slot = expr->PrototypeSlot();
|
| builder()
|
| ->StoreAccumulatorInRegister(literal)
|
| @@ -1499,7 +1367,7 @@ void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
|
| .StoreAccumulatorInRegister(prototype);
|
|
|
| VisitClassLiteralProperties(expr, literal, prototype);
|
| - builder()->CallRuntime(Runtime::kToFastProperties, literal, 1);
|
| + builder()->CallRuntime(Runtime::kToFastProperties, literal);
|
| // Assign to class variable.
|
| if (expr->class_variable_proxy() != nullptr) {
|
| Variable* var = expr->class_variable_proxy()->var();
|
| @@ -1508,42 +1376,30 @@ void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
|
| : FeedbackVectorSlot::Invalid();
|
| VisitVariableAssignment(var, Token::INIT, slot);
|
| }
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition(
|
| ClassLiteral* expr) {
|
| - AccumulatorResultScope result_scope(this);
|
| - register_allocator()->PrepareForConsecutiveAllocations(4);
|
| - Register extends = register_allocator()->NextConsecutiveRegister();
|
| - Register constructor = register_allocator()->NextConsecutiveRegister();
|
| - Register start_position = register_allocator()->NextConsecutiveRegister();
|
| - Register end_position = register_allocator()->NextConsecutiveRegister();
|
| -
|
| + RegisterAllocationScope register_scope(this);
|
| + RegisterList args = register_allocator()->NewRegisterList(4);
|
| VisitForAccumulatorValueOrTheHole(expr->extends());
|
| - builder()->StoreAccumulatorInRegister(extends);
|
| -
|
| - VisitForAccumulatorValue(expr->constructor());
|
| + builder()->StoreAccumulatorInRegister(args[0]);
|
| + VisitForRegisterValue(expr->constructor(), args[1]);
|
| builder()
|
| - ->StoreAccumulatorInRegister(constructor)
|
| - .LoadLiteral(Smi::FromInt(expr->start_position()))
|
| - .StoreAccumulatorInRegister(start_position)
|
| + ->LoadLiteral(Smi::FromInt(expr->start_position()))
|
| + .StoreAccumulatorInRegister(args[2])
|
| .LoadLiteral(Smi::FromInt(expr->end_position()))
|
| - .StoreAccumulatorInRegister(end_position)
|
| - .CallRuntime(Runtime::kDefineClass, extends, 4);
|
| - result_scope.SetResultInAccumulator();
|
| + .StoreAccumulatorInRegister(args[3])
|
| + .CallRuntime(Runtime::kDefineClass, args);
|
| }
|
|
|
| void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
|
| Register literal,
|
| Register prototype) {
|
| RegisterAllocationScope register_scope(this);
|
| - register_allocator()->PrepareForConsecutiveAllocations(5);
|
| - Register receiver = register_allocator()->NextConsecutiveRegister();
|
| - Register key = register_allocator()->NextConsecutiveRegister();
|
| - Register value = register_allocator()->NextConsecutiveRegister();
|
| - Register attr = register_allocator()->NextConsecutiveRegister();
|
| - Register set_function_name = register_allocator()->NextConsecutiveRegister();
|
| + RegisterList args = register_allocator()->NewRegisterList(5);
|
| + Register receiver = args[0], key = args[1], value = args[2], attr = args[3],
|
| + set_function_name = args[4];
|
|
|
| bool attr_assigned = false;
|
| Register old_receiver = Register::invalid_value();
|
| @@ -1561,16 +1417,22 @@ void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
|
|
|
| VisitForAccumulatorValue(property->key());
|
| builder()->ConvertAccumulatorToName(key);
|
| - // The static prototype property is read only. We handle the non computed
|
| - // property name case in the parser. Since this is the only case where we
|
| - // need to check for an own read only property we special case this so we do
|
| - // not need to do this for every property.
|
| +
|
| if (property->is_static() && property->is_computed_name()) {
|
| - VisitClassLiteralStaticPrototypeWithComputedName(key);
|
| + // The static prototype property is read only. We handle the non computed
|
| + // property name case in the parser. Since this is the only case where we
|
| + // need to check for an own read only property we special case this so we
|
| + // do not need to do this for every property.
|
| + BytecodeLabel done;
|
| + builder()
|
| + ->LoadLiteral(prototype_string())
|
| + .CompareOperation(Token::Value::EQ_STRICT, key)
|
| + .JumpIfFalse(&done)
|
| + .CallRuntime(Runtime::kThrowStaticPrototypeError)
|
| + .Bind(&done);
|
| }
|
| - VisitForAccumulatorValue(property->value());
|
| - builder()->StoreAccumulatorInRegister(value);
|
|
|
| + VisitForRegisterValue(property->value(), value);
|
| VisitSetHomeObject(value, receiver, property);
|
|
|
| if (!attr_assigned) {
|
| @@ -1584,19 +1446,18 @@ void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
|
| case ClassLiteral::Property::METHOD: {
|
| builder()
|
| ->LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName()))
|
| - .StoreAccumulatorInRegister(set_function_name);
|
| - builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral, receiver,
|
| - 5);
|
| + .StoreAccumulatorInRegister(set_function_name)
|
| + .CallRuntime(Runtime::kDefineDataPropertyInLiteral, args);
|
| break;
|
| }
|
| case ClassLiteral::Property::GETTER: {
|
| builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked,
|
| - receiver, 4);
|
| + args.Truncate(4));
|
| break;
|
| }
|
| case ClassLiteral::Property::SETTER: {
|
| builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked,
|
| - receiver, 4);
|
| + args.Truncate(4));
|
| break;
|
| }
|
| case ClassLiteral::Property::FIELD: {
|
| @@ -1607,23 +1468,11 @@ void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
|
| }
|
| }
|
|
|
| -void BytecodeGenerator::VisitClassLiteralStaticPrototypeWithComputedName(
|
| - Register key) {
|
| - BytecodeLabel done;
|
| - builder()
|
| - ->LoadLiteral(prototype_string())
|
| - .CompareOperation(Token::Value::EQ_STRICT, key)
|
| - .JumpIfFalse(&done)
|
| - .CallRuntime(Runtime::kThrowStaticPrototypeError, Register(0), 0)
|
| - .Bind(&done);
|
| -}
|
| -
|
| void BytecodeGenerator::VisitNativeFunctionLiteral(
|
| NativeFunctionLiteral* expr) {
|
| size_t entry = builder()->AllocateConstantPoolEntry();
|
| builder()->CreateClosure(entry, NOT_TENURED);
|
| native_function_literals_.push_back(std::make_pair(expr, entry));
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitDoExpression(DoExpression* expr) {
|
| @@ -1653,8 +1502,6 @@ void BytecodeGenerator::VisitConditional(Conditional* expr) {
|
| VisitForAccumulatorValue(expr->else_expression());
|
| builder()->Bind(&end_label);
|
| }
|
| -
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitLiteral(Literal* expr) {
|
| @@ -1675,7 +1522,6 @@ void BytecodeGenerator::VisitLiteral(Literal* expr) {
|
| } else {
|
| builder()->LoadLiteral(raw_value->value());
|
| }
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
| }
|
|
|
| @@ -1683,7 +1529,6 @@ void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
|
| // Materialize a regular expression literal.
|
| builder()->CreateRegExpLiteral(expr->pattern(), expr->literal_index(),
|
| expr->flags());
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
| @@ -1694,7 +1539,7 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
| expr->ComputeFlags());
|
| // Allocate in the outer scope since this register is used to return the
|
| // expression's results to the caller.
|
| - Register literal = register_allocator()->outer()->NewRegister();
|
| + Register literal = register_allocator()->NewRegister();
|
| builder()->CreateObjectLiteral(expr->constant_properties(),
|
| expr->literal_index(), flags, literal);
|
|
|
| @@ -1738,23 +1583,17 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
| VisitForEffect(property->value());
|
| }
|
| } else {
|
| - register_allocator()->PrepareForConsecutiveAllocations(4);
|
| - Register literal_argument =
|
| - register_allocator()->NextConsecutiveRegister();
|
| - Register key = register_allocator()->NextConsecutiveRegister();
|
| - Register value = register_allocator()->NextConsecutiveRegister();
|
| - Register language = register_allocator()->NextConsecutiveRegister();
|
| -
|
| - builder()->MoveRegister(literal, literal_argument);
|
| - VisitForAccumulatorValue(property->key());
|
| - builder()->StoreAccumulatorInRegister(key);
|
| - VisitForAccumulatorValue(property->value());
|
| - builder()->StoreAccumulatorInRegister(value);
|
| + RegisterList args = register_allocator()->NewRegisterList(4);
|
| +
|
| + builder()->MoveRegister(literal, args[0]);
|
| + VisitForRegisterValue(property->key(), args[1]);
|
| + VisitForRegisterValue(property->value(), args[2]);
|
| if (property->emit_store()) {
|
| builder()
|
| ->LoadLiteral(Smi::FromInt(SLOPPY))
|
| - .StoreAccumulatorInRegister(language)
|
| - .CallRuntime(Runtime::kSetProperty, literal_argument, 4);
|
| + .StoreAccumulatorInRegister(args[3])
|
| + .CallRuntime(Runtime::kSetProperty, args);
|
| + Register value = args[2];
|
| VisitSetHomeObject(value, literal, property);
|
| }
|
| }
|
| @@ -1762,15 +1601,10 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
| }
|
| case ObjectLiteral::Property::PROTOTYPE: {
|
| DCHECK(property->emit_store());
|
| - register_allocator()->PrepareForConsecutiveAllocations(2);
|
| - Register literal_argument =
|
| - register_allocator()->NextConsecutiveRegister();
|
| - Register value = register_allocator()->NextConsecutiveRegister();
|
| -
|
| - builder()->MoveRegister(literal, literal_argument);
|
| - VisitForAccumulatorValue(property->value());
|
| - builder()->StoreAccumulatorInRegister(value).CallRuntime(
|
| - Runtime::kInternalSetPrototype, literal_argument, 2);
|
| + RegisterList args = register_allocator()->NewRegisterList(2);
|
| + builder()->MoveRegister(literal, args[0]);
|
| + VisitForRegisterValue(property->value(), args[1]);
|
| + builder()->CallRuntime(Runtime::kInternalSetPrototype, args);
|
| break;
|
| }
|
| case ObjectLiteral::Property::GETTER:
|
| @@ -1791,23 +1625,15 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
| for (AccessorTable::Iterator it = accessor_table.begin();
|
| it != accessor_table.end(); ++it) {
|
| RegisterAllocationScope inner_register_scope(this);
|
| - register_allocator()->PrepareForConsecutiveAllocations(5);
|
| - Register literal_argument = register_allocator()->NextConsecutiveRegister();
|
| - Register name = register_allocator()->NextConsecutiveRegister();
|
| - Register getter = register_allocator()->NextConsecutiveRegister();
|
| - Register setter = register_allocator()->NextConsecutiveRegister();
|
| - Register attr = register_allocator()->NextConsecutiveRegister();
|
| -
|
| - builder()->MoveRegister(literal, literal_argument);
|
| - VisitForAccumulatorValue(it->first);
|
| - builder()->StoreAccumulatorInRegister(name);
|
| - VisitObjectLiteralAccessor(literal, it->second->getter, getter);
|
| - VisitObjectLiteralAccessor(literal, it->second->setter, setter);
|
| + RegisterList args = register_allocator()->NewRegisterList(5);
|
| + builder()->MoveRegister(literal, args[0]);
|
| + VisitForRegisterValue(it->first, args[1]);
|
| + VisitObjectLiteralAccessor(literal, it->second->getter, args[2]);
|
| + VisitObjectLiteralAccessor(literal, it->second->setter, args[3]);
|
| builder()
|
| ->LoadLiteral(Smi::FromInt(NONE))
|
| - .StoreAccumulatorInRegister(attr)
|
| - .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked,
|
| - literal_argument, 5);
|
| + .StoreAccumulatorInRegister(args[4])
|
| + .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, args);
|
| }
|
|
|
| // Object literals have two parts. The "static" part on the left contains no
|
| @@ -1825,59 +1651,56 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|
|
| if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
|
| DCHECK(property->emit_store());
|
| - register_allocator()->PrepareForConsecutiveAllocations(2);
|
| - Register literal_argument =
|
| - register_allocator()->NextConsecutiveRegister();
|
| - Register value = register_allocator()->NextConsecutiveRegister();
|
| -
|
| - builder()->MoveRegister(literal, literal_argument);
|
| - VisitForAccumulatorValue(property->value());
|
| - builder()->StoreAccumulatorInRegister(value).CallRuntime(
|
| - Runtime::kInternalSetPrototype, literal_argument, 2);
|
| + RegisterList args = register_allocator()->NewRegisterList(2);
|
| + builder()->MoveRegister(literal, args[0]);
|
| + VisitForRegisterValue(property->value(), args[1]);
|
| + builder()->CallRuntime(Runtime::kInternalSetPrototype, args);
|
| continue;
|
| }
|
|
|
| - register_allocator()->PrepareForConsecutiveAllocations(5);
|
| - Register literal_argument = register_allocator()->NextConsecutiveRegister();
|
| - Register key = register_allocator()->NextConsecutiveRegister();
|
| - Register value = register_allocator()->NextConsecutiveRegister();
|
| - Register attr = register_allocator()->NextConsecutiveRegister();
|
| - DCHECK(Register::AreContiguous(literal_argument, key, value, attr));
|
| - Register set_function_name =
|
| - register_allocator()->NextConsecutiveRegister();
|
| -
|
| - builder()->MoveRegister(literal, literal_argument);
|
| - VisitForAccumulatorValue(property->key());
|
| - builder()->ConvertAccumulatorToName(key);
|
| - VisitForAccumulatorValue(property->value());
|
| - builder()->StoreAccumulatorInRegister(value);
|
| - VisitSetHomeObject(value, literal, property);
|
| - builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr);
|
| switch (property->kind()) {
|
| case ObjectLiteral::Property::CONSTANT:
|
| case ObjectLiteral::Property::COMPUTED:
|
| - case ObjectLiteral::Property::MATERIALIZED_LITERAL:
|
| + case ObjectLiteral::Property::MATERIALIZED_LITERAL: {
|
| + RegisterList args = register_allocator()->NewRegisterList(5);
|
| + builder()->MoveRegister(literal, args[0]);
|
| + VisitForAccumulatorValue(property->key());
|
| + builder()->ConvertAccumulatorToName(args[1]);
|
| + VisitForRegisterValue(property->value(), args[2]);
|
| + VisitSetHomeObject(args[2], literal, property);
|
| builder()
|
| - ->LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName()))
|
| - .StoreAccumulatorInRegister(set_function_name);
|
| - builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral,
|
| - literal_argument, 5);
|
| - break;
|
| - case ObjectLiteral::Property::PROTOTYPE:
|
| - UNREACHABLE(); // Handled specially above.
|
| + ->LoadLiteral(Smi::FromInt(NONE))
|
| + .StoreAccumulatorInRegister(args[3])
|
| + .LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName()))
|
| + .StoreAccumulatorInRegister(args[4]);
|
| + builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral, args);
|
| break;
|
| + }
|
| case ObjectLiteral::Property::GETTER:
|
| - builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked,
|
| - literal_argument, 4);
|
| + case ObjectLiteral::Property::SETTER: {
|
| + RegisterList args = register_allocator()->NewRegisterList(4);
|
| + builder()->MoveRegister(literal, args[0]);
|
| + VisitForAccumulatorValue(property->key());
|
| + builder()->ConvertAccumulatorToName(args[1]);
|
| + VisitForRegisterValue(property->value(), args[2]);
|
| + VisitSetHomeObject(args[2], literal, property);
|
| + builder()
|
| + ->LoadLiteral(Smi::FromInt(NONE))
|
| + .StoreAccumulatorInRegister(args[3]);
|
| + Runtime::FunctionId function_id =
|
| + property->kind() == ObjectLiteral::Property::GETTER
|
| + ? Runtime::kDefineGetterPropertyUnchecked
|
| + : Runtime::kDefineSetterPropertyUnchecked;
|
| + builder()->CallRuntime(function_id, args);
|
| break;
|
| - case ObjectLiteral::Property::SETTER:
|
| - builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked,
|
| - literal_argument, 4);
|
| + }
|
| + case ObjectLiteral::Property::PROTOTYPE:
|
| + UNREACHABLE(); // Handled specially above.
|
| break;
|
| }
|
| }
|
|
|
| - execution_result()->SetResultInRegister(literal);
|
| + builder()->LoadAccumulatorWithRegister(literal);
|
| }
|
|
|
| void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
| @@ -1921,7 +1744,6 @@ void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
| // Restore literal array into accumulator.
|
| builder()->LoadAccumulatorWithRegister(literal);
|
| }
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
|
| @@ -2009,91 +1831,44 @@ void BytecodeGenerator::VisitVariableLoad(Variable* variable,
|
| builder()
|
| ->LoadLiteral(it->second->export_name->string())
|
| .StoreAccumulatorInRegister(export_name)
|
| - .CallRuntime(Runtime::kLoadModuleExport, export_name, 1);
|
| + .CallRuntime(Runtime::kLoadModuleExport, export_name);
|
| } else {
|
| auto it = descriptor->regular_imports().find(variable->raw_name());
|
| DCHECK(it != descriptor->regular_imports().end());
|
| - register_allocator()->PrepareForConsecutiveAllocations(2);
|
| - Register import_name = register_allocator()->NextConsecutiveRegister();
|
| - Register module_request =
|
| - register_allocator()->NextConsecutiveRegister();
|
| + RegisterList args = register_allocator()->NewRegisterList(2);
|
| builder()
|
| ->LoadLiteral(it->second->import_name->string())
|
| - .StoreAccumulatorInRegister(import_name)
|
| + .StoreAccumulatorInRegister(args[0])
|
| .LoadLiteral(Smi::FromInt(it->second->module_request))
|
| - .StoreAccumulatorInRegister(module_request)
|
| - .CallRuntime(Runtime::kLoadModuleImport, import_name, 2);
|
| + .StoreAccumulatorInRegister(args[1])
|
| + .CallRuntime(Runtime::kLoadModuleImport, args);
|
| }
|
| BuildHoleCheckForVariableLoad(variable);
|
| break;
|
| }
|
| }
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitVariableLoadForAccumulatorValue(
|
| Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
|
| - AccumulatorResultScope accumulator_result(this);
|
| + ValueResultScope accumulator_result(this);
|
| VisitVariableLoad(variable, slot, typeof_mode);
|
| }
|
|
|
| -Register BytecodeGenerator::VisitVariableLoadForRegisterValue(
|
| - Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
|
| - RegisterResultScope register_scope(this);
|
| - VisitVariableLoad(variable, slot, typeof_mode);
|
| - return register_scope.ResultRegister();
|
| -}
|
| -
|
| -void BytecodeGenerator::BuildNamedSuperPropertyLoad(Register receiver,
|
| - Register home_object,
|
| - Register name) {
|
| - DCHECK(Register::AreContiguous(receiver, home_object, name));
|
| - builder()->CallRuntime(Runtime::kLoadFromSuper, receiver, 3);
|
| -}
|
| -
|
| -void BytecodeGenerator::BuildKeyedSuperPropertyLoad(Register receiver,
|
| - Register home_object,
|
| - Register key) {
|
| - DCHECK(Register::AreContiguous(receiver, home_object, key));
|
| - builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, receiver, 3);
|
| -}
|
| -
|
| -void BytecodeGenerator::BuildNamedSuperPropertyStore(Register receiver,
|
| - Register home_object,
|
| - Register name,
|
| - Register value) {
|
| - DCHECK(Register::AreContiguous(receiver, home_object, name, value));
|
| - Runtime::FunctionId function_id = is_strict(language_mode())
|
| - ? Runtime::kStoreToSuper_Strict
|
| - : Runtime::kStoreToSuper_Sloppy;
|
| - builder()->CallRuntime(function_id, receiver, 4);
|
| -}
|
| -
|
| -void BytecodeGenerator::BuildKeyedSuperPropertyStore(Register receiver,
|
| - Register home_object,
|
| - Register key,
|
| - Register value) {
|
| - DCHECK(Register::AreContiguous(receiver, home_object, key, value));
|
| - Runtime::FunctionId function_id = is_strict(language_mode())
|
| - ? Runtime::kStoreKeyedToSuper_Strict
|
| - : Runtime::kStoreKeyedToSuper_Sloppy;
|
| - builder()->CallRuntime(function_id, receiver, 4);
|
| -}
|
| -
|
| void BytecodeGenerator::BuildAbort(BailoutReason bailout_reason) {
|
| RegisterAllocationScope register_scope(this);
|
| Register reason = register_allocator()->NewRegister();
|
| builder()
|
| ->LoadLiteral(Smi::FromInt(static_cast<int>(bailout_reason)))
|
| .StoreAccumulatorInRegister(reason)
|
| - .CallRuntime(Runtime::kAbort, reason, 1);
|
| + .CallRuntime(Runtime::kAbort, reason);
|
| }
|
|
|
| void BytecodeGenerator::BuildThrowReferenceError(Handle<String> name) {
|
| RegisterAllocationScope register_scope(this);
|
| Register name_reg = register_allocator()->NewRegister();
|
| builder()->LoadLiteral(name).StoreAccumulatorInRegister(name_reg).CallRuntime(
|
| - Runtime::kThrowReferenceError, name_reg, 1);
|
| + Runtime::kThrowReferenceError, name_reg);
|
| }
|
|
|
| void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) {
|
| @@ -2166,7 +1941,7 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
|
| if (mode != CONST || op == Token::INIT) {
|
| builder()->StoreAccumulatorInRegister(destination);
|
| } else if (variable->throw_on_const_assignment(language_mode())) {
|
| - builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0);
|
| + builder()->CallRuntime(Runtime::kThrowConstAssignError);
|
| }
|
| break;
|
| }
|
| @@ -2201,7 +1976,7 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
|
| if (mode != CONST || op == Token::INIT) {
|
| builder()->StoreContextSlot(context_reg, variable->index(), depth);
|
| } else if (variable->throw_on_const_assignment(language_mode())) {
|
| - builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0);
|
| + builder()->CallRuntime(Runtime::kThrowConstAssignError);
|
| }
|
| break;
|
| }
|
| @@ -2213,7 +1988,7 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
|
| DCHECK(IsDeclaredVariableMode(mode));
|
|
|
| if (mode == CONST && op != Token::INIT) {
|
| - builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0);
|
| + builder()->CallRuntime(Runtime::kThrowConstAssignError);
|
| break;
|
| }
|
|
|
| @@ -2228,14 +2003,12 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
|
| auto it = mod->regular_exports().find(variable->raw_name());
|
| DCHECK(it != mod->regular_exports().end());
|
|
|
| - register_allocator()->PrepareForConsecutiveAllocations(2);
|
| - Register export_name = register_allocator()->NextConsecutiveRegister();
|
| - Register value = register_allocator()->NextConsecutiveRegister();
|
| + RegisterList args = register_allocator()->NewRegisterList(2);
|
| builder()
|
| - ->StoreAccumulatorInRegister(value)
|
| + ->StoreAccumulatorInRegister(args[1])
|
| .LoadLiteral(it->second->export_name->string())
|
| - .StoreAccumulatorInRegister(export_name)
|
| - .CallRuntime(Runtime::kStoreModuleExport, export_name, 2);
|
| + .StoreAccumulatorInRegister(args[0])
|
| + .CallRuntime(Runtime::kStoreModuleExport, args);
|
| break;
|
| }
|
| }
|
| @@ -2243,7 +2016,8 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
|
|
|
| void BytecodeGenerator::VisitAssignment(Assignment* expr) {
|
| DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
|
| - Register object, key, home_object, value;
|
| + Register object, key;
|
| + RegisterList super_property_args;
|
| Handle<String> name;
|
|
|
| // Left-hand side can only be a property, a global or a variable slot.
|
| @@ -2262,44 +2036,29 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
|
| }
|
| case KEYED_PROPERTY: {
|
| object = VisitForRegisterValue(property->obj());
|
| - 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 = register_allocator()->NewRegister();
|
| - VisitForAccumulatorValue(property->key());
|
| - builder()->StoreAccumulatorInRegister(key);
|
| - } else {
|
| - key = VisitForRegisterValue(property->key());
|
| - }
|
| + key = VisitForRegisterValue(property->key());
|
| break;
|
| }
|
| case NAMED_SUPER_PROPERTY: {
|
| - register_allocator()->PrepareForConsecutiveAllocations(4);
|
| - object = register_allocator()->NextConsecutiveRegister();
|
| - home_object = register_allocator()->NextConsecutiveRegister();
|
| - key = register_allocator()->NextConsecutiveRegister();
|
| - value = register_allocator()->NextConsecutiveRegister();
|
| + super_property_args = register_allocator()->NewRegisterList(4);
|
| SuperPropertyReference* super_property =
|
| property->obj()->AsSuperPropertyReference();
|
| - VisitForRegisterValue(super_property->this_var(), object);
|
| - VisitForRegisterValue(super_property->home_object(), home_object);
|
| + VisitForRegisterValue(super_property->this_var(), super_property_args[0]);
|
| + VisitForRegisterValue(super_property->home_object(),
|
| + super_property_args[1]);
|
| builder()
|
| ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
|
| - .StoreAccumulatorInRegister(key);
|
| + .StoreAccumulatorInRegister(super_property_args[2]);
|
| break;
|
| }
|
| case KEYED_SUPER_PROPERTY: {
|
| - register_allocator()->PrepareForConsecutiveAllocations(4);
|
| - object = register_allocator()->NextConsecutiveRegister();
|
| - home_object = register_allocator()->NextConsecutiveRegister();
|
| - key = register_allocator()->NextConsecutiveRegister();
|
| - value = register_allocator()->NextConsecutiveRegister();
|
| - builder()->StoreAccumulatorInRegister(value);
|
| + super_property_args = register_allocator()->NewRegisterList(4);
|
| SuperPropertyReference* super_property =
|
| property->obj()->AsSuperPropertyReference();
|
| - VisitForRegisterValue(super_property->this_var(), object);
|
| - VisitForRegisterValue(super_property->home_object(), home_object);
|
| - VisitForRegisterValue(property->key(), key);
|
| + VisitForRegisterValue(super_property->this_var(), super_property_args[0]);
|
| + VisitForRegisterValue(super_property->home_object(),
|
| + super_property_args[1]);
|
| + VisitForRegisterValue(property->key(), super_property_args[2]);
|
| break;
|
| }
|
| }
|
| @@ -2307,17 +2066,16 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
|
| // Evaluate the value and potentially handle compound assignments by loading
|
| // the left-hand side value and performing a binary operation.
|
| if (expr->is_compound()) {
|
| - Register old_value;
|
| + Register old_value = register_allocator()->NewRegister();
|
| switch (assign_type) {
|
| case VARIABLE: {
|
| VariableProxy* proxy = expr->target()->AsVariableProxy();
|
| - old_value = VisitVariableLoadForRegisterValue(
|
| - proxy->var(), proxy->VariableFeedbackSlot());
|
| + VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
|
| + builder()->StoreAccumulatorInRegister(old_value);
|
| break;
|
| }
|
| case NAMED_PROPERTY: {
|
| FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
|
| - old_value = register_allocator()->NewRegister();
|
| builder()
|
| ->LoadNamedProperty(object, name, feedback_index(slot))
|
| .StoreAccumulatorInRegister(old_value);
|
| @@ -2327,22 +2085,23 @@ 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 = register_allocator()->NewRegister();
|
| builder()
|
| ->LoadKeyedProperty(object, feedback_index(slot))
|
| .StoreAccumulatorInRegister(old_value);
|
| break;
|
| }
|
| case NAMED_SUPER_PROPERTY: {
|
| - old_value = register_allocator()->NewRegister();
|
| - BuildNamedSuperPropertyLoad(object, home_object, key);
|
| - builder()->StoreAccumulatorInRegister(old_value);
|
| + builder()
|
| + ->CallRuntime(Runtime::kLoadFromSuper,
|
| + super_property_args.Truncate(3))
|
| + .StoreAccumulatorInRegister(old_value);
|
| break;
|
| }
|
| case KEYED_SUPER_PROPERTY: {
|
| - old_value = register_allocator()->NewRegister();
|
| - BuildKeyedSuperPropertyLoad(object, home_object, key);
|
| - builder()->StoreAccumulatorInRegister(old_value);
|
| + builder()
|
| + ->CallRuntime(Runtime::kLoadKeyedFromSuper,
|
| + super_property_args.Truncate(3))
|
| + .StoreAccumulatorInRegister(old_value);
|
| break;
|
| }
|
| }
|
| @@ -2375,17 +2134,18 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
|
| language_mode());
|
| break;
|
| case NAMED_SUPER_PROPERTY: {
|
| - builder()->StoreAccumulatorInRegister(value);
|
| - BuildNamedSuperPropertyStore(object, home_object, key, value);
|
| + builder()
|
| + ->StoreAccumulatorInRegister(super_property_args[3])
|
| + .CallRuntime(StoreToSuperRuntimeId(), super_property_args);
|
| break;
|
| }
|
| case KEYED_SUPER_PROPERTY: {
|
| - builder()->StoreAccumulatorInRegister(value);
|
| - BuildKeyedSuperPropertyStore(object, home_object, key, value);
|
| + builder()
|
| + ->StoreAccumulatorInRegister(super_property_args[3])
|
| + .CallRuntime(StoreKeyedToSuperRuntimeId(), super_property_args);
|
| break;
|
| }
|
| }
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitYield(Yield* expr) {
|
| @@ -2415,12 +2175,12 @@ void BytecodeGenerator::VisitYield(Yield* expr) {
|
|
|
| Register input = register_allocator()->NewRegister();
|
| builder()
|
| - ->CallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, generator, 1)
|
| + ->CallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, generator)
|
| .StoreAccumulatorInRegister(input);
|
|
|
| Register resume_mode = register_allocator()->NewRegister();
|
| builder()
|
| - ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator, 1)
|
| + ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator)
|
| .StoreAccumulatorInRegister(resume_mode);
|
|
|
| // Now dispatch on resume mode.
|
| @@ -2440,14 +2200,12 @@ void BytecodeGenerator::VisitYield(Yield* expr) {
|
|
|
| builder()->Bind(&resume_with_return);
|
| {
|
| - register_allocator()->PrepareForConsecutiveAllocations(2);
|
| - Register value = register_allocator()->NextConsecutiveRegister();
|
| - Register done = register_allocator()->NextConsecutiveRegister();
|
| + RegisterList args = register_allocator()->NewRegisterList(2);
|
| builder()
|
| - ->MoveRegister(input, value)
|
| + ->MoveRegister(input, args[0])
|
| .LoadTrue()
|
| - .StoreAccumulatorInRegister(done)
|
| - .CallRuntime(Runtime::kInlineCreateIterResultObject, value, 2);
|
| + .StoreAccumulatorInRegister(args[1])
|
| + .CallRuntime(Runtime::kInlineCreateIterResultObject, args);
|
| execution_control()->ReturnAccumulator();
|
| }
|
|
|
| @@ -2463,18 +2221,12 @@ void BytecodeGenerator::VisitYield(Yield* expr) {
|
| builder()->Bind(&resume_with_next);
|
| builder()->LoadAccumulatorWithRegister(input);
|
| }
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitThrow(Throw* expr) {
|
| VisitForAccumulatorValue(expr->exception());
|
| builder()->SetExpressionPosition(expr);
|
| builder()->Throw();
|
| - // Throw statements are modeled as expressions instead of statements. These
|
| - // are converted from assignment statements in Rewriter::ReWrite pass. An
|
| - // assignment statement expects a value in the accumulator. This is a hack to
|
| - // avoid DCHECK fails assert accumulator has been set.
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) {
|
| @@ -2502,56 +2254,45 @@ void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) {
|
| VisitKeyedSuperPropertyLoad(expr, Register::invalid_value());
|
| break;
|
| }
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitPropertyLoadForAccumulator(Register obj,
|
| Property* expr) {
|
| - AccumulatorResultScope result_scope(this);
|
| + ValueResultScope result_scope(this);
|
| VisitPropertyLoad(obj, expr);
|
| }
|
|
|
| void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property,
|
| Register opt_receiver_out) {
|
| RegisterAllocationScope register_scope(this);
|
| - register_allocator()->PrepareForConsecutiveAllocations(3);
|
| -
|
| - Register receiver, home_object, name;
|
| - receiver = register_allocator()->NextConsecutiveRegister();
|
| - home_object = register_allocator()->NextConsecutiveRegister();
|
| - name = register_allocator()->NextConsecutiveRegister();
|
| SuperPropertyReference* super_property =
|
| property->obj()->AsSuperPropertyReference();
|
| - VisitForRegisterValue(super_property->this_var(), receiver);
|
| - VisitForRegisterValue(super_property->home_object(), home_object);
|
| + RegisterList args = register_allocator()->NewRegisterList(3);
|
| + VisitForRegisterValue(super_property->this_var(), args[0]);
|
| + VisitForRegisterValue(super_property->home_object(), args[1]);
|
| builder()
|
| ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
|
| - .StoreAccumulatorInRegister(name);
|
| - BuildNamedSuperPropertyLoad(receiver, home_object, name);
|
| + .StoreAccumulatorInRegister(args[2])
|
| + .CallRuntime(Runtime::kLoadFromSuper, args);
|
|
|
| if (opt_receiver_out.is_valid()) {
|
| - builder()->MoveRegister(receiver, opt_receiver_out);
|
| + builder()->MoveRegister(args[0], opt_receiver_out);
|
| }
|
| }
|
|
|
| void BytecodeGenerator::VisitKeyedSuperPropertyLoad(Property* property,
|
| Register opt_receiver_out) {
|
| RegisterAllocationScope register_scope(this);
|
| - register_allocator()->PrepareForConsecutiveAllocations(3);
|
| -
|
| - Register receiver, home_object, key;
|
| - receiver = register_allocator()->NextConsecutiveRegister();
|
| - home_object = register_allocator()->NextConsecutiveRegister();
|
| - key = register_allocator()->NextConsecutiveRegister();
|
| SuperPropertyReference* super_property =
|
| property->obj()->AsSuperPropertyReference();
|
| - VisitForRegisterValue(super_property->this_var(), receiver);
|
| - VisitForRegisterValue(super_property->home_object(), home_object);
|
| - VisitForRegisterValue(property->key(), key);
|
| - BuildKeyedSuperPropertyLoad(receiver, home_object, key);
|
| + RegisterList args = register_allocator()->NewRegisterList(3);
|
| + VisitForRegisterValue(super_property->this_var(), args[0]);
|
| + VisitForRegisterValue(super_property->home_object(), args[1]);
|
| + VisitForRegisterValue(property->key(), args[2]);
|
| + builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, args);
|
|
|
| if (opt_receiver_out.is_valid()) {
|
| - builder()->MoveRegister(receiver, opt_receiver_out);
|
| + builder()->MoveRegister(args[0], opt_receiver_out);
|
| }
|
| }
|
|
|
| @@ -2566,36 +2307,13 @@ void BytecodeGenerator::VisitProperty(Property* expr) {
|
| }
|
| }
|
|
|
| -Register BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args) {
|
| - if (args->length() == 0) {
|
| - return Register();
|
| - }
|
| -
|
| - // Visit arguments and place in a contiguous block of temporary
|
| - // registers. Return the first temporary register corresponding to
|
| - // the first argument.
|
| - //
|
| - // NB the caller may have already called
|
| - // PrepareForConsecutiveAllocations() with args->length() + N. The
|
| - // second call here will be a no-op provided there have been N or
|
| - // 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.
|
| - register_allocator()->PrepareForConsecutiveAllocations(args->length());
|
| -
|
| - // Visit for first argument that goes into returned register
|
| - 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 = register_allocator()->NextConsecutiveRegister();
|
| - VisitForAccumulatorValue(args->at(i));
|
| - builder()->StoreAccumulatorInRegister(ith_arg);
|
| - DCHECK(ith_arg.index() - i == first_arg.index());
|
| +void BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args,
|
| + RegisterList arg_regs,
|
| + size_t first_argument_register) {
|
| + // Visit arguments.
|
| + for (int i = 0; i < static_cast<int>(args->length()); i++) {
|
| + VisitForRegisterValue(args->at(i), arg_regs[first_argument_register + i]);
|
| }
|
| - return first_arg;
|
| }
|
|
|
| void BytecodeGenerator::VisitCall(Call* expr) {
|
| @@ -2606,18 +2324,15 @@ void BytecodeGenerator::VisitCall(Call* expr) {
|
| return VisitCallSuper(expr);
|
| }
|
|
|
| - // Prepare the callee and the receiver to the function call. This depends on
|
| - // the semantics of the underlying call type.
|
| + Register callee = register_allocator()->NewRegister();
|
|
|
| - // The receiver and arguments need to be allocated consecutively for
|
| - // Call(). We allocate the callee and receiver consecutively for calls to
|
| - // %LoadLookupSlotForCall. Future optimizations could avoid this there are
|
| - // no arguments or the receiver and arguments are already consecutive.
|
| - ZoneList<Expression*>* args = expr->arguments();
|
| - register_allocator()->PrepareForConsecutiveAllocations(args->length() + 2);
|
| - Register callee = register_allocator()->NextConsecutiveRegister();
|
| - Register receiver = register_allocator()->NextConsecutiveRegister();
|
| + // Add an argument register for the receiver.
|
| + RegisterList args =
|
| + register_allocator()->NewRegisterList(expr->arguments()->length() + 1);
|
| + Register receiver = args[0];
|
|
|
| + // Prepare the callee and the receiver to the function call. This depends on
|
| + // the semantics of the underlying call type.
|
| switch (call_type) {
|
| case Call::NAMED_PROPERTY_CALL:
|
| case Call::KEYED_PROPERTY_CALL: {
|
| @@ -2650,8 +2365,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
|
| builder()
|
| ->LoadLiteral(variable->name())
|
| .StoreAccumulatorInRegister(name)
|
| - .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name, 1,
|
| - callee);
|
| + .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name, callee);
|
| break;
|
| }
|
| // Fall through.
|
| @@ -2659,8 +2373,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
|
| }
|
| case Call::OTHER_CALL: {
|
| builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
|
| - VisitForAccumulatorValue(callee_expr);
|
| - builder()->StoreAccumulatorInRegister(callee);
|
| + VisitForRegisterValue(callee_expr, callee);
|
| break;
|
| }
|
| case Call::NAMED_SUPER_PROPERTY_CALL: {
|
| @@ -2680,42 +2393,34 @@ void BytecodeGenerator::VisitCall(Call* expr) {
|
| break;
|
| }
|
|
|
| - // Evaluate all arguments to the function call and store in sequential
|
| + // Evaluate all arguments to the function call and store in sequential args
|
| // registers.
|
| - Register arg = VisitArguments(args);
|
| - CHECK(args->length() == 0 || arg.index() == receiver.index() + 1);
|
| + VisitArguments(expr->arguments(), args, 1);
|
|
|
| // 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) {
|
| + if (call_type == Call::POSSIBLY_EVAL_CALL &&
|
| + expr->arguments()->length() > 0) {
|
| RegisterAllocationScope inner_register_scope(this);
|
| - register_allocator()->PrepareForConsecutiveAllocations(6);
|
| - Register callee_for_eval = register_allocator()->NextConsecutiveRegister();
|
| - Register source = register_allocator()->NextConsecutiveRegister();
|
| - Register function = register_allocator()->NextConsecutiveRegister();
|
| - Register language = register_allocator()->NextConsecutiveRegister();
|
| - Register eval_scope_position =
|
| - register_allocator()->NextConsecutiveRegister();
|
| - Register eval_position = register_allocator()->NextConsecutiveRegister();
|
| -
|
| // Set up arguments for ResolvePossiblyDirectEval by copying callee, source
|
| // strings and function closure, and loading language and
|
| // position.
|
| + RegisterList runtime_call_args = register_allocator()->NewRegisterList(6);
|
| builder()
|
| - ->MoveRegister(callee, callee_for_eval)
|
| - .MoveRegister(arg, source)
|
| - .MoveRegister(Register::function_closure(), function)
|
| + ->MoveRegister(callee, runtime_call_args[0])
|
| + .MoveRegister(args[1], runtime_call_args[1])
|
| + .MoveRegister(Register::function_closure(), runtime_call_args[2])
|
| .LoadLiteral(Smi::FromInt(language_mode()))
|
| - .StoreAccumulatorInRegister(language)
|
| + .StoreAccumulatorInRegister(runtime_call_args[3])
|
| .LoadLiteral(
|
| Smi::FromInt(execution_context()->scope()->start_position()))
|
| - .StoreAccumulatorInRegister(eval_scope_position)
|
| + .StoreAccumulatorInRegister(runtime_call_args[4])
|
| .LoadLiteral(Smi::FromInt(expr->position()))
|
| - .StoreAccumulatorInRegister(eval_position);
|
| + .StoreAccumulatorInRegister(runtime_call_args[5]);
|
|
|
| // Call ResolvePossiblyDirectEval and modify the callee.
|
| builder()
|
| - ->CallRuntime(Runtime::kResolvePossiblyDirectEval, callee_for_eval, 6)
|
| + ->CallRuntime(Runtime::kResolvePossiblyDirectEval, runtime_call_args)
|
| .StoreAccumulatorInRegister(callee);
|
| }
|
|
|
| @@ -2732,9 +2437,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
|
| } else {
|
| feedback_slot_index = feedback_index(expr->CallFeedbackICSlot());
|
| }
|
| - builder()->Call(callee, receiver, 1 + args->length(), feedback_slot_index,
|
| - expr->tail_call_mode());
|
| - execution_result()->SetResultInAccumulator();
|
| + builder()->Call(callee, args, feedback_slot_index, expr->tail_call_mode());
|
| }
|
|
|
| void BytecodeGenerator::VisitCallSuper(Call* expr) {
|
| @@ -2742,17 +2445,15 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) {
|
| SuperCallReference* super = expr->expression()->AsSuperCallReference();
|
|
|
| // Prepare the constructor to the super call.
|
| - Register this_function = register_allocator()->NewRegister();
|
| - VisitForAccumulatorValue(super->this_function_var());
|
| - builder()
|
| - ->StoreAccumulatorInRegister(this_function)
|
| - .CallRuntime(Runtime::kInlineGetSuperConstructor, this_function, 1);
|
| + Register this_function = VisitForRegisterValue(super->this_function_var());
|
| + builder()->CallRuntime(Runtime::kInlineGetSuperConstructor, this_function);
|
|
|
| Register constructor = this_function; // Re-use dead this_function register.
|
| builder()->StoreAccumulatorInRegister(constructor);
|
|
|
| - ZoneList<Expression*>* args = expr->arguments();
|
| - Register first_arg = VisitArguments(args);
|
| + RegisterList args =
|
| + register_allocator()->NewRegisterList(expr->arguments()->length());
|
| + VisitArguments(expr->arguments(), args);
|
|
|
| // The new target is loaded into the accumulator from the
|
| // {new.target} variable.
|
| @@ -2766,52 +2467,45 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) {
|
| // Type feedback is not necessary for super constructor calls. The type
|
| // information can be inferred in most cases. Slot id 0 indicates type
|
| // feedback is not required.
|
| - builder()->New(constructor, first_arg, args->length(), 0);
|
| - execution_result()->SetResultInAccumulator();
|
| + builder()->New(constructor, args, 0);
|
| }
|
|
|
| void BytecodeGenerator::VisitCallNew(CallNew* expr) {
|
| - Register constructor = register_allocator()->NewRegister();
|
| - VisitForAccumulatorValue(expr->expression());
|
| - builder()->StoreAccumulatorInRegister(constructor);
|
| -
|
| - ZoneList<Expression*>* args = expr->arguments();
|
| - Register first_arg = VisitArguments(args);
|
| + Register constructor = VisitForRegisterValue(expr->expression());
|
| + RegisterList args =
|
| + register_allocator()->NewRegisterList(expr->arguments()->length());
|
| + VisitArguments(expr->arguments(), args);
|
|
|
| builder()->SetExpressionPosition(expr);
|
| // The accumulator holds new target which is the same as the
|
| // constructor for CallNew.
|
| builder()
|
| ->LoadAccumulatorWithRegister(constructor)
|
| - .New(constructor, first_arg, args->length(),
|
| - feedback_index(expr->CallNewFeedbackSlot()));
|
| - execution_result()->SetResultInAccumulator();
|
| + .New(constructor, args, feedback_index(expr->CallNewFeedbackSlot()));
|
| }
|
|
|
| void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
| - ZoneList<Expression*>* args = expr->arguments();
|
| if (expr->is_jsruntime()) {
|
| // Allocate a register for the receiver and load it with undefined.
|
| - register_allocator()->PrepareForConsecutiveAllocations(1 + args->length());
|
| - Register receiver = register_allocator()->NextConsecutiveRegister();
|
| + RegisterList args =
|
| + register_allocator()->NewRegisterList(expr->arguments()->length() + 1);
|
| + Register receiver = args[0];
|
| builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
|
| - Register first_arg = VisitArguments(args);
|
| - CHECK(args->length() == 0 || first_arg.index() == receiver.index() + 1);
|
| - builder()->CallJSRuntime(expr->context_index(), receiver,
|
| - 1 + args->length());
|
| + VisitArguments(expr->arguments(), args, 1);
|
| + builder()->CallJSRuntime(expr->context_index(), args);
|
| } else {
|
| // Evaluate all arguments to the runtime call.
|
| - Register first_arg = VisitArguments(args);
|
| + RegisterList args =
|
| + register_allocator()->NewRegisterList(expr->arguments()->length());
|
| + VisitArguments(expr->arguments(), args);
|
| Runtime::FunctionId function_id = expr->function()->function_id;
|
| - builder()->CallRuntime(function_id, first_arg, args->length());
|
| + builder()->CallRuntime(function_id, args);
|
| }
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
|
| VisitForEffect(expr->expression());
|
| builder()->LoadUndefined();
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
|
| @@ -2825,7 +2519,6 @@ void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
|
| VisitForAccumulatorValue(expr->expression());
|
| }
|
| builder()->TypeOf();
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
|
| @@ -2842,7 +2535,6 @@ void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
|
| } else {
|
| VisitForAccumulatorValue(expr->expression());
|
| builder()->LogicalNot();
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
| }
|
|
|
| @@ -2917,7 +2609,7 @@ void BytecodeGenerator::VisitDelete(UnaryOperation* expr) {
|
| builder()
|
| ->LoadLiteral(variable->name())
|
| .StoreAccumulatorInRegister(name_reg)
|
| - .CallRuntime(Runtime::kDeleteLookupSlot, name_reg, 1);
|
| + .CallRuntime(Runtime::kDeleteLookupSlot, name_reg);
|
| break;
|
| }
|
| default:
|
| @@ -2928,7 +2620,6 @@ void BytecodeGenerator::VisitDelete(UnaryOperation* expr) {
|
| VisitForEffect(expr->expression());
|
| builder()->LoadTrue();
|
| }
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
|
| @@ -2941,7 +2632,8 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
|
| bool is_postfix = expr->is_postfix() && !execution_result()->IsEffect();
|
|
|
| // Evaluate LHS expression and get old value.
|
| - Register object, home_object, key, old_value, value;
|
| + Register object, key, old_value;
|
| + RegisterList super_property_args;
|
| Handle<String> name;
|
| switch (assign_type) {
|
| case VARIABLE: {
|
| @@ -2969,43 +2661,35 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
|
| break;
|
| }
|
| case NAMED_SUPER_PROPERTY: {
|
| - register_allocator()->PrepareForConsecutiveAllocations(4);
|
| - object = register_allocator()->NextConsecutiveRegister();
|
| - home_object = register_allocator()->NextConsecutiveRegister();
|
| - key = register_allocator()->NextConsecutiveRegister();
|
| - value = register_allocator()->NextConsecutiveRegister();
|
| + super_property_args = register_allocator()->NewRegisterList(4);
|
| + RegisterList load_super_args = super_property_args.Truncate(3);
|
| SuperPropertyReference* super_property =
|
| property->obj()->AsSuperPropertyReference();
|
| - VisitForRegisterValue(super_property->this_var(), object);
|
| - VisitForRegisterValue(super_property->home_object(), home_object);
|
| + VisitForRegisterValue(super_property->this_var(), load_super_args[0]);
|
| + VisitForRegisterValue(super_property->home_object(), load_super_args[1]);
|
| builder()
|
| ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
|
| - .StoreAccumulatorInRegister(key);
|
| - BuildNamedSuperPropertyLoad(object, home_object, key);
|
| + .StoreAccumulatorInRegister(load_super_args[2])
|
| + .CallRuntime(Runtime::kLoadFromSuper, load_super_args);
|
| break;
|
| }
|
| case KEYED_SUPER_PROPERTY: {
|
| - register_allocator()->PrepareForConsecutiveAllocations(4);
|
| - object = register_allocator()->NextConsecutiveRegister();
|
| - home_object = register_allocator()->NextConsecutiveRegister();
|
| - key = register_allocator()->NextConsecutiveRegister();
|
| - value = register_allocator()->NextConsecutiveRegister();
|
| - builder()->StoreAccumulatorInRegister(value);
|
| + super_property_args = register_allocator()->NewRegisterList(4);
|
| + RegisterList load_super_args = super_property_args.Truncate(3);
|
| SuperPropertyReference* super_property =
|
| property->obj()->AsSuperPropertyReference();
|
| - VisitForRegisterValue(super_property->this_var(), object);
|
| - VisitForRegisterValue(super_property->home_object(), home_object);
|
| - VisitForRegisterValue(property->key(), key);
|
| - BuildKeyedSuperPropertyLoad(object, home_object, key);
|
| + VisitForRegisterValue(super_property->this_var(), load_super_args[0]);
|
| + VisitForRegisterValue(super_property->home_object(), load_super_args[1]);
|
| + VisitForRegisterValue(property->key(), load_super_args[2]);
|
| + builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, load_super_args);
|
| break;
|
| }
|
| }
|
|
|
| // Save result for postfix expressions.
|
| if (is_postfix) {
|
| - old_value = register_allocator()->outer()->NewRegister();
|
| -
|
| // Convert old value into a number before saving it.
|
| + old_value = register_allocator()->NewRegister();
|
| builder()->ConvertAccumulatorToNumber(old_value);
|
| }
|
|
|
| @@ -3033,22 +2717,22 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
|
| break;
|
| }
|
| case NAMED_SUPER_PROPERTY: {
|
| - builder()->StoreAccumulatorInRegister(value);
|
| - BuildNamedSuperPropertyStore(object, home_object, key, value);
|
| + builder()
|
| + ->StoreAccumulatorInRegister(super_property_args[3])
|
| + .CallRuntime(StoreToSuperRuntimeId(), super_property_args);
|
| break;
|
| }
|
| case KEYED_SUPER_PROPERTY: {
|
| - builder()->StoreAccumulatorInRegister(value);
|
| - BuildKeyedSuperPropertyStore(object, home_object, key, value);
|
| + builder()
|
| + ->StoreAccumulatorInRegister(super_property_args[3])
|
| + .CallRuntime(StoreKeyedToSuperRuntimeId(), super_property_args);
|
| break;
|
| }
|
| }
|
|
|
| // Restore old value for postfix expressions.
|
| if (is_postfix) {
|
| - execution_result()->SetResultInRegister(old_value);
|
| - } else {
|
| - execution_result()->SetResultInAccumulator();
|
| + builder()->LoadAccumulatorWithRegister(old_value);
|
| }
|
| }
|
|
|
| @@ -3075,7 +2759,6 @@ void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
| builder()->SetExpressionPosition(expr);
|
| FeedbackVectorSlot slot = expr->CompareOperationFeedbackSlot();
|
| builder()->CompareOperation(expr->op(), lhs, feedback_index(slot));
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
|
| @@ -3085,7 +2768,6 @@ void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
|
| VisitForAccumulatorValue(expr->right());
|
| FeedbackVectorSlot slot = expr->BinaryOperationFeedbackSlot();
|
| builder()->BinaryOperation(expr->op(), lhs, feedback_index(slot));
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
|
| @@ -3095,7 +2777,7 @@ void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
|
| }
|
|
|
| void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) {
|
| - execution_result()->SetResultInRegister(Register::function_closure());
|
| + builder()->LoadAccumulatorWithRegister(Register::function_closure());
|
| }
|
|
|
| void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) {
|
| @@ -3105,8 +2787,7 @@ void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) {
|
|
|
| void BytecodeGenerator::VisitSuperPropertyReference(
|
| SuperPropertyReference* expr) {
|
| - builder()->CallRuntime(Runtime::kThrowUnsupportedSuperError, Register(0), 0);
|
| - execution_result()->SetResultInAccumulator();
|
| + builder()->CallRuntime(Runtime::kThrowUnsupportedSuperError);
|
| }
|
|
|
| void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {
|
| @@ -3146,7 +2827,6 @@ void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
|
| VisitForAccumulatorValue(right);
|
| builder()->Bind(&end_label);
|
| }
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
| }
|
|
|
| @@ -3182,7 +2862,6 @@ void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {
|
| VisitForAccumulatorValue(right);
|
| builder()->Bind(&end_label);
|
| }
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
| }
|
|
|
| @@ -3191,44 +2870,36 @@ void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) {
|
| }
|
|
|
| void BytecodeGenerator::BuildNewLocalActivationContext() {
|
| - AccumulatorResultScope accumulator_execution_result(this);
|
| + ValueResultScope value_execution_result(this);
|
| Scope* scope = this->scope();
|
|
|
| // Create the appropriate context.
|
| if (scope->is_script_scope()) {
|
| - RegisterAllocationScope register_scope(this);
|
| - register_allocator()->PrepareForConsecutiveAllocations(2);
|
| - Register closure = register_allocator()->NextConsecutiveRegister();
|
| - Register scope_info = register_allocator()->NextConsecutiveRegister();
|
| + RegisterList args = register_allocator()->NewRegisterList(2);
|
| builder()
|
| ->LoadAccumulatorWithRegister(Register::function_closure())
|
| - .StoreAccumulatorInRegister(closure)
|
| + .StoreAccumulatorInRegister(args[0])
|
| .LoadLiteral(scope->scope_info())
|
| - .StoreAccumulatorInRegister(scope_info)
|
| - .CallRuntime(Runtime::kNewScriptContext, closure, 2);
|
| + .StoreAccumulatorInRegister(args[1])
|
| + .CallRuntime(Runtime::kNewScriptContext, args);
|
| } else if (scope->is_module_scope()) {
|
| // We don't need to do anything for the outer script scope.
|
| DCHECK(scope->outer_scope()->is_script_scope());
|
|
|
| - RegisterAllocationScope register_scope(this);
|
| - register_allocator()->PrepareForConsecutiveAllocations(3);
|
| - Register module = register_allocator()->NextConsecutiveRegister();
|
| - Register closure = register_allocator()->NextConsecutiveRegister();
|
| - Register scope_info = register_allocator()->NextConsecutiveRegister();
|
| // A JSFunction representing a module is called with the module object as
|
| // its sole argument, which we pass on to PushModuleContext.
|
| + RegisterList args = register_allocator()->NewRegisterList(3);
|
| builder()
|
| - ->MoveRegister(builder()->Parameter(1), module)
|
| + ->MoveRegister(builder()->Parameter(1), args[0])
|
| .LoadAccumulatorWithRegister(Register::function_closure())
|
| - .StoreAccumulatorInRegister(closure)
|
| + .StoreAccumulatorInRegister(args[1])
|
| .LoadLiteral(scope->scope_info())
|
| - .StoreAccumulatorInRegister(scope_info)
|
| - .CallRuntime(Runtime::kPushModuleContext, module, 3);
|
| + .StoreAccumulatorInRegister(args[2])
|
| + .CallRuntime(Runtime::kPushModuleContext, args);
|
| } else {
|
| int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
|
| builder()->CreateFunctionContext(slot_count);
|
| }
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::BuildLocalActivationContextInitialization() {
|
| @@ -3260,28 +2931,26 @@ void BytecodeGenerator::BuildLocalActivationContextInitialization() {
|
| }
|
|
|
| void BytecodeGenerator::BuildNewLocalBlockContext(Scope* scope) {
|
| - AccumulatorResultScope accumulator_execution_result(this);
|
| + ValueResultScope value_execution_result(this);
|
| DCHECK(scope->is_block_scope());
|
|
|
| VisitFunctionClosureForContext();
|
| builder()->CreateBlockContext(scope->scope_info());
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::BuildNewLocalWithContext(Scope* scope) {
|
| - AccumulatorResultScope accumulator_execution_result(this);
|
| + ValueResultScope value_execution_result(this);
|
|
|
| Register extension_object = register_allocator()->NewRegister();
|
|
|
| builder()->ConvertAccumulatorToObject(extension_object);
|
| VisitFunctionClosureForContext();
|
| builder()->CreateWithContext(extension_object, scope->scope_info());
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::BuildNewLocalCatchContext(Variable* variable,
|
| Scope* scope) {
|
| - AccumulatorResultScope accumulator_execution_result(this);
|
| + ValueResultScope value_execution_result(this);
|
| DCHECK(variable->IsContextSlot());
|
|
|
| Register exception = register_allocator()->NewRegister();
|
| @@ -3289,17 +2958,14 @@ void BytecodeGenerator::BuildNewLocalCatchContext(Variable* variable,
|
| VisitFunctionClosureForContext();
|
| builder()->CreateCatchContext(exception, variable->name(),
|
| scope->scope_info());
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| void BytecodeGenerator::VisitObjectLiteralAccessor(
|
| Register home_object, ObjectLiteralProperty* property, Register value_out) {
|
| - // TODO(rmcilroy): Replace value_out with VisitForRegister();
|
| if (property == nullptr) {
|
| builder()->LoadNull().StoreAccumulatorInRegister(value_out);
|
| } else {
|
| - VisitForAccumulatorValue(property->value());
|
| - builder()->StoreAccumulatorInRegister(value_out);
|
| + VisitForRegisterValue(property->value(), value_out);
|
| VisitSetHomeObject(value_out, home_object, property);
|
| }
|
| }
|
| @@ -3367,7 +3033,7 @@ void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {
|
| }
|
|
|
| void BytecodeGenerator::VisitFunctionClosureForContext() {
|
| - AccumulatorResultScope accumulator_execution_result(this);
|
| + ValueResultScope value_execution_result(this);
|
| DeclarationScope* closure_scope =
|
| execution_context()->scope()->GetClosureScope();
|
| if (closure_scope->is_script_scope()) {
|
| @@ -3390,12 +3056,11 @@ void BytecodeGenerator::VisitFunctionClosureForContext() {
|
| closure_scope->is_module_scope());
|
| builder()->LoadAccumulatorWithRegister(Register::function_closure());
|
| }
|
| - execution_result()->SetResultInAccumulator();
|
| }
|
|
|
| // Visits the expression |expr| and places the result in the accumulator.
|
| void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) {
|
| - AccumulatorResultScope accumulator_scope(this);
|
| + ValueResultScope accumulator_scope(this);
|
| Visit(expr);
|
| }
|
|
|
| @@ -3416,16 +3081,17 @@ void BytecodeGenerator::VisitForEffect(Expression* expr) {
|
| // Visits the expression |expr| and returns the register containing
|
| // the expression result.
|
| Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) {
|
| - RegisterResultScope register_scope(this);
|
| - Visit(expr);
|
| - return register_scope.ResultRegister();
|
| + VisitForAccumulatorValue(expr);
|
| + Register result = register_allocator()->NewRegister();
|
| + builder()->StoreAccumulatorInRegister(result);
|
| + return result;
|
| }
|
|
|
| // Visits the expression |expr| and stores the expression result in
|
| // |destination|.
|
| void BytecodeGenerator::VisitForRegisterValue(Expression* expr,
|
| Register destination) {
|
| - AccumulatorResultScope register_scope(this);
|
| + ValueResultScope register_scope(this);
|
| Visit(expr);
|
| builder()->StoreAccumulatorInRegister(destination);
|
| }
|
| @@ -3474,6 +3140,16 @@ int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
|
| return TypeFeedbackVector::GetIndex(slot);
|
| }
|
|
|
| +Runtime::FunctionId BytecodeGenerator::StoreToSuperRuntimeId() {
|
| + return is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict
|
| + : Runtime::kStoreToSuper_Sloppy;
|
| +}
|
| +
|
| +Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() {
|
| + return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict
|
| + : Runtime::kStoreKeyedToSuper_Sloppy;
|
| +}
|
| +
|
| } // namespace interpreter
|
| } // namespace internal
|
| } // namespace v8
|
|
|