Commit 677e54e2 authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[Interpreter] Always store current context in the frames context slot.

Change the interpreter to always store the current context in the frame's
context slot instead of the function context. This makes it possible to
restore the correct context during deopt.

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

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

Cr-Commit-Position: refs/heads/master@{#33477}
parent 12ac11e9
...@@ -1069,8 +1069,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) { ...@@ -1069,8 +1069,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
Operand(FixedArray::kHeaderSize - kHeapObjectTag)); Operand(FixedArray::kHeaderSize - kHeapObjectTag));
// Get the context from the frame. // Get the context from the frame.
// TODO(rmcilroy): Update interpreter frame to expect current context at the
// context slot instead of the function context.
__ ldr(kContextRegister, __ ldr(kContextRegister,
MemOperand(kInterpreterRegisterFileRegister, MemOperand(kInterpreterRegisterFileRegister,
InterpreterFrameConstants::kContextFromRegisterPointer)); InterpreterFrameConstants::kContextFromRegisterPointer));
......
...@@ -1028,8 +1028,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) { ...@@ -1028,8 +1028,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
Operand(FixedArray::kHeaderSize - kHeapObjectTag)); Operand(FixedArray::kHeaderSize - kHeapObjectTag));
// Get the context from the frame. // Get the context from the frame.
// TODO(rmcilroy): Update interpreter frame to expect current context at the
// context slot instead of the function context.
__ Ldr(kContextRegister, __ Ldr(kContextRegister,
MemOperand(kInterpreterRegisterFileRegister, MemOperand(kInterpreterRegisterFileRegister,
InterpreterFrameConstants::kContextFromRegisterPointer)); InterpreterFrameConstants::kContextFromRegisterPointer));
......
...@@ -155,8 +155,8 @@ Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const { ...@@ -155,8 +155,8 @@ Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const {
Node* BytecodeGraphBuilder::Environment::LookupRegister( Node* BytecodeGraphBuilder::Environment::LookupRegister(
interpreter::Register the_register) const { interpreter::Register the_register) const {
if (the_register.is_function_context()) { if (the_register.is_current_context()) {
return builder()->GetFunctionContext(); return Context();
} else if (the_register.is_function_closure()) { } else if (the_register.is_function_closure()) {
return builder()->GetFunctionClosure(); return builder()->GetFunctionClosure();
} else if (the_register.is_new_target()) { } else if (the_register.is_new_target()) {
...@@ -1034,9 +1034,10 @@ void BytecodeGraphBuilder::VisitKeyedStoreICStrictWide( ...@@ -1034,9 +1034,10 @@ void BytecodeGraphBuilder::VisitKeyedStoreICStrictWide(
void BytecodeGraphBuilder::VisitPushContext( void BytecodeGraphBuilder::VisitPushContext(
const interpreter::BytecodeArrayIterator& iterator) { const interpreter::BytecodeArrayIterator& iterator) {
Node* context = environment()->LookupAccumulator(); Node* new_context = environment()->LookupAccumulator();
environment()->BindRegister(iterator.GetRegisterOperand(0), context); environment()->BindRegister(iterator.GetRegisterOperand(0),
environment()->SetContext(context); environment()->Context());
environment()->SetContext(new_context);
} }
......
...@@ -80,7 +80,10 @@ void InterpreterAssembler::SetAccumulator(Node* value) { accumulator_ = value; } ...@@ -80,7 +80,10 @@ void InterpreterAssembler::SetAccumulator(Node* value) { accumulator_ = value; }
Node* InterpreterAssembler::GetContext() { return context_; } Node* InterpreterAssembler::GetContext() { return context_; }
void InterpreterAssembler::SetContext(Node* value) { context_ = value; } void InterpreterAssembler::SetContext(Node* value) {
StoreRegister(value, interpreter::Register::current_context());
context_ = value;
}
Node* InterpreterAssembler::BytecodeOffset() { return bytecode_offset_; } Node* InterpreterAssembler::BytecodeOffset() { return bytecode_offset_; }
......
...@@ -800,8 +800,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) { ...@@ -800,8 +800,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
__ mov(ebx, Operand(ebx, esi, times_pointer_size, 0)); __ mov(ebx, Operand(ebx, esi, times_pointer_size, 0));
// Get the context from the frame. // Get the context from the frame.
// TODO(rmcilroy): Update interpreter frame to expect current context at the
// context slot instead of the function context.
__ mov(kContextRegister, __ mov(kContextRegister,
Operand(kInterpreterRegisterFileRegister, Operand(kInterpreterRegisterFileRegister,
InterpreterFrameConstants::kContextFromRegisterPointer)); InterpreterFrameConstants::kContextFromRegisterPointer));
......
...@@ -1341,7 +1341,7 @@ bool BytecodeArrayBuilder::RegisterIsValid(Register reg, ...@@ -1341,7 +1341,7 @@ bool BytecodeArrayBuilder::RegisterIsValid(Register reg,
return false; return false;
} }
if (reg.is_function_context() || reg.is_function_closure() || if (reg.is_current_context() || reg.is_function_closure() ||
reg.is_new_target()) { reg.is_new_target()) {
return true; return true;
} else if (reg.is_parameter()) { } else if (reg.is_parameter()) {
......
...@@ -27,19 +27,26 @@ class BytecodeGenerator::ContextScope BASE_EMBEDDED { ...@@ -27,19 +27,26 @@ class BytecodeGenerator::ContextScope BASE_EMBEDDED {
: generator_(generator), : generator_(generator),
scope_(scope), scope_(scope),
outer_(generator_->execution_context()), outer_(generator_->execution_context()),
register_(generator_->NextContextRegister()), register_(Register::current_context()),
depth_(0), depth_(0),
should_pop_context_(should_pop_context) { should_pop_context_(should_pop_context) {
if (outer_) { if (outer_) {
depth_ = outer_->depth_ + 1; depth_ = outer_->depth_ + 1;
generator_->builder()->PushContext(register_);
// Push the outer context into a new context register.
Register outer_context_reg(builder()->first_context_register().index() +
outer_->depth_);
outer_->set_register(outer_context_reg);
generator_->builder()->PushContext(outer_context_reg);
} }
generator_->set_execution_context(this); generator_->set_execution_context(this);
} }
~ContextScope() { ~ContextScope() {
if (outer_ && should_pop_context_) { if (outer_ && should_pop_context_) {
DCHECK_EQ(register_.index(), Register::current_context().index());
generator_->builder()->PopContext(outer_->reg()); generator_->builder()->PopContext(outer_->reg());
outer_->set_register(register_);
} }
generator_->set_execution_context(outer_); generator_->set_execution_context(outer_);
} }
...@@ -67,6 +74,10 @@ class BytecodeGenerator::ContextScope BASE_EMBEDDED { ...@@ -67,6 +74,10 @@ class BytecodeGenerator::ContextScope BASE_EMBEDDED {
Register reg() const { return register_; } Register reg() const { return register_; }
private: private:
const BytecodeArrayBuilder* builder() const { return generator_->builder(); }
void set_register(Register reg) { register_ = reg; }
BytecodeGenerator* generator_; BytecodeGenerator* generator_;
Scope* scope_; Scope* scope_;
ContextScope* outer_; ContextScope* outer_;
...@@ -1866,7 +1877,7 @@ void BytecodeGenerator::VisitCall(Call* expr) { ...@@ -1866,7 +1877,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
DCHECK(Register::AreContiguous(callee, receiver)); DCHECK(Register::AreContiguous(callee, receiver));
Variable* variable = callee_expr->AsVariableProxy()->var(); Variable* variable = callee_expr->AsVariableProxy()->var();
builder() builder()
->MoveRegister(execution_context()->reg(), context) ->MoveRegister(Register::current_context(), context)
.LoadLiteral(variable->name()) .LoadLiteral(variable->name())
.StoreAccumulatorInRegister(name) .StoreAccumulatorInRegister(name)
.CallRuntimeForPair(Runtime::kLoadLookupSlot, context, 2, callee); .CallRuntimeForPair(Runtime::kLoadLookupSlot, context, 2, callee);
...@@ -2480,24 +2491,6 @@ void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) { ...@@ -2480,24 +2491,6 @@ void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) {
} }
Register BytecodeGenerator::NextContextRegister() const {
if (execution_context() == nullptr) {
// Return the incoming function context for the outermost execution context.
return Register::function_context();
}
Register previous = execution_context()->reg();
if (previous == Register::function_context()) {
// If the previous context was the incoming function context, then the next
// context register is the first local context register.
return builder_.first_context_register();
} else {
// Otherwise use the next local context register.
DCHECK_LT(previous.index(), builder_.last_context_register().index());
return Register(previous.index() + 1);
}
}
LanguageMode BytecodeGenerator::language_mode() const { LanguageMode BytecodeGenerator::language_mode() const {
return info()->language_mode(); return info()->language_mode();
} }
......
...@@ -42,7 +42,6 @@ class BytecodeGenerator final : public AstVisitor { ...@@ -42,7 +42,6 @@ class BytecodeGenerator final : public AstVisitor {
class RegisterAllocationScope; class RegisterAllocationScope;
void MakeBytecodeBody(); void MakeBytecodeBody();
Register NextContextRegister() const;
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
......
...@@ -294,7 +294,7 @@ std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, ...@@ -294,7 +294,7 @@ std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start,
case interpreter::OperandType::kReg8: case interpreter::OperandType::kReg8:
case interpreter::OperandType::kReg16: { case interpreter::OperandType::kReg16: {
Register reg = DecodeRegister(operand_start, op_type); Register reg = DecodeRegister(operand_start, op_type);
if (reg.is_function_context()) { if (reg.is_current_context()) {
os << "<context>"; os << "<context>";
} else if (reg.is_function_closure()) { } else if (reg.is_function_closure()) {
os << "<closure>"; os << "<closure>";
...@@ -358,7 +358,7 @@ static const int kLastParamRegisterIndex = ...@@ -358,7 +358,7 @@ static const int kLastParamRegisterIndex =
-InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize;
static const int kFunctionClosureRegisterIndex = static const int kFunctionClosureRegisterIndex =
-InterpreterFrameConstants::kFunctionFromRegisterPointer / kPointerSize; -InterpreterFrameConstants::kFunctionFromRegisterPointer / kPointerSize;
static const int kFunctionContextRegisterIndex = static const int kCurrentContextRegisterIndex =
-InterpreterFrameConstants::kContextFromRegisterPointer / kPointerSize; -InterpreterFrameConstants::kContextFromRegisterPointer / kPointerSize;
static const int kNewTargetRegisterIndex = static const int kNewTargetRegisterIndex =
-InterpreterFrameConstants::kNewTargetFromRegisterPointer / kPointerSize; -InterpreterFrameConstants::kNewTargetFromRegisterPointer / kPointerSize;
...@@ -397,13 +397,13 @@ bool Register::is_function_closure() const { ...@@ -397,13 +397,13 @@ bool Register::is_function_closure() const {
} }
Register Register::function_context() { Register Register::current_context() {
return Register(kFunctionContextRegisterIndex); return Register(kCurrentContextRegisterIndex);
} }
bool Register::is_function_context() const { bool Register::is_current_context() const {
return index() == kFunctionContextRegisterIndex; return index() == kCurrentContextRegisterIndex;
} }
......
...@@ -308,9 +308,9 @@ class Register { ...@@ -308,9 +308,9 @@ class Register {
static Register function_closure(); static Register function_closure();
bool is_function_closure() const; bool is_function_closure() const;
// Returns the register for the function's outer context. // Returns the register which holds the current context object.
static Register function_context(); static Register current_context();
bool is_function_context() const; bool is_current_context() const;
// Returns the register for the incoming new target value. // Returns the register for the incoming new target value.
static Register new_target(); static Register new_target();
......
...@@ -816,12 +816,14 @@ void Interpreter::DoKeyedStoreICStrictWide( ...@@ -816,12 +816,14 @@ void Interpreter::DoKeyedStoreICStrictWide(
// PushContext <context> // PushContext <context>
// //
// Pushes the accumulator as the current context, and saves it in <context> // Saves the current context in <context>, and pushes the accumulator as the
// new current context.
void Interpreter::DoPushContext(compiler::InterpreterAssembler* assembler) { void Interpreter::DoPushContext(compiler::InterpreterAssembler* assembler) {
Node* reg_index = __ BytecodeOperandReg(0); Node* reg_index = __ BytecodeOperandReg(0);
Node* context = __ GetAccumulator(); Node* new_context = __ GetAccumulator();
__ SetContext(context); Node* old_context = __ GetContext();
__ StoreRegister(context, reg_index); __ StoreRegister(old_context, reg_index);
__ SetContext(new_context);
__ Dispatch(); __ Dispatch();
} }
......
...@@ -1058,8 +1058,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) { ...@@ -1058,8 +1058,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
Operand(FixedArray::kHeaderSize - kHeapObjectTag)); Operand(FixedArray::kHeaderSize - kHeapObjectTag));
// Get the context from the frame. // Get the context from the frame.
// TODO(rmcilroy): Update interpreter frame to expect current context at the
// context slot instead of the function context.
__ lw(kContextRegister, __ lw(kContextRegister,
MemOperand(kInterpreterRegisterFileRegister, MemOperand(kInterpreterRegisterFileRegister,
InterpreterFrameConstants::kContextFromRegisterPointer)); InterpreterFrameConstants::kContextFromRegisterPointer));
......
...@@ -1049,8 +1049,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) { ...@@ -1049,8 +1049,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
Operand(FixedArray::kHeaderSize - kHeapObjectTag)); Operand(FixedArray::kHeaderSize - kHeapObjectTag));
// Get the context from the frame. // Get the context from the frame.
// TODO(rmcilroy): Update interpreter frame to expect current context at the
// context slot instead of the function context.
__ ld(kContextRegister, __ ld(kContextRegister,
MemOperand(kInterpreterRegisterFileRegister, MemOperand(kInterpreterRegisterFileRegister,
InterpreterFrameConstants::kContextFromRegisterPointer)); InterpreterFrameConstants::kContextFromRegisterPointer));
......
...@@ -1058,8 +1058,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) { ...@@ -1058,8 +1058,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
Operand(FixedArray::kHeaderSize - kHeapObjectTag)); Operand(FixedArray::kHeaderSize - kHeapObjectTag));
// Get the context from the frame. // Get the context from the frame.
// TODO(rmcilroy): Update interpreter frame to expect current context at the
// context slot instead of the function context.
__ LoadP(kContextRegister, __ LoadP(kContextRegister,
MemOperand(kInterpreterRegisterFileRegister, MemOperand(kInterpreterRegisterFileRegister,
InterpreterFrameConstants::kContextFromRegisterPointer)); InterpreterFrameConstants::kContextFromRegisterPointer));
......
...@@ -821,8 +821,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) { ...@@ -821,8 +821,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
Immediate(FixedArray::kHeaderSize - kHeapObjectTag)); Immediate(FixedArray::kHeaderSize - kHeapObjectTag));
// Get the context from the frame. // Get the context from the frame.
// TODO(rmcilroy): Update interpreter frame to expect current context at the
// context slot instead of the function context.
__ movp(kContextRegister, __ movp(kContextRegister,
Operand(kInterpreterRegisterFileRegister, Operand(kInterpreterRegisterFileRegister,
InterpreterFrameConstants::kContextFromRegisterPointer)); InterpreterFrameConstants::kContextFromRegisterPointer));
......
...@@ -801,8 +801,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) { ...@@ -801,8 +801,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
__ mov(ebx, Operand(ebx, esi, times_pointer_size, 0)); __ mov(ebx, Operand(ebx, esi, times_pointer_size, 0));
// Get the context from the frame. // Get the context from the frame.
// TODO(rmcilroy): Update interpreter frame to expect current context at the
// context slot instead of the function context.
__ mov(kContextRegister, __ mov(kContextRegister,
Operand(kInterpreterRegisterFileRegister, Operand(kInterpreterRegisterFileRegister,
InterpreterFrameConstants::kContextFromRegisterPointer)); InterpreterFrameConstants::kContextFromRegisterPointer));
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
function outer(y) {
function inner() {
var x = 10;
(function() {
// Access x from inner function to force it to be context allocated.
x = 20;
%DeoptimizeFunction(inner);
})();
// Variable y should be read from the outer context.
return y;
};
%OptimizeFunctionOnNextCall(inner);
return inner();
}
assertEquals(30, outer(30));
...@@ -409,6 +409,16 @@ TARGET_TEST_F(InterpreterAssemblerTest, GetSetAccumulator) { ...@@ -409,6 +409,16 @@ TARGET_TEST_F(InterpreterAssemblerTest, GetSetAccumulator) {
} }
TARGET_TEST_F(InterpreterAssemblerTest, GetSetContext) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
Node* context_node = m.Int32Constant(100);
m.SetContext(context_node);
EXPECT_THAT(m.GetContext(), context_node);
}
}
TARGET_TEST_F(InterpreterAssemblerTest, RegisterLocation) { TARGET_TEST_F(InterpreterAssemblerTest, RegisterLocation) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode); InterpreterAssemblerForTest m(this, bytecode);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment