Commit 67c99a99 authored by mythria's avatar mythria Committed by Commit bot

[Interpreter] Adds wide variant of CreateLiterals. Adds CreateLiterals to BytecodeGraphBuilder.

Adds implementation and tests for CreateObjectLiteral, CreateArrayLiteral and CreateRegExpLiteral
to bytecode graph builder. Also changes these bytecodes to expect three operands instead of using
accumulator to pass one of the operands. This is done to avoid looking into the earlier nodes to
fetch operands in the bytecode graph builder. Also adds support for wide variant of these
bytecodes to bytecode generator and bytecode graph builder.

BUG=v8:4280
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#32710}
parent 82fd0047
......@@ -702,21 +702,82 @@ void BytecodeGraphBuilder::VisitCreateUnmappedArguments(
}
void BytecodeGraphBuilder::BuildCreateLiteral(const Operator* op) {
Node* literal = NewNode(op, GetFunctionClosure());
AddEmptyFrameStateInputs(literal);
environment()->BindAccumulator(literal);
}
void BytecodeGraphBuilder::BuildCreateRegExpLiteral(
const interpreter::BytecodeArrayIterator& iterator) {
Handle<String> constant_pattern =
Handle<String>::cast(iterator.GetConstantForIndexOperand(0));
int literal_index = iterator.GetIndexOperand(1);
int literal_flags = iterator.GetImmediateOperand(2);
const Operator* op = javascript()->CreateLiteralRegExp(
constant_pattern, literal_flags, literal_index);
BuildCreateLiteral(op);
}
void BytecodeGraphBuilder::VisitCreateRegExpLiteral(
const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED();
BuildCreateRegExpLiteral(iterator);
}
void BytecodeGraphBuilder::VisitCreateRegExpLiteralWide(
const interpreter::BytecodeArrayIterator& iterator) {
BuildCreateRegExpLiteral(iterator);
}
void BytecodeGraphBuilder::BuildCreateArrayLiteral(
const interpreter::BytecodeArrayIterator& iterator) {
Handle<FixedArray> constant_elements =
Handle<FixedArray>::cast(iterator.GetConstantForIndexOperand(0));
int literal_index = iterator.GetIndexOperand(1);
int literal_flags = iterator.GetImmediateOperand(2);
const Operator* op = javascript()->CreateLiteralArray(
constant_elements, literal_flags, literal_index);
BuildCreateLiteral(op);
}
void BytecodeGraphBuilder::VisitCreateArrayLiteral(
const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED();
BuildCreateArrayLiteral(iterator);
}
void BytecodeGraphBuilder::VisitCreateArrayLiteralWide(
const interpreter::BytecodeArrayIterator& iterator) {
BuildCreateArrayLiteral(iterator);
}
void BytecodeGraphBuilder::BuildCreateObjectLiteral(
const interpreter::BytecodeArrayIterator& iterator) {
Handle<FixedArray> constant_properties =
Handle<FixedArray>::cast(iterator.GetConstantForIndexOperand(0));
int literal_index = iterator.GetIndexOperand(1);
int literal_flags = iterator.GetImmediateOperand(2);
const Operator* op = javascript()->CreateLiteralObject(
constant_properties, literal_flags, literal_index);
BuildCreateLiteral(op);
}
void BytecodeGraphBuilder::VisitCreateObjectLiteral(
const interpreter::BytecodeArrayIterator& iterator) {
UNIMPLEMENTED();
BuildCreateObjectLiteral(iterator);
}
void BytecodeGraphBuilder::VisitCreateObjectLiteralWide(
const interpreter::BytecodeArrayIterator& iterator) {
BuildCreateObjectLiteral(iterator);
}
......
......@@ -107,6 +107,13 @@ class BytecodeGraphBuilder {
interpreter::Register first_arg,
size_t arity);
void BuildCreateLiteral(const Operator* op);
void BuildCreateRegExpLiteral(
const interpreter::BytecodeArrayIterator& iterator);
void BuildCreateArrayLiteral(
const interpreter::BytecodeArrayIterator& iterator);
void BuildCreateObjectLiteral(
const interpreter::BytecodeArrayIterator& iterator);
void BuildLoadGlobal(const interpreter::BytecodeArrayIterator& iterator,
TypeofMode typeof_mode);
void BuildStoreGlobal(const interpreter::BytecodeArrayIterator& iterator);
......
......@@ -537,11 +537,17 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
int literal_index, int flags) {
Handle<String> pattern, int literal_index, int flags) {
DCHECK(FitsInImm8Operand(flags)); // Flags should fit in 8 bits.
if (FitsInIdx8Operand(literal_index)) {
Output(Bytecode::kCreateRegExpLiteral, static_cast<uint8_t>(literal_index),
static_cast<uint8_t>(flags));
size_t pattern_entry = GetConstantPoolEntry(pattern);
if (FitsInIdx8Operand(literal_index) && FitsInIdx8Operand(pattern_entry)) {
Output(Bytecode::kCreateRegExpLiteral, static_cast<uint8_t>(pattern_entry),
static_cast<uint8_t>(literal_index), static_cast<uint8_t>(flags));
} else if (FitsInIdx16Operand(literal_index) &&
FitsInIdx16Operand(pattern_entry)) {
Output(Bytecode::kCreateRegExpLiteralWide,
static_cast<uint16_t>(pattern_entry),
static_cast<uint16_t>(literal_index), static_cast<uint8_t>(flags));
} else {
UNIMPLEMENTED();
}
......@@ -550,11 +556,19 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
int literal_index, int flags) {
Handle<FixedArray> constant_elements, int literal_index, int flags) {
DCHECK(FitsInImm8Operand(flags)); // Flags should fit in 8 bits.
if (FitsInIdx8Operand(literal_index)) {
Output(Bytecode::kCreateArrayLiteral, static_cast<uint8_t>(literal_index),
static_cast<uint8_t>(flags));
size_t constant_elements_entry = GetConstantPoolEntry(constant_elements);
if (FitsInIdx8Operand(literal_index) &&
FitsInIdx8Operand(constant_elements_entry)) {
Output(Bytecode::kCreateArrayLiteral,
static_cast<uint8_t>(constant_elements_entry),
static_cast<uint8_t>(literal_index), static_cast<uint8_t>(flags));
} else if (FitsInIdx16Operand(literal_index) &&
FitsInIdx16Operand(constant_elements_entry)) {
Output(Bytecode::kCreateArrayLiteralWide,
static_cast<uint16_t>(constant_elements_entry),
static_cast<uint16_t>(literal_index), static_cast<uint8_t>(flags));
} else {
UNIMPLEMENTED();
}
......@@ -563,11 +577,19 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
int literal_index, int flags) {
Handle<FixedArray> constant_properties, int literal_index, int flags) {
DCHECK(FitsInImm8Operand(flags)); // Flags should fit in 8 bits.
if (FitsInIdx8Operand(literal_index)) {
Output(Bytecode::kCreateObjectLiteral, static_cast<uint8_t>(literal_index),
static_cast<uint8_t>(flags));
size_t constant_properties_entry = GetConstantPoolEntry(constant_properties);
if (FitsInIdx8Operand(literal_index) &&
FitsInIdx8Operand(constant_properties_entry)) {
Output(Bytecode::kCreateObjectLiteral,
static_cast<uint8_t>(constant_properties_entry),
static_cast<uint8_t>(literal_index), static_cast<uint8_t>(flags));
} else if (FitsInIdx16Operand(literal_index) &&
FitsInIdx16Operand(constant_properties_entry)) {
Output(Bytecode::kCreateObjectLiteralWide,
static_cast<uint16_t>(constant_properties_entry),
static_cast<uint16_t>(literal_index), static_cast<uint8_t>(flags));
} else {
UNIMPLEMENTED();
}
......
......@@ -125,9 +125,12 @@ class BytecodeArrayBuilder {
BytecodeArrayBuilder& CreateArguments(CreateArgumentsType type);
// Literals creation. Constant elements should be in the accumulator.
BytecodeArrayBuilder& CreateRegExpLiteral(int literal_index, int flags);
BytecodeArrayBuilder& CreateArrayLiteral(int literal_index, int flags);
BytecodeArrayBuilder& CreateObjectLiteral(int literal_index, int flags);
BytecodeArrayBuilder& CreateRegExpLiteral(Handle<String> pattern,
int literal_index, int flags);
BytecodeArrayBuilder& CreateArrayLiteral(Handle<FixedArray> constant_elements,
int literal_index, int flags);
BytecodeArrayBuilder& CreateObjectLiteral(
Handle<FixedArray> constant_properties, int literal_index, int flags);
// Push the context in accumulator as the new context, and store in register
// |context|.
......
......@@ -1040,18 +1040,17 @@ void BytecodeGenerator::VisitLiteral(Literal* expr) {
void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
// Materialize a regular expression literal.
TemporaryRegisterScope temporary_register_scope(builder());
builder()
->LoadLiteral(expr->pattern())
.CreateRegExpLiteral(expr->literal_index(), expr->flags());
builder()->CreateRegExpLiteral(expr->pattern(), expr->literal_index(),
expr->flags());
execution_result()->SetResultInAccumulator();
}
void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
// Deep-copy the literal boilerplate.
builder()
->LoadLiteral(expr->constant_properties())
.CreateObjectLiteral(expr->literal_index(), expr->ComputeFlags(true));
builder()->CreateObjectLiteral(expr->constant_properties(),
expr->literal_index(),
expr->ComputeFlags(true));
TemporaryRegisterScope temporary_register_scope(builder());
Register literal;
......@@ -1243,9 +1242,9 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
// Deep-copy the literal boilerplate.
builder()
->LoadLiteral(expr->constant_elements())
.CreateArrayLiteral(expr->literal_index(), expr->ComputeFlags(true));
builder()->CreateArrayLiteral(expr->constant_elements(),
expr->literal_index(),
expr->ComputeFlags(true));
TemporaryRegisterScope temporary_register_scope(builder());
Register index, literal;
......
......@@ -155,9 +155,18 @@ namespace interpreter {
V(ToObject, OperandType::kNone) \
\
/* Literals */ \
V(CreateRegExpLiteral, OperandType::kIdx8, OperandType::kImm8) \
V(CreateArrayLiteral, OperandType::kIdx8, OperandType::kImm8) \
V(CreateObjectLiteral, OperandType::kIdx8, OperandType::kImm8) \
V(CreateRegExpLiteral, OperandType::kIdx8, OperandType::kIdx8, \
OperandType::kImm8) \
V(CreateArrayLiteral, OperandType::kIdx8, OperandType::kIdx8, \
OperandType::kImm8) \
V(CreateObjectLiteral, OperandType::kIdx8, OperandType::kIdx8, \
OperandType::kImm8) \
V(CreateRegExpLiteralWide, OperandType::kIdx16, OperandType::kIdx16, \
OperandType::kImm8) \
V(CreateArrayLiteralWide, OperandType::kIdx16, OperandType::kIdx16, \
OperandType::kImm8) \
V(CreateObjectLiteralWide, OperandType::kIdx16, OperandType::kIdx16, \
OperandType::kImm8) \
\
/* Closure allocation */ \
V(CreateClosure, OperandType::kIdx8, OperandType::kImm8) \
......
......@@ -1305,10 +1305,11 @@ void Interpreter::DoJumpIfUndefinedConstant(
void Interpreter::DoCreateLiteral(Runtime::FunctionId function_id,
compiler::InterpreterAssembler* assembler) {
Node* constant_elements = __ GetAccumulator();
Node* literal_index_raw = __ BytecodeOperandIdx(0);
Node* index = __ BytecodeOperandIdx(0);
Node* constant_elements = __ LoadConstantPoolEntry(index);
Node* literal_index_raw = __ BytecodeOperandIdx(1);
Node* literal_index = __ SmiTag(literal_index_raw);
Node* flags_raw = __ BytecodeOperandImm(1);
Node* flags_raw = __ BytecodeOperandImm(2);
Node* flags = __ SmiTag(flags_raw);
Node* closure = __ LoadRegister(Register::function_closure());
Node* result = __ CallRuntime(function_id, closure, literal_index,
......@@ -1318,36 +1319,66 @@ void Interpreter::DoCreateLiteral(Runtime::FunctionId function_id,
}
// CreateRegExpLiteral <idx> <flags>
// CreateRegExpLiteral <pattern_idx> <literal_idx> <flags>
//
// Creates a regular expression literal for literal index <idx> with <flags> and
// the pattern in the accumulator.
// Creates a regular expression literal for literal index <literal_idx> with
// <flags> and the pattern in <pattern_idx>.
void Interpreter::DoCreateRegExpLiteral(
compiler::InterpreterAssembler* assembler) {
DoCreateLiteral(Runtime::kCreateRegExpLiteral, assembler);
}
// CreateArrayLiteral <idx> <flags>
// CreateRegExpLiteralWide <pattern_idx> <literal_idx> <flags>
//
// Creates a regular expression literal for literal index <literal_idx> with
// <flags> and the pattern in <pattern_idx>.
void Interpreter::DoCreateRegExpLiteralWide(
compiler::InterpreterAssembler* assembler) {
DoCreateLiteral(Runtime::kCreateRegExpLiteral, assembler);
}
// CreateArrayLiteral <element_idx> <literal_idx> <flags>
//
// Creates an array literal for literal index <idx> with flags <flags> and
// constant elements in the accumulator.
// Creates an array literal for literal index <literal_idx> with flags <flags>
// and constant elements in <element_idx>.
void Interpreter::DoCreateArrayLiteral(
compiler::InterpreterAssembler* assembler) {
DoCreateLiteral(Runtime::kCreateArrayLiteral, assembler);
}
// CreateObjectLiteral <idx> <flags>
// CreateArrayLiteralWide <element_idx> <literal_idx> <flags>
//
// Creates an object literal for literal index <idx> with flags <flags> and
// constant elements in the accumulator.
// Creates an array literal for literal index <literal_idx> with flags <flags>
// and constant elements in <element_idx>.
void Interpreter::DoCreateArrayLiteralWide(
compiler::InterpreterAssembler* assembler) {
DoCreateLiteral(Runtime::kCreateArrayLiteral, assembler);
}
// CreateObjectLiteral <element_idx> <literal_idx> <flags>
//
// Creates an object literal for literal index <literal_idx> with flags <flags>
// and constant elements in <element_idx>.
void Interpreter::DoCreateObjectLiteral(
compiler::InterpreterAssembler* assembler) {
DoCreateLiteral(Runtime::kCreateObjectLiteral, assembler);
}
// CreateObjectLiteralWide <element_idx> <literal_idx> <flags>
//
// Creates an object literal for literal index <literal_idx> with flags <flags>
// and constant elements in <element_idx>.
void Interpreter::DoCreateObjectLiteralWide(
compiler::InterpreterAssembler* assembler) {
DoCreateLiteral(Runtime::kCreateObjectLiteral, assembler);
}
// CreateClosure <index> <tenured>
//
// Creates a new closure for SharedFunctionInfo at position |index| in the
......
......@@ -1183,6 +1183,150 @@ TEST(BytecodeGraphBuilderLoadContext) {
}
}
TEST(BytecodeGraphBuilderRegExpLiterals) {
HandleAndZoneScope scope;
Isolate* isolate = scope.main_isolate();
Zone* zone = scope.main_zone();
Factory* factory = isolate->factory();
ExpectedSnippet<0> snippets[] = {
{"return /abd/.exec('cccabbdd');", {factory->null_value()}},
{"return /ab+d/.exec('cccabbdd')[0];",
{factory->NewStringFromStaticChars("abbd")}},
{"var a = 3.1414;"
REPEAT_256(SPACE, "a = 3.1414;")
"return /ab+d/.exec('cccabbdd')[0];",
{factory->NewStringFromStaticChars("abbd")}},
{"return /ab+d/.exec('cccabbdd')[1];", {factory->undefined_value()}},
{"return /AbC/i.exec('ssaBC')[0];",
{factory->NewStringFromStaticChars("aBC")}},
{"return 'ssaBC'.match(/AbC/i)[0];",
{factory->NewStringFromStaticChars("aBC")}},
{"return 'ssaBCtAbC'.match(/(AbC)/gi)[1];",
{factory->NewStringFromStaticChars("AbC")}},
};
size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
for (size_t i = 0; i < num_snippets; i++) {
ScopedVector<char> script(4096);
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(BytecodeGraphBuilderArrayLiterals) {
HandleAndZoneScope scope;
Isolate* isolate = scope.main_isolate();
Zone* zone = scope.main_zone();
Factory* factory = isolate->factory();
ExpectedSnippet<0> snippets[] = {
{"return [][0];", {factory->undefined_value()}},
{"return [1, 3, 2][1];", {factory->NewNumberFromInt(3)}},
{"var a;" REPEAT_256(SPACE, "a = 9.87;") "return [1, 3, 2][1];",
{factory->NewNumberFromInt(3)}},
{"return ['a', 'b', 'c'][2];", {factory->NewStringFromStaticChars("c")}},
{"var a = 100; return [a, a++, a + 2, a + 3][2];",
{factory->NewNumberFromInt(103)}},
{"var a = 100; return [a, ++a, a + 2, a + 3][1];",
{factory->NewNumberFromInt(101)}},
{"var a = 9.2;"
REPEAT_256(SPACE, "a = 9.34;")
"return [a, ++a, a + 2, a + 3][2];",
{factory->NewHeapNumber(12.34)}},
{"return [[1, 2, 3], ['a', 'b', 'c']][1][0];",
{factory->NewStringFromStaticChars("a")}},
{"var t = 't'; return [[t, t + 'est'], [1 + t]][0][1];",
{factory->NewStringFromStaticChars("test")}},
{"var t = 't'; return [[t, t + 'est'], [1 + t]][1][0];",
{factory->NewStringFromStaticChars("1t")}}};
size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
for (size_t i = 0; i < num_snippets; i++) {
ScopedVector<char> script(4096);
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(BytecodeGraphBuilderObjectLiterals) {
HandleAndZoneScope scope;
Isolate* isolate = scope.main_isolate();
Zone* zone = scope.main_zone();
Factory* factory = isolate->factory();
ExpectedSnippet<0> snippets[] = {
{"return { }.name;", {factory->undefined_value()}},
{"return { name: 'string', val: 9.2 }.name;",
{factory->NewStringFromStaticChars("string")}},
{"var a;\n"
REPEAT_256(SPACE, "a = 1.23;\n")
"return { name: 'string', val: 9.2 }.name;",
{factory->NewStringFromStaticChars("string")}},
{"return { name: 'string', val: 9.2 }['name'];",
{factory->NewStringFromStaticChars("string")}},
{"var a = 15; return { name: 'string', val: a }.val;",
{factory->NewNumberFromInt(15)}},
{"var a;"
REPEAT_256(SPACE, "a = 1.23;")
"return { name: 'string', val: a }.val;",
{factory->NewHeapNumber(1.23)}},
{"var a = 15; var b = 'val'; return { name: 'string', val: a }[b];",
{factory->NewNumberFromInt(15)}},
{"var a = 5; return { val: a, val: a + 1 }.val;",
{factory->NewNumberFromInt(6)}},
{"return { func: function() { return 'test' } }.func();",
{factory->NewStringFromStaticChars("test")}},
{"return { func(a) { return a + 'st'; } }.func('te');",
{factory->NewStringFromStaticChars("test")}},
{"return { get a() { return 22; } }.a;", {factory->NewNumberFromInt(22)}},
{"var a = { get b() { return this.x + 't'; },\n"
" set b(val) { this.x = val + 's' } };\n"
"a.b = 'te';\n"
"return a.b;",
{factory->NewStringFromStaticChars("test")}},
{"var a = 123; return { 1: a }[1];", {factory->NewNumberFromInt(123)}},
{"return Object.getPrototypeOf({ __proto__: null });",
{factory->null_value()}},
{"var a = 'test'; return { [a]: 1 }.test;",
{factory->NewNumberFromInt(1)}},
{"var a = 'test'; return { b: a, [a]: a + 'ing' }['test']",
{factory->NewStringFromStaticChars("testing")}},
{"var a = 'proto_str';\n"
"var b = { [a]: 1, __proto__: { var : a } };\n"
"return Object.getPrototypeOf(b).var",
{factory->NewStringFromStaticChars("proto_str")}},
{"var n = 'name';\n"
"return { [n]: 'val', get a() { return 987 } }['a'];",
{factory->NewNumberFromInt(987)}},
};
size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
for (size_t i = 0; i < num_snippets; i++) {
ScopedVector<char> script(4096);
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()));
}
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -104,10 +104,10 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
builder.CreateArguments(CreateArgumentsType::kMappedArguments)
.CreateArguments(CreateArgumentsType::kUnmappedArguments);
// Emit literal creation operations
builder.CreateRegExpLiteral(0, 0)
.CreateArrayLiteral(0, 0)
.CreateObjectLiteral(0, 0);
// Emit literal creation operations.
builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("a"), 0, 0)
.CreateArrayLiteral(factory->NewFixedArray(1), 0, 0)
.CreateObjectLiteral(factory->NewFixedArray(1), 0, 0);
// Call operations.
builder.Call(reg, reg, 0, 0)
......@@ -224,6 +224,12 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
false);
builder.CreateClosure(shared_info2, NOT_TENURED);
// Emit wide variant of literal creation operations.
builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("wide_literal"),
0, 0)
.CreateArrayLiteral(factory->NewFixedArray(2), 0, 0)
.CreateObjectLiteral(factory->NewFixedArray(2), 0, 0);
builder.Return();
// Generate BytecodeArray.
......
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