Commit 380f8c8f authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[Interpreter] Add ForOf support.

Adds support for ForOf to the interpreter.

BUG=v8:4685
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#33470}
parent 56e1b13e
......@@ -1082,7 +1082,21 @@ void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
UNIMPLEMENTED();
LoopBuilder loop_builder(builder());
ControlScopeForIteration control_scope(this, stmt, &loop_builder);
VisitForEffect(stmt->assign_iterator());
loop_builder.LoopHeader();
loop_builder.Next();
VisitForEffect(stmt->next_result());
VisitForAccumulatorValue(stmt->result_done());
loop_builder.BreakIfTrue();
VisitForEffect(stmt->assign_each());
Visit(stmt->body());
loop_builder.JumpToHeader();
loop_builder.EndLoop();
}
......
......@@ -2294,6 +2294,99 @@ TEST(BytecodeGraphBuilderForIn) {
}
TEST(BytecodeGraphBuilderForOf) {
HandleAndZoneScope scope;
Isolate* isolate = scope.main_isolate();
Zone* zone = scope.main_zone();
Factory* factory = isolate->factory();
ExpectedSnippet<0> snippets[] = {
{" var r = 0;\n"
" for (var a of [0,6,7,9]) { r += a; }\n"
" return r;\n",
{handle(Smi::FromInt(22), isolate)}},
{" var r = '';\n"
" for (var a of 'foobar') { r = a + r; }\n"
" return r;\n",
{factory->NewStringFromStaticChars("raboof")}},
{" var a = [1, 2, 3];\n"
" a.name = 4;\n"
" var r = 0;\n"
" for (var x of a) { r += x; }\n"
" return r;\n",
{handle(Smi::FromInt(6), isolate)}},
{" var r = '';\n"
" var data = [1, 2, 3]; \n"
" for (a of data) { delete data[0]; r += a; } return r;",
{factory->NewStringFromStaticChars("123")}},
{" var r = '';\n"
" var data = [1, 2, 3]; \n"
" for (a of data) { delete data[2]; r += a; } return r;",
{factory->NewStringFromStaticChars("12undefined")}},
{" var r = '';\n"
" var data = [1, 2, 3]; \n"
" for (a of data) { delete data; r += a; } return r;",
{factory->NewStringFromStaticChars("123")}},
{" var r = '';\n"
" var input = 'foobar';\n"
" for (var a of input) {\n"
" if (a == 'b') break;\n"
" r += a;\n"
" }\n"
" return r;\n",
{factory->NewStringFromStaticChars("foo")}},
{" var r = '';\n"
" var input = 'foobar';\n"
" for (var a of input) {\n"
" if (a == 'b') continue;\n"
" r += a;\n"
" }\n"
" return r;\n",
{factory->NewStringFromStaticChars("fooar")}},
{" var r = '';\n"
" var data = [1, 2, 3, 4]; \n"
" for (a of data) { data[2] = 567; r += a; }\n"
" return r;\n",
{factory->NewStringFromStaticChars("125674")}},
{" var r = '';\n"
" var data = [1, 2, 3, 4]; \n"
" for (a of data) { data[4] = 567; r += a; }\n"
" return r;\n",
{factory->NewStringFromStaticChars("1234567")}},
{" var r = '';\n"
" var data = [1, 2, 3, 4]; \n"
" for (a of data) { data[5] = 567; r += a; }\n"
" return r;\n",
{factory->NewStringFromStaticChars("1234undefined567")}},
{" var r = '';\n"
" var obj = new Object();\n"
" obj[Symbol.iterator] = function() { return {\n"
" index: 3,\n"
" data: ['a', 'b', 'c', 'd'],"
" next: function() {"
" return {"
" done: this.index == -1,\n"
" value: this.index < 0 ? undefined : this.data[this.index--]\n"
" }\n"
" }\n"
" }}\n"
" for (a of obj) { r += a }\n"
" return r;\n",
{factory->NewStringFromStaticChars("dcba")}},
};
for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
snippets[i].code_snippet, kFunctionName);
BytecodeGraphTester tester(isolate, zone, script.start());
auto callable = tester.GetCallable<>();
Handle<Object> return_value = callable().ToHandleChecked();
CHECK(return_value->SameValue(*snippets[i].return_value()));
}
}
TEST(JumpWithConstantsAndWideConstants) {
HandleAndZoneScope scope;
auto isolate = scope.main_isolate();
......
......@@ -2837,6 +2837,116 @@ TEST(InterpreterForIn) {
}
TEST(InterpreterForOf) {
HandleAndZoneScope handles;
i::Isolate* isolate = handles.main_isolate();
i::Factory* factory = isolate->factory();
std::pair<const char*, Handle<Object>> for_of[] = {
{"function f() {\n"
" var r = 0;\n"
" for (var a of [0,6,7,9]) { r += a; }\n"
" return r;\n"
"}",
handle(Smi::FromInt(22), isolate)},
{"function f() {\n"
" var r = '';\n"
" for (var a of 'foobar') { r = a + r; }\n"
" return r;\n"
"}",
factory->NewStringFromStaticChars("raboof")},
{"function f() {\n"
" var a = [1, 2, 3];\n"
" a.name = 4;\n"
" var r = 0;\n"
" for (var x of a) { r += x; }\n"
" return r;\n"
"}",
handle(Smi::FromInt(6), isolate)},
{"function f() {\n"
" var r = '';\n"
" var data = [1, 2, 3]; \n"
" for (a of data) { delete data[0]; r += a; } return r; }",
factory->NewStringFromStaticChars("123")},
{"function f() {\n"
" var r = '';\n"
" var data = [1, 2, 3]; \n"
" for (a of data) { delete data[2]; r += a; } return r; }",
factory->NewStringFromStaticChars("12undefined")},
{"function f() {\n"
" var r = '';\n"
" var data = [1, 2, 3]; \n"
" for (a of data) { delete data; r += a; } return r; }",
factory->NewStringFromStaticChars("123")},
{"function f() {\n"
" var r = '';\n"
" var input = 'foobar';\n"
" for (var a of input) {\n"
" if (a == 'b') break;\n"
" r += a;\n"
" }\n"
" return r;\n"
"}",
factory->NewStringFromStaticChars("foo")},
{"function f() {\n"
" var r = '';\n"
" var input = 'foobar';\n"
" for (var a of input) {\n"
" if (a == 'b') continue;\n"
" r += a;\n"
" }\n"
" return r;\n"
"}",
factory->NewStringFromStaticChars("fooar")},
{"function f() {\n"
" var r = '';\n"
" var data = [1, 2, 3, 4]; \n"
" for (a of data) { data[2] = 567; r += a; }\n"
" return r;\n"
"}",
factory->NewStringFromStaticChars("125674")},
{"function f() {\n"
" var r = '';\n"
" var data = [1, 2, 3, 4]; \n"
" for (a of data) { data[4] = 567; r += a; }\n"
" return r;\n"
"}",
factory->NewStringFromStaticChars("1234567")},
{"function f() {\n"
" var r = '';\n"
" var data = [1, 2, 3, 4]; \n"
" for (a of data) { data[5] = 567; r += a; }\n"
" return r;\n"
"}",
factory->NewStringFromStaticChars("1234undefined567")},
{"function f() {\n"
" var r = '';\n"
" var obj = new Object();\n"
" obj[Symbol.iterator] = function() { return {\n"
" index: 3,\n"
" data: ['a', 'b', 'c', 'd'],"
" next: function() {"
" return {"
" done: this.index == -1,\n"
" value: this.index < 0 ? undefined : this.data[this.index--]\n"
" }\n"
" }\n"
" }}\n"
" for (a of obj) { r += a }\n"
" return r;\n"
"}",
factory->NewStringFromStaticChars("dcba")},
};
for (size_t i = 0; i < arraysize(for_of); i++) {
InterpreterTester tester(handles.main_isolate(), for_of[i].first);
auto callable = tester.GetCallable<>();
Handle<Object> return_val = callable().ToHandleChecked();
CHECK(return_val->SameValue(*for_of[i].second));
}
}
TEST(InterpreterSwitch) {
HandleAndZoneScope handles;
i::Isolate* isolate = handles.main_isolate();
......
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