| Index: test/cctest/interpreter/test-bytecode-generator.cc
|
| diff --git a/test/cctest/interpreter/test-bytecode-generator.cc b/test/cctest/interpreter/test-bytecode-generator.cc
|
| index 16dc3eea2b16bfd54434d083ec5bbff5c3bfbf5a..a9eb58aa3aa84c300a3c4d47ac57251bf7f4c7bf 100644
|
| --- a/test/cctest/interpreter/test-bytecode-generator.cc
|
| +++ b/test/cctest/interpreter/test-bytecode-generator.cc
|
| @@ -50,12 +50,15 @@ class BytecodeGeneratorHelper {
|
|
|
|
|
| // Structure for containing expected bytecode snippets.
|
| +template<typename T>
|
| struct ExpectedSnippet {
|
| const char* body;
|
| int frame_size;
|
| int parameter_count;
|
| int bytecode_length;
|
| const uint8_t bytecode[16];
|
| + int constant_count;
|
| + T constants[16];
|
| };
|
|
|
|
|
| @@ -69,16 +72,16 @@ TEST(PrimitiveReturnStatements) {
|
| InitializedHandleScope handle_scope;
|
| BytecodeGeneratorHelper helper;
|
|
|
| - ExpectedSnippet snippets[] = {
|
| - {"return;", 0, 1, 2, {B(LdaUndefined), B(Return)}},
|
| - {"return null;", 0, 1, 2, {B(LdaNull), B(Return)}},
|
| - {"return true;", 0, 1, 2, {B(LdaTrue), B(Return)}},
|
| - {"return false;", 0, 1, 2, {B(LdaFalse), B(Return)}},
|
| - {"return 0;", 0, 1, 2, {B(LdaZero), B(Return)}},
|
| - {"return +1;", 0, 1, 3, {B(LdaSmi8), U8(1), B(Return)}},
|
| - {"return -1;", 0, 1, 3, {B(LdaSmi8), U8(-1), B(Return)}},
|
| - {"return +127;", 0, 1, 3, {B(LdaSmi8), U8(127), B(Return)}},
|
| - {"return -128;", 0, 1, 3, {B(LdaSmi8), U8(-128), B(Return)}},
|
| + ExpectedSnippet<void*> snippets[] = {
|
| + {"return;", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0},
|
| + {"return null;", 0, 1, 2, {B(LdaNull), B(Return)}, 0},
|
| + {"return true;", 0, 1, 2, {B(LdaTrue), B(Return)}, 0},
|
| + {"return false;", 0, 1, 2, {B(LdaFalse), B(Return)}, 0},
|
| + {"return 0;", 0, 1, 2, {B(LdaZero), B(Return)}, 0},
|
| + {"return +1;", 0, 1, 3, {B(LdaSmi8), U8(1), B(Return)}, 0},
|
| + {"return -1;", 0, 1, 3, {B(LdaSmi8), U8(-1), B(Return)}, 0},
|
| + {"return +127;", 0, 1, 3, {B(LdaSmi8), U8(127), B(Return)}, 0},
|
| + {"return -128;", 0, 1, 3, {B(LdaSmi8), U8(-128), B(Return)}, 0},
|
| };
|
|
|
| size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
|
| @@ -90,6 +93,7 @@ TEST(PrimitiveReturnStatements) {
|
| CHECK_EQ(ba->length(), snippets[i].bytecode_length);
|
| CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode,
|
| ba->length()));
|
| + CHECK_EQ(ba->constant_pool(), CcTest::heap()->empty_fixed_array());
|
| }
|
| }
|
|
|
| @@ -98,7 +102,7 @@ TEST(PrimitiveExpressions) {
|
| InitializedHandleScope handle_scope;
|
| BytecodeGeneratorHelper helper;
|
|
|
| - ExpectedSnippet snippets[] = {
|
| + ExpectedSnippet<void*> snippets[] = {
|
| {"var x = 0; return x;",
|
| kPointerSize,
|
| 1,
|
| @@ -108,7 +112,9 @@ TEST(PrimitiveExpressions) {
|
| B(Star), R(0), //
|
| B(Ldar), R(0), //
|
| B(Return) //
|
| - }},
|
| + },
|
| + 0
|
| + },
|
| {"var x = 0; return x + 3;",
|
| 2 * kPointerSize,
|
| 1,
|
| @@ -121,7 +127,9 @@ TEST(PrimitiveExpressions) {
|
| B(LdaSmi8), U8(3), //
|
| B(Add), R(1), //
|
| B(Return) //
|
| - }}};
|
| + },
|
| + 0
|
| + }};
|
|
|
| size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
|
| for (size_t i = 0; i < num_snippets; i++) {
|
| @@ -132,6 +140,7 @@ TEST(PrimitiveExpressions) {
|
| CHECK_EQ(ba->length(), snippets[i].bytecode_length);
|
| CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode,
|
| ba->length()));
|
| + CHECK_EQ(ba->constant_pool(), CcTest::heap()->empty_fixed_array());
|
| }
|
| }
|
|
|
| @@ -142,17 +151,17 @@ TEST(Parameters) {
|
|
|
| int last_param_index =
|
| -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize;
|
| - ExpectedSnippet snippets[] = {
|
| + ExpectedSnippet<void*> snippets[] = {
|
| {"function f() { return this; }",
|
| - 0, 1, 3, {B(Ldar), R(last_param_index), B(Return)}},
|
| + 0, 1, 3, {B(Ldar), R(last_param_index), B(Return)}, 0},
|
| {"function f(arg1) { return arg1; }",
|
| - 0, 2, 3, {B(Ldar), R(last_param_index), B(Return)}},
|
| + 0, 2, 3, {B(Ldar), R(last_param_index), B(Return)}, 0},
|
| {"function f(arg1) { return this; }",
|
| - 0, 2, 3, {B(Ldar), R(last_param_index - 1), B(Return)}},
|
| + 0, 2, 3, {B(Ldar), R(last_param_index - 1), B(Return)}, 0},
|
| {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return arg4; }",
|
| - 0, 8, 3, {B(Ldar), R(last_param_index - 3), B(Return)}},
|
| + 0, 8, 3, {B(Ldar), R(last_param_index - 3), B(Return)}, 0},
|
| {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return this; }",
|
| - 0, 8, 3, {B(Ldar), R(last_param_index - 7), B(Return)}}
|
| + 0, 8, 3, {B(Ldar), R(last_param_index - 7), B(Return)}, 0}
|
| };
|
|
|
| size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
|
| @@ -163,9 +172,160 @@ TEST(Parameters) {
|
| CHECK_EQ(ba->length(), snippets[i].bytecode_length);
|
| CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode,
|
| ba->length()));
|
| + CHECK_EQ(ba->constant_pool(), CcTest::heap()->empty_fixed_array());
|
| }
|
| }
|
|
|
| +
|
| +TEST(Constants) {
|
| + InitializedHandleScope handle_scope;
|
| + BytecodeGeneratorHelper helper;
|
| +
|
| + // Check large SMIs.
|
| + {
|
| + ExpectedSnippet<int> snippets[] = {
|
| + {"return 12345678;", 0, 1, 3,
|
| + {
|
| + B(LdaConstant), U8(0),
|
| + B(Return)
|
| + }, 1, { 12345678 }
|
| + },
|
| + {"var a = 1234; return 5678;", 1 * kPointerSize, 1, 7,
|
| + {
|
| + B(LdaConstant), U8(0),
|
| + B(Star), R(0),
|
| + B(LdaConstant), U8(1),
|
| + B(Return)
|
| + }, 2, { 1234, 5678 }
|
| + },
|
| + {"var a = 1234; return 1234;",
|
| + 1 * kPointerSize, 1, 7,
|
| + {
|
| + B(LdaConstant), U8(0),
|
| + B(Star), R(0),
|
| + B(LdaConstant), U8(0),
|
| + B(Return)
|
| + }, 1, { 1234 }
|
| + }
|
| + };
|
| +
|
| + size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
|
| + for (size_t i = 0; i < num_snippets; i++) {
|
| + Handle<BytecodeArray> ba =
|
| + helper.MakeBytecodeForFunctionBody(snippets[i].body);
|
| + CHECK_EQ(ba->frame_size(), snippets[i].frame_size);
|
| + CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count);
|
| + CHECK_EQ(ba->length(), snippets[i].bytecode_length);
|
| + CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode,
|
| + ba->length()));
|
| + CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count);
|
| + for (int j = 0; j < snippets[i].constant_count; j++) {
|
| + CHECK_EQ(Smi::cast(ba->constant_pool()->get(j))->value(),
|
| + snippets[i].constants[j]);
|
| + }
|
| + }
|
| + }
|
| +
|
| + // Check heap number double constants
|
| + {
|
| + ExpectedSnippet<double> snippets[] = {
|
| + {"return 1.2;",
|
| + 0, 1, 3,
|
| + {
|
| + B(LdaConstant), U8(0),
|
| + B(Return)
|
| + }, 1, { 1.2 }
|
| + },
|
| + {"var a = 1.2; return 2.6;", 1 * kPointerSize, 1, 7,
|
| + {
|
| + B(LdaConstant), U8(0),
|
| + B(Star), R(0),
|
| + B(LdaConstant), U8(1),
|
| + B(Return)
|
| + }, 2, { 1.2, 2.6 }
|
| + },
|
| + {"var a = 3.14; return 3.14;", 1 * kPointerSize, 1, 7,
|
| + {
|
| + B(LdaConstant), U8(0),
|
| + B(Star), R(0),
|
| + B(LdaConstant), U8(1),
|
| + B(Return)
|
| + }, 2,
|
| + // TODO(rmcilroy): Currently multiple identical double literals end up
|
| + // being allocated as new HeapNumbers and so require multiple constant
|
| + // pool entries. De-dup identical values.
|
| + { 3.14, 3.14 }
|
| + }
|
| + };
|
| +
|
| + size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
|
| + for (size_t i = 0; i < num_snippets; i++) {
|
| + Handle<BytecodeArray> ba =
|
| + helper.MakeBytecodeForFunctionBody(snippets[i].body);
|
| + CHECK_EQ(ba->frame_size(), snippets[i].frame_size);
|
| + CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count);
|
| + CHECK_EQ(ba->length(), snippets[i].bytecode_length);
|
| + CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode,
|
| + ba->length()));
|
| + CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count);
|
| + for (int j = 0; j < snippets[i].constant_count; j++) {
|
| + CHECK_EQ(HeapNumber::cast(ba->constant_pool()->get(j))->value(),
|
| + snippets[i].constants[j]);
|
| + }
|
| + }
|
| + }
|
| +
|
| + // Check string literals
|
| + {
|
| + ExpectedSnippet<const char*> snippets[] = {
|
| + {"return \"This is a string\";", 0, 1, 3,
|
| + {
|
| + B(LdaConstant), U8(0),
|
| + B(Return)
|
| + }, 1,
|
| + { "This is a string" }
|
| + },
|
| + {"var a = \"First string\"; return \"Second string\";",
|
| + 1 * kPointerSize, 1, 7,
|
| + {
|
| + B(LdaConstant), U8(0),
|
| + B(Star), R(0),
|
| + B(LdaConstant), U8(1),
|
| + B(Return)
|
| + }, 2, { "First string", "Second string"}
|
| + },
|
| + {"var a = \"Same string\"; return \"Same string\";",
|
| + 1 * kPointerSize, 1, 7,
|
| + {
|
| + B(LdaConstant), U8(0),
|
| + B(Star), R(0),
|
| + B(LdaConstant), U8(0),
|
| + B(Return)
|
| + }, 1, { "Same string" }
|
| + }
|
| + };
|
| +
|
| + size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
|
| + for (size_t i = 0; i < num_snippets; i++) {
|
| + Handle<BytecodeArray> ba =
|
| + helper.MakeBytecodeForFunctionBody(snippets[i].body);
|
| + CHECK_EQ(ba->frame_size(), snippets[i].frame_size);
|
| + CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count);
|
| + CHECK_EQ(ba->length(), snippets[i].bytecode_length);
|
| + CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode,
|
| + ba->length()));
|
| + CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count);
|
| + for (int j = 0; j < snippets[i].constant_count; j++) {
|
| + Handle<String> expected =
|
| + CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(
|
| + snippets[i].constants[j]);
|
| + CHECK(String::cast(ba->constant_pool()->get(j))->Equals(*expected));
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| } // namespace interpreter
|
| } // namespace internal
|
| } // namespance v8
|
|
|