Commit dac46ef7 authored by mythria's avatar mythria Committed by Commit bot

[Interpreter] Adds support for variable/function declarations in lookup slots.

Adds support for variable and function declarations in lookup slots to the
interpreter.

BUG=v8:4280
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#33355}
parent 085487dd
...@@ -480,9 +480,31 @@ void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { ...@@ -480,9 +480,31 @@ void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
variable->index()); variable->index());
} }
break; break;
case VariableLocation::LOOKUP: case VariableLocation::LOOKUP: {
UNIMPLEMENTED(); DCHECK(IsDeclaredVariableMode(mode));
register_allocator()->PrepareForConsecutiveAllocations(3);
Register name = register_allocator()->NextConsecutiveRegister();
Register init_value = register_allocator()->NextConsecutiveRegister();
Register attributes = register_allocator()->NextConsecutiveRegister();
builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name);
if (hole_init) {
builder()->LoadTheHole().StoreAccumulatorInRegister(init_value);
} else {
// For variables, we must not use an initial value (such as 'undefined')
// because we may have a (legal) redeclaration and we must not destroy
// the current value.
builder()
->LoadLiteral(Smi::FromInt(0))
.StoreAccumulatorInRegister(init_value);
}
builder()
->LoadLiteral(Smi::FromInt(variable->DeclarationPropertyAttributes()))
.StoreAccumulatorInRegister(attributes)
.CallRuntime(Runtime::kDeclareLookupSlot, name, 3);
break; break;
}
} }
} }
...@@ -513,8 +535,20 @@ void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { ...@@ -513,8 +535,20 @@ void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
variable->index()); variable->index());
break; break;
} }
case VariableLocation::LOOKUP: case VariableLocation::LOOKUP: {
UNIMPLEMENTED(); register_allocator()->PrepareForConsecutiveAllocations(3);
Register name = register_allocator()->NextConsecutiveRegister();
Register literal = register_allocator()->NextConsecutiveRegister();
Register attributes = register_allocator()->NextConsecutiveRegister();
builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name);
VisitForAccumulatorValue(decl->fun());
builder()
->StoreAccumulatorInRegister(literal)
.LoadLiteral(Smi::FromInt(variable->DeclarationPropertyAttributes()))
.StoreAccumulatorInRegister(attributes)
.CallRuntime(Runtime::kDeclareLookupSlot, name, 3);
}
} }
} }
...@@ -533,7 +567,10 @@ void BytecodeGenerator::VisitDeclarations( ...@@ -533,7 +567,10 @@ void BytecodeGenerator::VisitDeclarations(
ZoneList<Declaration*>* declarations) { ZoneList<Declaration*>* declarations) {
RegisterAllocationScope register_scope(this); RegisterAllocationScope register_scope(this);
DCHECK(globals()->empty()); DCHECK(globals()->empty());
AstVisitor::VisitDeclarations(declarations); for (int i = 0; i < declarations->length(); i++) {
RegisterAllocationScope register_scope(this);
Visit(declarations->at(i));
}
if (globals()->empty()) return; if (globals()->empty()) return;
int array_index = 0; int array_index = 0;
Handle<FixedArray> data = isolate()->factory()->NewFixedArray( Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
...@@ -1319,6 +1356,8 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable, ...@@ -1319,6 +1356,8 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
break; break;
} }
case VariableLocation::LOOKUP: { case VariableLocation::LOOKUP: {
// TODO(mythria): Use Runtime::kInitializeLegacyConstLookupSlot for
// initializations of const declarations.
builder()->StoreLookupSlot(variable->name(), language_mode()); builder()->StoreLookupSlot(variable->name(), language_mode());
break; break;
} }
...@@ -1559,7 +1598,7 @@ void BytecodeGenerator::VisitCall(Call* expr) { ...@@ -1559,7 +1598,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(Register::function_context(), context) ->MoveRegister(execution_context()->reg(), context)
.LoadLiteral(variable->name()) .LoadLiteral(variable->name())
.StoreAccumulatorInRegister(name) .StoreAccumulatorInRegister(name)
.CallRuntimeForPair(Runtime::kLoadLookupSlot, context, 2, callee); .CallRuntimeForPair(Runtime::kLoadLookupSlot, context, 2, callee);
......
...@@ -3562,6 +3562,81 @@ TEST(InterpreterEvalGlobal) { ...@@ -3562,6 +3562,81 @@ TEST(InterpreterEvalGlobal) {
} }
} }
TEST(InterpreterEvalVariableDecl) {
HandleAndZoneScope handles;
i::Isolate* isolate = handles.main_isolate();
i::Factory* factory = isolate->factory();
std::pair<const char*, Handle<Object>> eval_global[] = {
{"function f() { eval('var x = 10; x++;'); return x; }",
handle(Smi::FromInt(11), isolate)},
{"function f() { var x = 20; eval('var x = 10; x++;'); return x; }",
handle(Smi::FromInt(11), isolate)},
{"function f() {"
" var x = 20;"
" eval('\"use strict\"; var x = 10; x++;');"
" return x; }",
handle(Smi::FromInt(20), isolate)},
{"function f() {"
" var y = 30;"
" eval('var x = {1:20}; x[2]=y;');"
" return x[2]; }",
handle(Smi::FromInt(30), isolate)},
{"function f() {"
" eval('var x = {name:\"test\"};');"
" return x.name; }",
factory->NewStringFromStaticChars("test")},
{"function f() {"
" eval('var x = [{name:\"test\"}, {type:\"cc\"}];');"
" return x[1].type+x[0].name; }",
factory->NewStringFromStaticChars("cctest")},
{"function f() {\n"
" var x = 3;\n"
" var get_eval_x;\n"
" eval('\"use strict\"; "
" var x = 20; "
" get_eval_x = function func() {return x;};');\n"
" return get_eval_x() + x;\n"
"}",
handle(Smi::FromInt(23), isolate)},
// TODO(mythria): Add tests with const declarations.
};
for (size_t i = 0; i < arraysize(eval_global); i++) {
InterpreterTester tester(handles.main_isolate(), eval_global[i].first, "*");
auto callable = tester.GetCallable<>();
Handle<i::Object> return_value = callable().ToHandleChecked();
CHECK(return_value->SameValue(*eval_global[i].second));
}
}
TEST(InterpreterEvalFunctionDecl) {
HandleAndZoneScope handles;
i::Isolate* isolate = handles.main_isolate();
std::pair<const char*, Handle<Object>> eval_func_decl[] = {
{"function f() {\n"
" var x = 3;\n"
" eval('var x = 20;"
" function get_x() {return x;};');\n"
" return get_x() + x;\n"
"}",
handle(Smi::FromInt(40), isolate)},
};
for (size_t i = 0; i < arraysize(eval_func_decl); i++) {
InterpreterTester tester(handles.main_isolate(), eval_func_decl[i].first,
"*");
auto callable = tester.GetCallable<>();
Handle<i::Object> return_value = callable().ToHandleChecked();
CHECK(return_value->SameValue(*eval_func_decl[i].second));
}
}
} // namespace interpreter } // namespace interpreter
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
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