summaryrefslogtreecommitdiff
path: root/deps/v8/src/interpreter/bytecode-generator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/interpreter/bytecode-generator.cc')
-rw-r--r--deps/v8/src/interpreter/bytecode-generator.cc1254
1 files changed, 508 insertions, 746 deletions
diff --git a/deps/v8/src/interpreter/bytecode-generator.cc b/deps/v8/src/interpreter/bytecode-generator.cc
index 6ff43a4170..db5a596b85 100644
--- a/deps/v8/src/interpreter/bytecode-generator.cc
+++ b/deps/v8/src/interpreter/bytecode-generator.cc
@@ -4,15 +4,16 @@
#include "src/interpreter/bytecode-generator.h"
+#include "src/ast/compile-time-value.h"
#include "src/ast/scopes.h"
#include "src/code-stubs.h"
+#include "src/compilation-info.h"
#include "src/compiler.h"
#include "src/interpreter/bytecode-flags.h"
#include "src/interpreter/bytecode-label.h"
#include "src/interpreter/bytecode-register-allocator.h"
#include "src/interpreter/control-flow-builders.h"
#include "src/objects.h"
-#include "src/parsing/parser.h"
#include "src/parsing/token.h"
namespace v8 {
@@ -216,10 +217,10 @@ class BytecodeGenerator::ControlScopeForTopLevel final
case CMD_CONTINUE:
UNREACHABLE();
case CMD_RETURN:
- generator()->builder()->Return();
+ generator()->BuildReturn();
return true;
case CMD_RETHROW:
- generator()->builder()->ReThrow();
+ generator()->BuildReThrow();
return true;
}
return false;
@@ -310,7 +311,7 @@ class BytecodeGenerator::ControlScopeForTryCatch final
case CMD_RETURN:
break;
case CMD_RETHROW:
- generator()->builder()->ReThrow();
+ generator()->BuildReThrow();
return true;
}
return false;
@@ -373,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);
+ generator_->register_allocator()->ReleaseRegisters(
+ outer_next_register_index_);
}
- Register NextConsecutiveRegister() {
- 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_;
+ 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; }
@@ -453,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);
};
@@ -485,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) {}
-};
-
-// 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 {
- public:
- explicit AccumulatorResultScope(BytecodeGenerator* generator)
- : ExpressionResultScope(generator, Expression::kValue) {}
-
- virtual void SetResultInAccumulator() { set_result_identified(); }
-
- virtual void SetResultInRegister(Register reg) {
- builder()->LoadAccumulatorWithRegister(reg);
- set_result_identified();
- }
+ : ExpressionResultScope(generator, Expression::kEffect) {}
};
// 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 {
+// evaluated should go into the interpreter's accumulator.
+class BytecodeGenerator::ValueResultScope final : public ExpressionResultScope {
public:
- explicit RegisterResultScope(BytecodeGenerator* generator)
+ explicit ValueResultScope(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
@@ -554,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_; }
@@ -677,22 +567,17 @@ 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),
home_object_symbol_(info->isolate()->factory()->home_object_symbol()),
prototype_string_(info->isolate()->factory()->prototype_string()) {
- InitializeAstVisitor(info->isolate()->stack_guard()->real_climit());
}
Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) {
- // Create an inner HandleScope to avoid unnecessarily canonicalizing handles
- // created as part of bytecode finalization.
- HandleScope scope(isolate);
AllocateDeferredConstants();
if (HasStackOverflow()) return Handle<BytecodeArray>();
- return scope.CloseAndEscape(builder()->ToBytecodeArray(isolate));
+ return builder()->ToBytecodeArray(isolate);
}
void BytecodeGenerator::AllocateDeferredConstants() {
@@ -726,11 +611,13 @@ void BytecodeGenerator::AllocateDeferredConstants() {
}
}
-void BytecodeGenerator::GenerateBytecode() {
+void BytecodeGenerator::GenerateBytecode(uintptr_t stack_limit) {
DisallowHeapAllocation no_allocation;
DisallowHandleAllocation no_handles;
DisallowHandleDereference no_deref;
+ InitializeAstVisitor(stack_limit);
+
// Initialize the incoming context.
ContextScope incoming_context(this, scope(), false);
@@ -744,12 +631,11 @@ void BytecodeGenerator::GenerateBytecode() {
VisitGeneratorPrologue();
}
- // Build function context only if there are context allocated variables.
if (scope()->NeedsContext()) {
// Push a new inner context scope for the function.
- VisitNewLocalFunctionContext();
+ BuildNewLocalActivationContext();
ContextScope local_function_context(this, scope(), false);
- VisitBuildLocalActivationContext();
+ BuildLocalActivationContextInitialization();
GenerateBytecodeBody();
} else {
GenerateBytecodeBody();
@@ -763,7 +649,13 @@ void BytecodeGenerator::GenerateBytecode() {
if (!label.is_bound()) builder()->Bind(&label);
}
- builder()->EnsureReturn();
+ // Emit an implicit return instruction in case control flow can fall off the
+ // end of the function without an explicit return being present on all paths.
+ if (builder()->RequiresImplicitReturn()) {
+ builder()->LoadUndefined();
+ BuildReturn();
+ }
+ DCHECK(!builder()->RequiresImplicitReturn());
}
void BytecodeGenerator::GenerateBytecodeBody() {
@@ -771,8 +663,7 @@ void BytecodeGenerator::GenerateBytecodeBody() {
VisitArgumentsObject(scope()->arguments());
// Build rest arguments array if it is used.
- int rest_index;
- Variable* rest_parameter = scope()->rest_parameter(&rest_index);
+ Variable* rest_parameter = scope()->rest_parameter();
VisitRestArgumentsArray(rest_parameter);
// Build assignment to {.this_function} variable if it is used.
@@ -781,10 +672,8 @@ void BytecodeGenerator::GenerateBytecodeBody() {
// Build assignment to {new.target} variable if it is used.
VisitNewTargetVariable(scope()->new_target_var());
- // TODO(rmcilroy): Emit tracing call if requested to do so.
- if (FLAG_trace) {
- UNIMPLEMENTED();
- }
+ // Emit tracing call if requested to do so.
+ if (FLAG_trace) builder()->CallRuntime(Runtime::kTraceEnter);
// Visit declarations within the function scope.
VisitDeclarations(scope()->declarations());
@@ -829,14 +718,6 @@ void BytecodeGenerator::VisitIterationHeader(IterationStatement* stmt,
loop_builder->LoopHeader(&resume_points_in_loop);
- // Insert an explicit {OsrPoll} right after the loop header, to trigger
- // on-stack replacement when armed for the given loop nesting depth.
- if (FLAG_ignition_osr) {
- // TODO(4764): Merge this with another bytecode (e.g. {Jump} back edge).
- int level = Min(loop_depth_, AbstractCode::kMaxLoopNestingMarker - 1);
- builder()->OsrPoll(level);
- }
-
if (stmt->yield_count() > 0) {
// If we are not resuming, fall through to loop body.
// If we are resuming, perform state dispatch.
@@ -882,7 +763,7 @@ void BytecodeGenerator::VisitGeneratorPrologue() {
void BytecodeGenerator::VisitBlock(Block* stmt) {
// Visit declarations and statements.
if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) {
- VisitNewLocalBlockContext(stmt->scope());
+ BuildNewLocalBlockContext(stmt->scope());
ContextScope scope(this, stmt->scope());
VisitBlockDeclarationsAndStatements(stmt);
} else {
@@ -903,7 +784,6 @@ void BytecodeGenerator::VisitBlockDeclarationsAndStatements(Block* stmt) {
void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
Variable* variable = decl->proxy()->var();
switch (variable->location()) {
- case VariableLocation::GLOBAL:
case VariableLocation::UNALLOCATED: {
DCHECK(!variable->binding_needs_init());
FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot();
@@ -926,8 +806,9 @@ void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
break;
case VariableLocation::CONTEXT:
if (variable->binding_needs_init()) {
+ DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope()));
builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(),
- variable->index());
+ variable->index(), 0);
}
break;
case VariableLocation::LOOKUP: {
@@ -939,18 +820,24 @@ void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
builder()
->LoadLiteral(variable->name())
.StoreAccumulatorInRegister(name)
- .CallRuntime(Runtime::kDeclareEvalVar, name, 1);
+ .CallRuntime(Runtime::kDeclareEvalVar, name);
break;
}
case VariableLocation::MODULE:
- UNREACHABLE();
+ if (variable->IsExport() && variable->binding_needs_init()) {
+ builder()->LoadTheHole();
+ VisitVariableAssignment(variable, Token::INIT,
+ FeedbackVectorSlot::Invalid());
+ }
+ // Nothing to do for imports.
+ break;
}
}
void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
Variable* variable = decl->proxy()->var();
+ DCHECK(variable->mode() == LET || variable->mode() == VAR);
switch (variable->location()) {
- case VariableLocation::GLOBAL:
case VariableLocation::UNALLOCATED: {
FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot();
globals_builder()->AddFunctionDeclaration(slot, decl->fun());
@@ -959,8 +846,6 @@ void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
case VariableLocation::PARAMETER:
case VariableLocation::LOCAL: {
VisitForAccumulatorValue(decl->fun());
- DCHECK(variable->mode() == LET || variable->mode() == VAR ||
- variable->mode() == CONST);
VisitVariableAssignment(variable, Token::INIT,
FeedbackVectorSlot::Invalid());
break;
@@ -968,23 +853,27 @@ void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
case VariableLocation::CONTEXT: {
DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope()));
VisitForAccumulatorValue(decl->fun());
- builder()->StoreContextSlot(execution_context()->reg(),
- variable->index());
+ builder()->StoreContextSlot(execution_context()->reg(), variable->index(),
+ 0);
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:
- UNREACHABLE();
+ DCHECK_EQ(variable->mode(), LET);
+ DCHECK(variable->IsExport());
+ VisitForAccumulatorValue(decl->fun());
+ VisitVariableAssignment(variable, Token::INIT,
+ FeedbackVectorSlot::Invalid());
+ break;
}
}
@@ -1002,20 +891,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());
@@ -1097,7 +981,7 @@ void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
builder()->SetStatementPosition(stmt);
VisitForAccumulatorValue(stmt->expression());
- VisitNewLocalWithContext();
+ BuildNewLocalWithContext(stmt->scope());
VisitInScope(stmt->statement(), stmt->scope());
}
@@ -1126,7 +1010,9 @@ void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
// Perform label comparison as if via '===' with tag.
VisitForAccumulatorValue(clause->label());
- builder()->CompareOperation(Token::Value::EQ_STRICT, tag);
+ builder()->CompareOperation(
+ Token::Value::EQ_STRICT, tag,
+ feedback_index(clause->CompareOperationFeedbackSlot()));
switch_builder.Case(i);
}
@@ -1168,13 +1054,16 @@ void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
} else if (stmt->cond()->ToBooleanIsTrue()) {
VisitIterationHeader(stmt, &loop_builder);
VisitIterationBody(stmt, &loop_builder);
- loop_builder.JumpToHeader();
+ loop_builder.JumpToHeader(loop_depth_);
} else {
VisitIterationHeader(stmt, &loop_builder);
VisitIterationBody(stmt, &loop_builder);
builder()->SetExpressionAsStatementPosition(stmt->cond());
- VisitForTest(stmt->cond(), loop_builder.header_labels(),
- loop_builder.break_labels(), TestFallthrough::kElse);
+ BytecodeLabels loop_backbranch(zone());
+ VisitForTest(stmt->cond(), &loop_backbranch, loop_builder.break_labels(),
+ TestFallthrough::kThen);
+ loop_backbranch.Bind(builder());
+ loop_builder.JumpToHeader(loop_depth_);
}
loop_builder.EndLoop();
}
@@ -1195,7 +1084,7 @@ void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
loop_body.Bind(builder());
}
VisitIterationBody(stmt, &loop_builder);
- loop_builder.JumpToHeader();
+ loop_builder.JumpToHeader(loop_depth_);
loop_builder.EndLoop();
}
@@ -1223,7 +1112,7 @@ void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
builder()->SetStatementPosition(stmt->next());
Visit(stmt->next());
}
- loop_builder.JumpToHeader();
+ loop_builder.JumpToHeader(loop_depth_);
loop_builder.EndLoop();
}
@@ -1265,36 +1154,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;
}
}
@@ -1316,15 +1197,12 @@ void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
builder()->JumpIfUndefined(&subject_undefined_label);
builder()->JumpIfNull(&subject_null_label);
Register receiver = register_allocator()->NewRegister();
- builder()->CastAccumulatorToJSObject(receiver);
+ 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);
// Set up loop counter
Register index = register_allocator()->NewRegister();
@@ -1334,17 +1212,17 @@ void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// The loop
VisitIterationHeader(stmt, &loop_builder);
builder()->SetExpressionAsStatementPosition(stmt->each());
- builder()->ForInDone(index, cache_length);
- loop_builder.BreakIfTrue();
- DCHECK(Register::AreContiguous(cache_type, cache_array));
+ builder()->ForInContinue(index, cache_length);
+ loop_builder.BreakIfFalse();
FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
- builder()->ForInNext(receiver, index, cache_type, feedback_index(slot));
+ builder()->ForInNext(receiver, index, triple.Truncate(2),
+ feedback_index(slot));
loop_builder.ContinueIfUndefined();
VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot());
VisitIterationBody(stmt, &loop_builder);
builder()->ForInStep(index);
builder()->StoreAccumulatorInRegister(index);
- loop_builder.JumpToHeader();
+ loop_builder.JumpToHeader(loop_depth_);
loop_builder.EndLoop();
builder()->Bind(&subject_null_label);
builder()->Bind(&subject_undefined_label);
@@ -1364,13 +1242,12 @@ void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
VisitForEffect(stmt->assign_each());
VisitIterationBody(stmt, &loop_builder);
- loop_builder.JumpToHeader();
+ loop_builder.JumpToHeader(loop_depth_);
loop_builder.EndLoop();
}
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.
@@ -1388,12 +1265,12 @@ void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
try_control_builder.EndTry();
// Create a catch scope that binds the exception.
- VisitNewLocalCatchContext(stmt->variable());
+ BuildNewLocalCatchContext(stmt->variable(), stmt->scope());
builder()->StoreAccumulatorInRegister(context);
// 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.
@@ -1406,7 +1283,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
@@ -1454,7 +1330,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.
@@ -1462,7 +1338,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();
@@ -1479,16 +1355,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)
@@ -1496,7 +1371,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();
@@ -1505,49 +1380,37 @@ 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();
// Create nodes to store method values into the literal.
for (int i = 0; i < expr->properties()->length(); i++) {
- ObjectLiteral::Property* property = expr->properties()->at(i);
+ ClassLiteral::Property* property = expr->properties()->at(i);
// Set-up receiver.
Register new_receiver = property->is_static() ? literal : prototype;
@@ -1557,17 +1420,23 @@ void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
}
VisitForAccumulatorValue(property->key());
- builder()->CastAccumulatorToName(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.
+ builder()->ConvertAccumulatorToName(key);
+
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) {
@@ -1578,51 +1447,36 @@ void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
}
switch (property->kind()) {
- case ObjectLiteral::Property::CONSTANT:
- case ObjectLiteral::Property::MATERIALIZED_LITERAL:
- case ObjectLiteral::Property::PROTOTYPE:
- // Invalid properties for ES6 classes.
- UNREACHABLE();
- break;
- case ObjectLiteral::Property::COMPUTED: {
+ 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 ObjectLiteral::Property::GETTER: {
+ case ClassLiteral::Property::GETTER: {
builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked,
- receiver, 4);
+ args.Truncate(4));
break;
}
- case ObjectLiteral::Property::SETTER: {
+ case ClassLiteral::Property::SETTER: {
builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked,
- receiver, 4);
+ args.Truncate(4));
+ break;
+ }
+ case ClassLiteral::Property::FIELD: {
+ UNREACHABLE();
break;
}
}
}
}
-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) {
@@ -1652,8 +1506,6 @@ void BytecodeGenerator::VisitConditional(Conditional* expr) {
VisitForAccumulatorValue(expr->else_expression());
builder()->Bind(&end_label);
}
-
- execution_result()->SetResultInAccumulator();
}
void BytecodeGenerator::VisitLiteral(Literal* expr) {
@@ -1674,7 +1526,6 @@ void BytecodeGenerator::VisitLiteral(Literal* expr) {
} else {
builder()->LoadLiteral(raw_value->value());
}
- execution_result()->SetResultInAccumulator();
}
}
@@ -1682,7 +1533,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) {
@@ -1693,7 +1543,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);
@@ -1737,23 +1587,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);
}
}
@@ -1761,15 +1605,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:
@@ -1790,23 +1629,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
@@ -1824,66 +1655,68 @@ 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()->CastAccumulatorToName(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) {
// Deep-copy the literal boilerplate.
+ int runtime_flags = expr->ComputeFlags();
+ bool use_fast_shallow_clone =
+ (runtime_flags & ArrayLiteral::kShallowElements) != 0 &&
+ expr->values()->length() <= JSArray::kInitialMaxFastElementArray;
+ uint8_t flags =
+ CreateArrayLiteralFlags::Encode(use_fast_shallow_clone, runtime_flags);
builder()->CreateArrayLiteral(expr->constant_elements(),
- expr->literal_index(),
- expr->ComputeFlags(true));
+ expr->literal_index(), flags);
Register index, literal;
// Evaluate all the non-constant subexpressions and store them into the
@@ -1915,7 +1748,6 @@ void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
// Restore literal array into accumulator.
builder()->LoadAccumulatorWithRegister(literal);
}
- execution_result()->SetResultInAccumulator();
}
void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
@@ -1953,7 +1785,6 @@ void BytecodeGenerator::VisitVariableLoad(Variable* variable,
BuildHoleCheckForVariableLoad(variable);
break;
}
- case VariableLocation::GLOBAL:
case VariableLocation::UNALLOCATED: {
builder()->LoadGlobal(feedback_index(slot), typeof_mode);
break;
@@ -1964,85 +1795,82 @@ void BytecodeGenerator::VisitVariableLoad(Variable* variable,
Register context_reg;
if (context) {
context_reg = context->reg();
+ depth = 0;
} else {
- 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.
- // TODO(mythria): Also update bytecode graph builder with correct depth
- // when this changes.
- builder()
- ->LoadAccumulatorWithRegister(execution_context()->reg())
- .StoreAccumulatorInRegister(context_reg);
- for (int i = 0; i < depth; ++i) {
- builder()
- ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
- .StoreAccumulatorInRegister(context_reg);
- }
+ context_reg = execution_context()->reg();
}
- builder()->LoadContextSlot(context_reg, variable->index());
+ builder()->LoadContextSlot(context_reg, variable->index(), depth);
BuildHoleCheckForVariableLoad(variable);
break;
}
case VariableLocation::LOOKUP: {
- builder()->LoadLookupSlot(variable->name(), typeof_mode);
+ switch (variable->mode()) {
+ case DYNAMIC_LOCAL: {
+ Variable* local_variable = variable->local_if_not_shadowed();
+ int depth =
+ execution_context()->ContextChainDepth(local_variable->scope());
+ builder()->LoadLookupContextSlot(variable->name(), typeof_mode,
+ local_variable->index(), depth);
+ BuildHoleCheckForVariableLoad(variable);
+ break;
+ }
+ case DYNAMIC_GLOBAL: {
+ int depth = scope()->ContextChainLengthUntilOutermostSloppyEval();
+ builder()->LoadLookupGlobalSlot(variable->name(), typeof_mode,
+ feedback_index(slot), depth);
+ break;
+ }
+ default:
+ builder()->LoadLookupSlot(variable->name(), typeof_mode);
+ }
+ break;
+ }
+ case VariableLocation::MODULE: {
+ ModuleDescriptor* descriptor = scope()->GetModuleScope()->module();
+ if (variable->IsExport()) {
+ auto it = descriptor->regular_exports().find(variable->raw_name());
+ DCHECK(it != descriptor->regular_exports().end());
+ Register export_name = register_allocator()->NewRegister();
+ builder()
+ ->LoadLiteral(it->second->export_name->string())
+ .StoreAccumulatorInRegister(export_name)
+ .CallRuntime(Runtime::kLoadModuleExport, export_name);
+ } else {
+ auto it = descriptor->regular_imports().find(variable->raw_name());
+ DCHECK(it != descriptor->regular_imports().end());
+ RegisterList args = register_allocator()->NewRegisterList(2);
+ builder()
+ ->LoadLiteral(it->second->import_name->string())
+ .StoreAccumulatorInRegister(args[0])
+ .LoadLiteral(Smi::FromInt(it->second->module_request))
+ .StoreAccumulatorInRegister(args[1])
+ .CallRuntime(Runtime::kLoadModuleImport, args);
+ }
+ BuildHoleCheckForVariableLoad(variable);
break;
}
- case VariableLocation::MODULE:
- UNREACHABLE();
}
- 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::BuildReturn() {
+ if (FLAG_trace) {
+ RegisterAllocationScope register_scope(this);
+ Register result = register_allocator()->NewRegister();
+ // Runtime returns {result} value, preserving accumulator.
+ builder()->StoreAccumulatorInRegister(result).CallRuntime(
+ Runtime::kTraceExit, result);
+ }
+ builder()->Return();
}
-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::BuildReThrow() { builder()->ReThrow(); }
void BytecodeGenerator::BuildAbort(BailoutReason bailout_reason) {
RegisterAllocationScope register_scope(this);
@@ -2050,14 +1878,14 @@ void BytecodeGenerator::BuildAbort(BailoutReason bailout_reason) {
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) {
@@ -2083,7 +1911,6 @@ void BytecodeGenerator::BuildThrowIfNotHole(Handle<String> name) {
void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable,
Token::Value op) {
- DCHECK(variable->mode() != CONST_LEGACY);
if (op != Token::INIT) {
// Perform an initialization check for let/const declared variables.
// E.g. let x = (x = 20); is not allowed.
@@ -2128,20 +1955,13 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
builder()->LoadAccumulatorWithRegister(value_temp);
}
- if ((mode == CONST || mode == CONST_LEGACY) && op != Token::INIT) {
- if (mode == CONST || is_strict(language_mode())) {
- builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(),
- 0);
- }
- // Non-initializing assignments to legacy constants are ignored
- // in sloppy mode. Break here to avoid storing into variable.
- break;
+ if (mode != CONST || op == Token::INIT) {
+ builder()->StoreAccumulatorInRegister(destination);
+ } else if (variable->throw_on_const_assignment(language_mode())) {
+ builder()->CallRuntime(Runtime::kThrowConstAssignError);
}
-
- builder()->StoreAccumulatorInRegister(destination);
break;
}
- case VariableLocation::GLOBAL:
case VariableLocation::UNALLOCATED: {
builder()->StoreGlobal(variable->name(), feedback_index(slot),
language_mode());
@@ -2154,24 +1974,9 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
if (context) {
context_reg = context->reg();
+ depth = 0;
} else {
- 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.
- // TODO(mythria): Also update bytecode graph builder with correct depth
- // when this changes.
- builder()
- ->StoreAccumulatorInRegister(value_temp)
- .LoadAccumulatorWithRegister(execution_context()->reg())
- .StoreAccumulatorInRegister(context_reg);
- for (int i = 0; i < depth; ++i) {
- builder()
- ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
- .StoreAccumulatorInRegister(context_reg);
- }
- builder()->LoadAccumulatorWithRegister(value_temp);
+ context_reg = execution_context()->reg();
}
if (hole_check_required) {
@@ -2179,38 +1984,57 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
Register value_temp = register_allocator()->NewRegister();
builder()
->StoreAccumulatorInRegister(value_temp)
- .LoadContextSlot(context_reg, variable->index());
+ .LoadContextSlot(context_reg, variable->index(), depth);
BuildHoleCheckForVariableAssignment(variable, op);
builder()->LoadAccumulatorWithRegister(value_temp);
}
- if ((mode == CONST || mode == CONST_LEGACY) && op != Token::INIT) {
- if (mode == CONST || is_strict(language_mode())) {
- builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(),
- 0);
- }
- // Non-initializing assignments to legacy constants are ignored
- // in sloppy mode. Break here to avoid storing into variable.
- break;
+ 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);
}
-
- builder()->StoreContextSlot(context_reg, variable->index());
break;
}
case VariableLocation::LOOKUP: {
- DCHECK_NE(CONST_LEGACY, variable->mode());
builder()->StoreLookupSlot(variable->name(), language_mode());
break;
}
- case VariableLocation::MODULE:
- UNREACHABLE();
+ case VariableLocation::MODULE: {
+ DCHECK(IsDeclaredVariableMode(mode));
+
+ if (mode == CONST && op != Token::INIT) {
+ builder()->CallRuntime(Runtime::kThrowConstAssignError);
+ break;
+ }
+
+ // If we don't throw above, we know that we're dealing with an
+ // export because imports are const and we do not generate initializing
+ // assignments for them.
+ DCHECK(variable->IsExport());
+
+ ModuleDescriptor* mod = scope()->GetModuleScope()->module();
+ // There may be several export names for this local name, but it doesn't
+ // matter which one we pick, as they all map to the same cell.
+ auto it = mod->regular_exports().find(variable->raw_name());
+ DCHECK(it != mod->regular_exports().end());
+
+ RegisterList args = register_allocator()->NewRegisterList(2);
+ builder()
+ ->StoreAccumulatorInRegister(args[1])
+ .LoadLiteral(it->second->export_name->string())
+ .StoreAccumulatorInRegister(args[0])
+ .CallRuntime(Runtime::kStoreModuleExport, args);
+ break;
+ }
}
}
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.
@@ -2229,44 +2053,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;
}
}
@@ -2274,17 +2083,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);
@@ -2294,22 +2102,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;
}
}
@@ -2342,17 +2151,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) {
@@ -2382,12 +2192,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.
@@ -2407,14 +2217,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();
}
@@ -2430,18 +2238,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) {
@@ -2469,56 +2271,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);
}
}
@@ -2533,36 +2324,13 @@ void BytecodeGenerator::VisitProperty(Property* expr) {
}
}
-Register BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args) {
- if (args->length() == 0) {
- return Register();
+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]);
}
-
- // 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());
- }
- return first_arg;
}
void BytecodeGenerator::VisitCall(Call* expr) {
@@ -2573,18 +2341,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: {
@@ -2613,12 +2378,13 @@ void BytecodeGenerator::VisitCall(Call* expr) {
// Call %LoadLookupSlotForCall to get the callee and receiver.
DCHECK(Register::AreContiguous(callee, receiver));
+ RegisterList result_pair(callee.index(), 2);
Variable* variable = callee_expr->AsVariableProxy()->var();
builder()
->LoadLiteral(variable->name())
.StoreAccumulatorInRegister(name)
- .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name, 1,
- callee);
+ .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name,
+ result_pair);
break;
}
// Fall through.
@@ -2626,8 +2392,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: {
@@ -2647,42 +2412,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);
}
@@ -2692,16 +2449,14 @@ void BytecodeGenerator::VisitCall(Call* expr) {
if (expr->CallFeedbackICSlot().IsInvalid()) {
DCHECK(call_type == Call::POSSIBLY_EVAL_CALL);
// Valid type feedback slots can only be greater than kReservedIndexCount.
- // We use 0 to indicate an invalid slot it. Statically assert that 0 cannot
+ // We use 0 to indicate an invalid slot id. Statically assert that 0 cannot
// be a valid slot id.
STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0);
feedback_slot_index = 0;
} 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) {
@@ -2709,17 +2464,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.
@@ -2727,51 +2480,51 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) {
// Call construct.
builder()->SetExpressionPosition(expr);
- builder()->New(constructor, first_arg, args->length());
- execution_result()->SetResultInAccumulator();
+ // Valid type feedback slots can only be greater than kReservedIndexCount.
+ // Assert that 0 cannot be valid a valid slot id.
+ STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0);
+ // 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, 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());
- 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) {
@@ -2785,7 +2538,6 @@ void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
VisitForAccumulatorValue(expr->expression());
}
builder()->TypeOf();
- execution_result()->SetResultInAccumulator();
}
void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
@@ -2802,7 +2554,6 @@ void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
} else {
VisitForAccumulatorValue(expr->expression());
builder()->LogicalNot();
- execution_result()->SetResultInAccumulator();
}
}
@@ -2846,16 +2597,15 @@ void BytecodeGenerator::VisitDelete(UnaryOperation* expr) {
Variable* variable = proxy->var();
DCHECK(is_sloppy(language_mode()) || variable->is_this());
switch (variable->location()) {
- case VariableLocation::GLOBAL:
case VariableLocation::UNALLOCATED: {
// Global var, let, const or variables not explicitly declared.
Register native_context = register_allocator()->NewRegister();
Register global_object = register_allocator()->NewRegister();
builder()
->LoadContextSlot(execution_context()->reg(),
- Context::NATIVE_CONTEXT_INDEX)
+ Context::NATIVE_CONTEXT_INDEX, 0)
.StoreAccumulatorInRegister(native_context)
- .LoadContextSlot(native_context, Context::EXTENSION_INDEX)
+ .LoadContextSlot(native_context, Context::EXTENSION_INDEX, 0)
.StoreAccumulatorInRegister(global_object)
.LoadLiteral(variable->name())
.Delete(global_object, language_mode());
@@ -2878,7 +2628,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:
@@ -2889,7 +2639,6 @@ void BytecodeGenerator::VisitDelete(UnaryOperation* expr) {
VisitForEffect(expr->expression());
builder()->LoadTrue();
}
- execution_result()->SetResultInAccumulator();
}
void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
@@ -2902,7 +2651,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: {
@@ -2930,44 +2680,36 @@ 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.
- builder()->CastAccumulatorToNumber(old_value);
+ old_value = register_allocator()->NewRegister();
+ builder()->ConvertAccumulatorToNumber(old_value);
}
// Perform +1/-1 operation.
@@ -2994,22 +2736,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);
}
}
@@ -3034,8 +2776,8 @@ void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
Register lhs = VisitForRegisterValue(expr->left());
VisitForAccumulatorValue(expr->right());
builder()->SetExpressionPosition(expr);
- builder()->CompareOperation(expr->op(), lhs);
- execution_result()->SetResultInAccumulator();
+ FeedbackVectorSlot slot = expr->CompareOperationFeedbackSlot();
+ builder()->CompareOperation(expr->op(), lhs, feedback_index(slot));
}
void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
@@ -3045,7 +2787,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(); }
@@ -3055,7 +2796,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) {
@@ -3065,8 +2806,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) {
@@ -3106,7 +2846,6 @@ void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
VisitForAccumulatorValue(right);
builder()->Bind(&end_label);
}
- execution_result()->SetResultInAccumulator();
}
}
@@ -3142,7 +2881,6 @@ void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {
VisitForAccumulatorValue(right);
builder()->Bind(&end_label);
}
- execution_result()->SetResultInAccumulator();
}
}
@@ -3150,35 +2888,45 @@ void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) {
Visit(expr->expression());
}
-void BytecodeGenerator::VisitNewLocalFunctionContext() {
- AccumulatorResultScope accumulator_execution_result(this);
+void BytecodeGenerator::BuildNewLocalActivationContext() {
+ ValueResultScope value_execution_result(this);
Scope* scope = this->scope();
- // Allocate a new local context.
+ // Create the appropriate context.
if (scope->is_script_scope()) {
- RegisterAllocationScope register_scope(this);
- Register closure = register_allocator()->NewRegister();
- Register scope_info = register_allocator()->NewRegister();
- DCHECK(Register::AreContiguous(closure, scope_info));
+ 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());
+
+ // 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), args[0])
+ .LoadAccumulatorWithRegister(Register::function_closure())
+ .StoreAccumulatorInRegister(args[1])
+ .LoadLiteral(scope->scope_info())
+ .StoreAccumulatorInRegister(args[2])
+ .CallRuntime(Runtime::kPushModuleContext, args);
} else {
int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
if (slot_count <= FastNewFunctionContextStub::kMaximumSlots) {
builder()->CreateFunctionContext(slot_count);
} else {
builder()->CallRuntime(Runtime::kNewFunctionContext,
- Register::function_closure(), 1);
+ Register::function_closure());
}
}
- execution_result()->SetResultInAccumulator();
}
-void BytecodeGenerator::VisitBuildLocalActivationContext() {
+void BytecodeGenerator::BuildLocalActivationContextInitialization() {
DeclarationScope* scope = this->scope();
if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
@@ -3187,7 +2935,7 @@ void BytecodeGenerator::VisitBuildLocalActivationContext() {
// Context variable (at bottom of the context chain).
DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot(
- execution_context()->reg(), variable->index());
+ execution_context()->reg(), variable->index(), 0);
}
// Copy parameters into context if necessary.
@@ -3201,56 +2949,53 @@ void BytecodeGenerator::VisitBuildLocalActivationContext() {
Register parameter(builder()->Parameter(i + 1));
// Context variable (at bottom of the context chain).
DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
- builder()->LoadAccumulatorWithRegister(parameter)
- .StoreContextSlot(execution_context()->reg(), variable->index());
+ builder()->LoadAccumulatorWithRegister(parameter).StoreContextSlot(
+ execution_context()->reg(), variable->index(), 0);
}
}
-void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) {
- AccumulatorResultScope accumulator_execution_result(this);
+void BytecodeGenerator::BuildNewLocalBlockContext(Scope* scope) {
+ ValueResultScope value_execution_result(this);
DCHECK(scope->is_block_scope());
VisitFunctionClosureForContext();
builder()->CreateBlockContext(scope->scope_info());
- execution_result()->SetResultInAccumulator();
}
-void BytecodeGenerator::VisitNewLocalWithContext() {
- AccumulatorResultScope accumulator_execution_result(this);
+void BytecodeGenerator::BuildNewLocalWithContext(Scope* scope) {
+ ValueResultScope value_execution_result(this);
Register extension_object = register_allocator()->NewRegister();
- builder()->CastAccumulatorToJSObject(extension_object);
+ builder()->ConvertAccumulatorToObject(extension_object);
VisitFunctionClosureForContext();
- builder()->CreateWithContext(extension_object);
- execution_result()->SetResultInAccumulator();
+ builder()->CreateWithContext(extension_object, scope->scope_info());
}
-void BytecodeGenerator::VisitNewLocalCatchContext(Variable* variable) {
- AccumulatorResultScope accumulator_execution_result(this);
+void BytecodeGenerator::BuildNewLocalCatchContext(Variable* variable,
+ Scope* scope) {
+ ValueResultScope value_execution_result(this);
DCHECK(variable->IsContextSlot());
Register exception = register_allocator()->NewRegister();
builder()->StoreAccumulatorInRegister(exception);
VisitFunctionClosureForContext();
- builder()->CreateCatchContext(exception, variable->name());
- execution_result()->SetResultInAccumulator();
+ builder()->CreateCatchContext(exception, variable->name(),
+ scope->scope_info());
}
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);
}
}
void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object,
- ObjectLiteralProperty* property,
+ LiteralProperty* property,
int slot_number) {
Expression* expr = property->value();
if (FunctionLiteral::NeedsHomeObject(expr)) {
@@ -3302,38 +3047,44 @@ void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {
// Store the new target we were called with in the given variable.
builder()->LoadAccumulatorWithRegister(Register::new_target());
VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
+
+ // TODO(mstarzinger): The <new.target> register is not set by the deoptimizer
+ // and we need to make sure {BytecodeRegisterOptimizer} flushes its state
+ // before a local variable containing the <new.target> is used. Using a label
+ // as below flushes the entire pipeline, we should be more specific here.
+ BytecodeLabel flush_state_label;
+ builder()->Bind(&flush_state_label);
}
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() ||
- closure_scope->is_module_scope()) {
+ if (closure_scope->is_script_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 = register_allocator()->NewRegister();
builder()
->LoadContextSlot(execution_context()->reg(),
- Context::NATIVE_CONTEXT_INDEX)
+ Context::NATIVE_CONTEXT_INDEX, 0)
.StoreAccumulatorInRegister(native_context)
- .LoadContextSlot(native_context, Context::CLOSURE_INDEX);
+ .LoadContextSlot(native_context, Context::CLOSURE_INDEX, 0);
} else if (closure_scope->is_eval_scope()) {
// Contexts created by a call to eval have the same closure as the
// context calling eval, not the anonymous closure containing the eval
// code. Fetch it from the context.
builder()->LoadContextSlot(execution_context()->reg(),
- Context::CLOSURE_INDEX);
+ Context::CLOSURE_INDEX, 0);
} else {
- DCHECK(closure_scope->is_function_scope());
+ DCHECK(closure_scope->is_function_scope() ||
+ 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);
}
@@ -3354,16 +3105,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);
}
@@ -3412,6 +3164,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