Commit 2e2e6b41 authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[Interpreter] Add wide context slot load / store operations.

Adds wide context slot load / store operations. Adds LdaContextSlotWide
and StaContextSlotWide bytecodes.

BUG=v8:4280
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#33211}
parent 036e3e01
...@@ -766,6 +766,12 @@ void BytecodeGraphBuilder::VisitLdaContextSlot( ...@@ -766,6 +766,12 @@ void BytecodeGraphBuilder::VisitLdaContextSlot(
} }
void BytecodeGraphBuilder::VisitLdaContextSlotWide(
const interpreter::BytecodeArrayIterator& iterator) {
VisitLdaContextSlot(iterator);
}
void BytecodeGraphBuilder::VisitStaContextSlot( void BytecodeGraphBuilder::VisitStaContextSlot(
const interpreter::BytecodeArrayIterator& iterator) { const interpreter::BytecodeArrayIterator& iterator) {
// TODO(mythria): LoadContextSlots are unrolled by the required depth when // TODO(mythria): LoadContextSlots are unrolled by the required depth when
...@@ -779,6 +785,12 @@ void BytecodeGraphBuilder::VisitStaContextSlot( ...@@ -779,6 +785,12 @@ void BytecodeGraphBuilder::VisitStaContextSlot(
} }
void BytecodeGraphBuilder::VisitStaContextSlotWide(
const interpreter::BytecodeArrayIterator& iterator) {
VisitStaContextSlot(iterator);
}
void BytecodeGraphBuilder::BuildLdaLookupSlot( void BytecodeGraphBuilder::BuildLdaLookupSlot(
TypeofMode typeof_mode, TypeofMode typeof_mode,
const interpreter::BytecodeArrayIterator& iterator) { const interpreter::BytecodeArrayIterator& iterator) {
......
...@@ -431,6 +431,9 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, ...@@ -431,6 +431,9 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context,
if (FitsInIdx8Operand(slot_index)) { if (FitsInIdx8Operand(slot_index)) {
Output(Bytecode::kLdaContextSlot, context.ToOperand(), Output(Bytecode::kLdaContextSlot, context.ToOperand(),
static_cast<uint8_t>(slot_index)); static_cast<uint8_t>(slot_index));
} else if (FitsInIdx16Operand(slot_index)) {
Output(Bytecode::kLdaContextSlotWide, context.ToOperand(),
static_cast<uint16_t>(slot_index));
} else { } else {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
...@@ -444,6 +447,9 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, ...@@ -444,6 +447,9 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
if (FitsInIdx8Operand(slot_index)) { if (FitsInIdx8Operand(slot_index)) {
Output(Bytecode::kStaContextSlot, context.ToOperand(), Output(Bytecode::kStaContextSlot, context.ToOperand(),
static_cast<uint8_t>(slot_index)); static_cast<uint8_t>(slot_index));
} else if (FitsInIdx16Operand(slot_index)) {
Output(Bytecode::kStaContextSlotWide, context.ToOperand(),
static_cast<uint16_t>(slot_index));
} else { } else {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
......
...@@ -67,6 +67,8 @@ namespace interpreter { ...@@ -67,6 +67,8 @@ namespace interpreter {
V(PopContext, OperandType::kReg8) \ V(PopContext, OperandType::kReg8) \
V(LdaContextSlot, OperandType::kReg8, OperandType::kIdx8) \ V(LdaContextSlot, OperandType::kReg8, OperandType::kIdx8) \
V(StaContextSlot, OperandType::kReg8, OperandType::kIdx8) \ V(StaContextSlot, OperandType::kReg8, OperandType::kIdx8) \
V(LdaContextSlotWide, OperandType::kReg8, OperandType::kIdx16) \
V(StaContextSlotWide, OperandType::kReg8, OperandType::kIdx16) \
\ \
/* Load-Store lookup slots */ \ /* Load-Store lookup slots */ \
V(LdaLookupSlot, OperandType::kIdx8) \ V(LdaLookupSlot, OperandType::kIdx8) \
......
...@@ -433,6 +433,15 @@ void Interpreter::DoLdaContextSlot(compiler::InterpreterAssembler* assembler) { ...@@ -433,6 +433,15 @@ void Interpreter::DoLdaContextSlot(compiler::InterpreterAssembler* assembler) {
} }
// LdaContextSlotWide <context> <slot_index>
//
// Load the object in |slot_index| of |context| into the accumulator.
void Interpreter::DoLdaContextSlotWide(
compiler::InterpreterAssembler* assembler) {
DoLdaContextSlot(assembler);
}
// StaContextSlot <context> <slot_index> // StaContextSlot <context> <slot_index>
// //
// Stores the object in the accumulator into |slot_index| of |context|. // Stores the object in the accumulator into |slot_index| of |context|.
...@@ -446,6 +455,15 @@ void Interpreter::DoStaContextSlot(compiler::InterpreterAssembler* assembler) { ...@@ -446,6 +455,15 @@ void Interpreter::DoStaContextSlot(compiler::InterpreterAssembler* assembler) {
} }
// StaContextSlot <context> <slot_index>
//
// Stores the object in the accumulator into |slot_index| of |context|.
void Interpreter::DoStaContextSlotWide(
compiler::InterpreterAssembler* assembler) {
DoStaContextSlot(assembler);
}
void Interpreter::DoLoadLookupSlot(Runtime::FunctionId function_id, void Interpreter::DoLoadLookupSlot(Runtime::FunctionId function_id,
compiler::InterpreterAssembler* assembler) { compiler::InterpreterAssembler* assembler) {
Node* index = __ BytecodeOperandIdx(0); Node* index = __ BytecodeOperandIdx(0);
......
...@@ -109,8 +109,12 @@ class BytecodeGeneratorHelper { ...@@ -109,8 +109,12 @@ class BytecodeGeneratorHelper {
#error Unknown byte ordering #error Unknown byte ordering
#endif #endif
#define XSTR(A) #A
#define STR(A) XSTR(A)
#define COMMA() , #define COMMA() ,
#define SPACE() #define SPACE()
#define UNIQUE_VAR() "var a" STR(__COUNTER__) " = 0;\n"
#define REPEAT_2(SEP, ...) \ #define REPEAT_2(SEP, ...) \
__VA_ARGS__ SEP() __VA_ARGS__ __VA_ARGS__ SEP() __VA_ARGS__
...@@ -135,6 +139,16 @@ class BytecodeGeneratorHelper { ...@@ -135,6 +139,16 @@ class BytecodeGeneratorHelper {
REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) SEP() \ REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) SEP() \
__VA_ARGS__ __VA_ARGS__
#define REPEAT_249(SEP, ...) \
REPEAT_127(SEP, __VA_ARGS__) SEP() REPEAT_64(SEP, __VA_ARGS__) SEP() \
REPEAT_32(SEP, __VA_ARGS__) SEP() REPEAT_16(SEP, __VA_ARGS__) SEP() \
REPEAT_8(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__)
#define REPEAT_249_UNIQUE_VARS() \
UNIQUE_VAR() REPEAT_127(UNIQUE_VAR) UNIQUE_VAR() REPEAT_64(UNIQUE_VAR) \
UNIQUE_VAR() REPEAT_32(UNIQUE_VAR) UNIQUE_VAR() REPEAT_16(UNIQUE_VAR) \
UNIQUE_VAR() REPEAT_8(UNIQUE_VAR) UNIQUE_VAR() REPEAT_2(UNIQUE_VAR)
// Structure for containing expected bytecode snippets. // Structure for containing expected bytecode snippets.
template<typename T, int C = 6> template<typename T, int C = 6>
struct ExpectedSnippet { struct ExpectedSnippet {
...@@ -4016,7 +4030,15 @@ TEST(ContextVariables) { ...@@ -4016,7 +4030,15 @@ TEST(ContextVariables) {
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
int closure = Register::function_closure().index(); int closure = Register::function_closure().index();
int new_target = Register::new_target().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS; int first_context_slot = Context::MIN_CONTEXT_SLOTS;
// The wide check below relies on MIN_CONTEXT_SLOTS + 3 + 249 == 256, if this
// ever changes, the REPEAT_XXX should be changed to output the correct number
// of unique variables to trigger the wide slot load / store.
STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS + 3 + 249 == 256);
int wide_slot = first_context_slot + 3;
ExpectedSnippet<InstanceType> snippets[] = { ExpectedSnippet<InstanceType> snippets[] = {
{"var a; return function() { a = 1; };", {"var a; return function() { a = 1; };",
1 * kPointerSize, 1 * kPointerSize,
...@@ -4109,6 +4131,39 @@ TEST(ContextVariables) { ...@@ -4109,6 +4131,39 @@ TEST(ContextVariables) {
2, 2,
{InstanceType::FIXED_ARRAY_TYPE, {InstanceType::FIXED_ARRAY_TYPE,
InstanceType::SHARED_FUNCTION_INFO_TYPE}}, InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"'use strict';\n"
REPEAT_249_UNIQUE_VARS()
"eval();"
"var b = 100;"
"return b",
3 * kPointerSize,
1,
1041,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
U8(1), //
B(PushContext), R(0), //
B(Ldar), THIS(1), //
B(StaContextSlot), R(0), U8(first_context_slot), //
B(CreateUnmappedArguments), //
B(StaContextSlot), R(0), U8(first_context_slot + 1), //
B(Ldar), R(new_target), //
B(StaContextSlot), R(0), U8(first_context_slot + 2), //
REPEAT_249(COMMA, //
B(LdaZero), //
B(StaContextSlot), R(0), U8(wide_slot++)), //
B(LdaUndefined), //
B(Star), R(2), //
B(LdaGlobalStrict), U8(0), U8(1), //
B(Star), R(1), //
B(Call), R(1), R(2), U8(0), U8(0), //
B(LdaSmi8), U8(100), //
B(StaContextSlotWide), R(0), U16(256), //
B(LdaContextSlotWide), R(0), U16(256), //
B(Return), //
},
1,
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
}; };
for (size_t i = 0; i < arraysize(snippets); i++) { for (size_t i = 0; i < arraysize(snippets); i++) {
......
...@@ -1944,7 +1944,11 @@ TEST(InterpreterContextVariables) { ...@@ -1944,7 +1944,11 @@ TEST(InterpreterContextVariables) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
i::Isolate* isolate = handles.main_isolate(); i::Isolate* isolate = handles.main_isolate();
std::pair<const char*, Handle<Object>> context_vars[] = { std::ostringstream unique_vars;
for (int i = 0; i < 250; i++) {
unique_vars << "var a" << i << " = 0;";
}
std::pair<std::string, Handle<Object>> context_vars[] = {
std::make_pair("var a; (function() { a = 1; })(); return a;", std::make_pair("var a; (function() { a = 1; })(); return a;",
handle(Smi::FromInt(1), isolate)), handle(Smi::FromInt(1), isolate)),
std::make_pair("var a = 10; (function() { a; })(); return a;", std::make_pair("var a = 10; (function() { a; })(); return a;",
...@@ -1959,10 +1963,14 @@ TEST(InterpreterContextVariables) { ...@@ -1959,10 +1963,14 @@ TEST(InterpreterContextVariables) {
"{ let b = 20; var c = function() { [a, b] };\n" "{ let b = 20; var c = function() { [a, b] };\n"
" return a + b; }", " return a + b; }",
handle(Smi::FromInt(30), isolate)), handle(Smi::FromInt(30), isolate)),
std::make_pair("'use strict';" + unique_vars.str() +
"eval(); var b = 100; return b;",
handle(Smi::FromInt(100), isolate)),
}; };
for (size_t i = 0; i < arraysize(context_vars); i++) { for (size_t i = 0; i < arraysize(context_vars); i++) {
std::string source(InterpreterTester::SourceForBody(context_vars[i].first)); std::string source(
InterpreterTester::SourceForBody(context_vars[i].first.c_str()));
InterpreterTester tester(handles.main_isolate(), source.c_str()); InterpreterTester tester(handles.main_isolate(), source.c_str());
auto callable = tester.GetCallable<>(); auto callable = tester.GetCallable<>();
......
...@@ -69,10 +69,10 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -69,10 +69,10 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.StoreGlobal(name, 1, LanguageMode::STRICT); .StoreGlobal(name, 1, LanguageMode::STRICT);
// Emit context operations. // Emit context operations.
builder.PushContext(reg); builder.PushContext(reg)
builder.PopContext(reg); .PopContext(reg)
builder.LoadContextSlot(reg, 1); .LoadContextSlot(reg, 1)
builder.StoreContextSlot(reg, 1); .StoreContextSlot(reg, 1);
// Emit load / store property operations. // Emit load / store property operations.
builder.LoadNamedProperty(reg, name, 0, LanguageMode::SLOPPY) builder.LoadNamedProperty(reg, name, 0, LanguageMode::SLOPPY)
...@@ -241,6 +241,10 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -241,6 +241,10 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.StoreNamedProperty(reg, wide_name, 0, LanguageMode::STRICT) .StoreNamedProperty(reg, wide_name, 0, LanguageMode::STRICT)
.StoreKeyedProperty(reg, reg, 2056, LanguageMode::STRICT); .StoreKeyedProperty(reg, reg, 2056, LanguageMode::STRICT);
// Emit wide context operations.
builder.LoadContextSlot(reg, 1024)
.StoreContextSlot(reg, 1024);
// Emit wide load / store lookup slots. // Emit wide load / store lookup slots.
builder.LoadLookupSlot(wide_name, TypeofMode::NOT_INSIDE_TYPEOF) builder.LoadLookupSlot(wide_name, TypeofMode::NOT_INSIDE_TYPEOF)
.LoadLookupSlot(wide_name, TypeofMode::INSIDE_TYPEOF) .LoadLookupSlot(wide_name, TypeofMode::INSIDE_TYPEOF)
......
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