diff options
Diffstat (limited to 'deps/v8/test/cctest/interpreter')
-rw-r--r-- | deps/v8/test/cctest/interpreter/test-bytecode-generator.cc | 4038 | ||||
-rw-r--r-- | deps/v8/test/cctest/interpreter/test-interpreter.cc | 751 |
2 files changed, 3454 insertions, 1335 deletions
diff --git a/deps/v8/test/cctest/interpreter/test-bytecode-generator.cc b/deps/v8/test/cctest/interpreter/test-bytecode-generator.cc index c29eb9659d..2c06da26a1 100644 --- a/deps/v8/test/cctest/interpreter/test-bytecode-generator.cc +++ b/deps/v8/test/cctest/interpreter/test-bytecode-generator.cc @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// TODO(rmcilroy): Remove this define after this flag is turned on globally -#define V8_IMMINENT_DEPRECATION_WARNINGS - #include "src/v8.h" #include "src/compiler.h" @@ -26,12 +23,13 @@ class BytecodeGeneratorHelper { -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; BytecodeGeneratorHelper() { - i::FLAG_vector_stores = true; i::FLAG_ignition = true; i::FLAG_ignition_fake_try_catch = true; + i::FLAG_ignition_fallback_on_eval_and_catch = false; i::FLAG_ignition_filter = StrDup(kFunctionName); i::FLAG_always_opt = false; i::FLAG_allow_natives_syntax = true; + i::FLAG_legacy_const = true; CcTest::i_isolate()->interpreter()->Initialize(); } @@ -59,10 +57,22 @@ class BytecodeGeneratorHelper { return handle(js_function->shared()->bytecode_array(), CcTest::i_isolate()); } + Handle<BytecodeArray> MakeBytecode(const char* script, const char* filter, + const char* function_name) { + const char* old_ignition_filter = i::FLAG_ignition_filter; + i::FLAG_ignition_filter = filter; + Handle<BytecodeArray> return_val = MakeBytecode(script, function_name); + i::FLAG_ignition_filter = old_ignition_filter; + return return_val; + } + Handle<BytecodeArray> MakeBytecodeForFunctionBody(const char* body) { - ScopedVector<char> program(3072); - SNPrintF(program, "function %s() { %s }\n%s();", kFunctionName, body, - kFunctionName); + static const char kFormat[] = "function %s() { %s }\n%s();"; + static const int kFormatLength = arraysize(kFormat); + int length = kFormatLength + 2 * StrLength(kFunctionName) + StrLength(body); + ScopedVector<char> program(length); + length = SNPrintF(program, kFormat, kFunctionName, body, kFunctionName); + CHECK_GT(length, 0); return MakeBytecode(program.start(), kFunctionName); } @@ -73,14 +83,9 @@ class BytecodeGeneratorHelper { } Handle<BytecodeArray> MakeBytecodeForFunctionNoFilter(const char* function) { - const char* old_ignition_filter = i::FLAG_ignition_filter; - i::FLAG_ignition_filter = "*"; ScopedVector<char> program(3072); SNPrintF(program, "%s\n%s();", function, kFunctionName); - Handle<BytecodeArray> return_val = - MakeBytecode(program.start(), kFunctionName); - i::FLAG_ignition_filter = old_ignition_filter; - return return_val; + return MakeBytecode(program.start(), "*", kFunctionName); } }; @@ -94,17 +99,25 @@ class BytecodeGeneratorHelper { #if defined(V8_TARGET_LITTLE_ENDIAN) #define U16(x) static_cast<uint8_t>((x) & 0xff), \ static_cast<uint8_t>(((x) >> kBitsPerByte) & 0xff) +#define U16I(x) static_cast<uint8_t>((x) & 0xff), \ + static_cast<uint8_t>(((x++) >> kBitsPerByte) & 0xff) #elif defined(V8_TARGET_BIG_ENDIAN) #define U16(x) static_cast<uint8_t>(((x) >> kBitsPerByte) & 0xff), \ static_cast<uint8_t>((x) & 0xff) +#define U16I(x) static_cast<uint8_t>(((x) >> kBitsPerByte) & 0xff), \ + static_cast<uint8_t>((x++) & 0xff) #else #error Unknown byte ordering #endif +#define XSTR(A) #A +#define STR(A) XSTR(A) + #define COMMA() , #define SPACE() +#define UNIQUE_VAR() "var a" STR(__COUNTER__) " = 0;\n" -#define REPEAT_2(SEP, ...) \ +#define REPEAT_2(SEP, ...) \ __VA_ARGS__ SEP() __VA_ARGS__ #define REPEAT_4(SEP, ...) \ REPEAT_2(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) @@ -127,6 +140,16 @@ class BytecodeGeneratorHelper { REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) SEP() \ __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. template<typename T, int C = 6> struct ExpectedSnippet { @@ -264,124 +287,134 @@ TEST(PrimitiveExpressions) { {"var x = 0; return x;", kPointerSize, 1, - 6, + 4, {B(LdaZero), // B(Star), R(0), // - B(Ldar), R(0), // B(Return)}, 0}, {"var x = 0; return x + 3;", - kPointerSize, + 2 * kPointerSize, 1, - 8, + 10, {B(LdaZero), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(3), // - B(Add), R(0), // + B(Add), R(1), // B(Return)}, 0}, {"var x = 0; return x - 3;", - kPointerSize, + 2 * kPointerSize, 1, - 8, + 10, {B(LdaZero), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(3), // - B(Sub), R(0), // + B(Sub), R(1), // B(Return)}, 0}, {"var x = 4; return x * 3;", - kPointerSize, + 2 * kPointerSize, 1, - 9, + 11, {B(LdaSmi8), U8(4), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(3), // - B(Mul), R(0), // + B(Mul), R(1), // B(Return)}, 0}, {"var x = 4; return x / 3;", - kPointerSize, + 2 * kPointerSize, 1, - 9, + 11, {B(LdaSmi8), U8(4), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(3), // - B(Div), R(0), // + B(Div), R(1), // B(Return)}, 0}, {"var x = 4; return x % 3;", - kPointerSize, + 2 * kPointerSize, 1, - 9, + 11, {B(LdaSmi8), U8(4), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(3), // - B(Mod), R(0), // + B(Mod), R(1), // B(Return)}, 0}, {"var x = 1; return x | 2;", - kPointerSize, + 2 * kPointerSize, 1, - 9, + 11, {B(LdaSmi8), U8(1), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(2), // - B(BitwiseOr), R(0), // + B(BitwiseOr), R(1), // B(Return)}, 0}, {"var x = 1; return x ^ 2;", - kPointerSize, + 2 * kPointerSize, 1, - 9, + 11, {B(LdaSmi8), U8(1), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(2), // - B(BitwiseXor), R(0), // + B(BitwiseXor), R(1), // B(Return)}, 0}, {"var x = 1; return x & 2;", - kPointerSize, + 2 * kPointerSize, 1, - 9, + 11, {B(LdaSmi8), U8(1), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(2), // - B(BitwiseAnd), R(0), // + B(BitwiseAnd), R(1), // B(Return)}, 0}, {"var x = 10; return x << 3;", - kPointerSize, + 2 * kPointerSize, 1, - 9, + 11, {B(LdaSmi8), U8(10), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(3), // - B(ShiftLeft), R(0), // + B(ShiftLeft), R(1), // B(Return)}, 0}, {"var x = 10; return x >> 3;", - kPointerSize, + 2 * kPointerSize, 1, - 9, + 11, {B(LdaSmi8), U8(10), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(3), // - B(ShiftRight), R(0), // + B(ShiftRight), R(1), // B(Return)}, 0}, {"var x = 10; return x >>> 3;", - kPointerSize, + 2 * kPointerSize, 1, - 9, + 11, {B(LdaSmi8), U8(10), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(3), // - B(ShiftRightLogical), R(0), // + B(ShiftRightLogical), R(1), // B(Return)}, 0}, {"var x = 0; return (x, 3);", - kPointerSize, + 1 * kPointerSize, 1, 6, {B(LdaZero), // @@ -402,27 +435,26 @@ TEST(LogicalExpressions) { InitializedHandleScope handle_scope; BytecodeGeneratorHelper helper; - ExpectedSnippet<int> snippets[] = { {"var x = 0; return x || 3;", 1 * kPointerSize, 1, - 10, + 8, {B(LdaZero), // B(Star), R(0), // - B(Ldar), R(0), // B(JumpIfToBooleanTrue), U8(4), // B(LdaSmi8), U8(3), // B(Return)}, 0}, {"var x = 0; return (x == 1) || 3;", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 12, + 14, {B(LdaZero), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(1), // - B(TestEqual), R(0), // + B(TestEqual), R(1), // B(JumpIfTrue), U8(4), // B(LdaSmi8), U8(3), // B(Return)}, @@ -430,22 +462,22 @@ TEST(LogicalExpressions) { {"var x = 0; return x && 3;", 1 * kPointerSize, 1, - 10, + 8, {B(LdaZero), // B(Star), R(0), // - B(Ldar), R(0), // B(JumpIfToBooleanFalse), U8(4), // B(LdaSmi8), U8(3), // B(Return)}, 0}, {"var x = 0; return (x == 0) && 3;", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 11, + 13, {B(LdaZero), // B(Star), R(0), // + B(Star), R(1), // B(LdaZero), // - B(TestEqual), R(0), // + B(TestEqual), R(1), // B(JumpIfFalse), U8(4), // B(LdaSmi8), U8(3), // B(Return)}, @@ -453,10 +485,9 @@ TEST(LogicalExpressions) { {"var x = 0; return x || (1, 2, 3);", 1 * kPointerSize, 1, - 10, + 8, {B(LdaZero), // B(Star), R(0), // - B(Ldar), R(0), // B(JumpIfToBooleanTrue), U8(4), // B(LdaSmi8), U8(3), // B(Return)}, @@ -464,18 +495,22 @@ TEST(LogicalExpressions) { {"var a = 2, b = 3, c = 4; return a || (a, b, a, b, c = 5, 3);", 3 * kPointerSize, 1, - 23, - {B(LdaSmi8), U8(2), // - B(Star), R(0), // - B(LdaSmi8), U8(3), // - B(Star), R(1), // - B(LdaSmi8), U8(4), // - B(Star), R(2), // - B(Ldar), R(0), // - B(JumpIfToBooleanTrue), U8(8), // - B(LdaSmi8), U8(5), // - B(Star), R(2), // - B(LdaSmi8), U8(3), // + 31, + {B(LdaSmi8), U8(2), // + B(Star), R(0), // + B(LdaSmi8), U8(3), // + B(Star), R(1), // + B(LdaSmi8), U8(4), // + B(Star), R(2), // + B(Ldar), R(0), // + B(JumpIfToBooleanTrue), U8(16), // + B(Ldar), R(0), // + B(Ldar), R(1), // + B(Ldar), R(0), // + B(Ldar), R(1), // + B(LdaSmi8), U8(5), // + B(Star), R(2), // + B(LdaSmi8), U8(3), // B(Return)}, 0}, {"var x = 1; var a = 2, b = 3; return x || (" @@ -493,10 +528,10 @@ TEST(LogicalExpressions) { B(Ldar), R(0), // B(JumpIfToBooleanTrueConstant), U8(0), // REPEAT_32(COMMA, // - B(LdaSmi8), U8(1), // - B(Star), R(1), // - B(LdaSmi8), U8(2), // - B(Star), R(2)), // + B(LdaSmi8), U8(1), // + B(Star), R(1), // + B(LdaSmi8), U8(2), // + B(Star), R(2)), // B(LdaSmi8), U8(3), // B(Return)}, 1, @@ -516,10 +551,10 @@ TEST(LogicalExpressions) { B(Ldar), R(0), // B(JumpIfToBooleanFalseConstant), U8(0), // REPEAT_32(COMMA, // - B(LdaSmi8), U8(1), // - B(Star), R(1), // - B(LdaSmi8), U8(2), // - B(Star), R(2)), // + B(LdaSmi8), U8(1), // + B(Star), R(1), // + B(LdaSmi8), U8(2), // + B(Star), R(2)), // B(LdaSmi8), U8(3), // B(Return)}, // 1, @@ -527,23 +562,25 @@ TEST(LogicalExpressions) { {"var x = 1; var a = 2, b = 3; return (x > 3) || (" REPEAT_32(SPACE, "a = 1, b = 2, ") "3);", - 3 * kPointerSize, + 4 * kPointerSize, 1, - 277, + 281, {B(LdaSmi8), U8(1), // B(Star), R(0), // B(LdaSmi8), U8(2), // B(Star), R(1), // B(LdaSmi8), U8(3), // B(Star), R(2), // + B(Ldar), R(0), // + B(Star), R(3), // B(LdaSmi8), U8(3), // - B(TestGreaterThan), R(0), // + B(TestGreaterThan), R(3), // B(JumpIfTrueConstant), U8(0), // REPEAT_32(COMMA, // - B(LdaSmi8), U8(1), // - B(Star), R(1), // - B(LdaSmi8), U8(2), // - B(Star), R(2)), // + B(LdaSmi8), U8(1), // + B(Star), R(1), // + B(LdaSmi8), U8(2), // + B(Star), R(2)), // B(LdaSmi8), U8(3), // B(Return)}, 1, @@ -551,23 +588,25 @@ TEST(LogicalExpressions) { {"var x = 0; var a = 2, b = 3; return (x < 5) && (" REPEAT_32(SPACE, "a = 1, b = 2, ") "3);", - 3 * kPointerSize, + 4 * kPointerSize, 1, - 276, + 280, {B(LdaZero), // B(Star), R(0), // B(LdaSmi8), U8(2), // B(Star), R(1), // B(LdaSmi8), U8(3), // B(Star), R(2), // + B(Ldar), R(0), // + B(Star), R(3), // B(LdaSmi8), U8(5), // - B(TestLessThan), R(0), // + B(TestLessThan), R(3), // B(JumpIfFalseConstant), U8(0), // REPEAT_32(COMMA, // - B(LdaSmi8), U8(1), // - B(Star), R(1), // - B(LdaSmi8), U8(2), // - B(Star), R(2)), // + B(LdaSmi8), U8(1), // + B(Star), R(1), // + B(LdaSmi8), U8(2), // + B(Star), R(2)), // B(LdaSmi8), U8(3), // B(Return)}, 1, @@ -589,10 +628,9 @@ TEST(LogicalExpressions) { {"var x = 1; return x && 3 || 0, 1;", 1 * kPointerSize, 1, - 16, + 14, {B(LdaSmi8), U8(1), // B(Star), R(0), // - B(Ldar), R(0), // B(JumpIfToBooleanFalse), U8(4), // B(LdaSmi8), U8(3), // B(JumpIfToBooleanTrue), U8(3), // @@ -856,154 +894,205 @@ TEST(PropertyLoads) { ExpectedSnippet<const char*> snippets[] = { {"function f(a) { return a.name; }\nf({name : \"test\"})", - 0, + 1 * kPointerSize, 2, - 5, + 9, { - B(LoadICSloppy), A(1, 2), U8(0), U8(vector->GetIndex(slot1)), // - B(Return), // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LoadICSloppy), R(0), U8(0), U8(vector->GetIndex(slot1)), // + B(Return), // }, 1, {"name"}}, {"function f(a) { return a[\"key\"]; }\nf({key : \"test\"})", - 0, + 1 * kPointerSize, 2, - 5, + 9, { - B(LoadICSloppy), A(1, 2), U8(0), U8(vector->GetIndex(slot1)), // - B(Return) // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LoadICSloppy), R(0), U8(0), U8(vector->GetIndex(slot1)), // + B(Return) // }, 1, {"key"}}, {"function f(a) { return a[100]; }\nf({100 : \"test\"})", - 0, + 1 * kPointerSize, 2, - 6, + 10, { - B(LdaSmi8), U8(100), // - B(KeyedLoadICSloppy), A(1, 2), U8(vector->GetIndex(slot1)), // - B(Return) // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LdaSmi8), U8(100), // + B(KeyedLoadICSloppy), R(0), U8(vector->GetIndex(slot1)), // + B(Return) // }, 0}, {"function f(a, b) { return a[b]; }\nf({arg : \"test\"}, \"arg\")", - 0, + 1 * kPointerSize, 3, - 6, + 10, { - B(Ldar), A(1, 2), // - B(KeyedLoadICSloppy), A(1, 3), U8(vector->GetIndex(slot1)), // - B(Return) // + B(Ldar), A(1, 3), // + B(Star), R(0), // + B(Ldar), A(1, 2), // + B(KeyedLoadICSloppy), R(0), U8(vector->GetIndex(slot1)), // + B(Return) // }, 0}, {"function f(a) { var b = a.name; return a[-124]; }\n" "f({\"-124\" : \"test\", name : 123 })", - kPointerSize, + 2 * kPointerSize, 2, - 12, + 20, { - B(LoadICSloppy), A(1, 2), U8(0), U8(vector->GetIndex(slot1)), // - B(Star), R(0), // - B(LdaSmi8), U8(-124), // - B(KeyedLoadICSloppy), A(1, 2), U8(vector->GetIndex(slot2)), // - B(Return), // + B(Ldar), A(1, 2), // + B(Star), R(1), // + B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot1)), // + B(Star), R(0), // + B(Ldar), A(1, 2), // + B(Star), R(1), // + B(LdaSmi8), U8(-124), // + B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot2)), // + B(Return), // }, 1, {"name"}}, {"function f(a) { \"use strict\"; return a.name; }\nf({name : \"test\"})", - 0, + 1 * kPointerSize, 2, - 5, + 9, { - B(LoadICStrict), A(1, 2), U8(0), U8(vector->GetIndex(slot1)), // - B(Return), // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LoadICStrict), R(0), U8(0), U8(vector->GetIndex(slot1)), // + B(Return), // }, 1, {"name"}}, - { - "function f(a, b) { \"use strict\"; return a[b]; }\n" - "f({arg : \"test\"}, \"arg\")", - 0, - 3, - 6, - { - B(Ldar), A(2, 3), // - B(KeyedLoadICStrict), A(1, 3), U8(vector->GetIndex(slot1)), // - B(Return), // - }, - 0}, - { - "function f(a) {\n" - " var b;\n" - REPEAT_127(SPACE, " b = a.name; ") - " return a.name; }\n" - "f({name : \"test\"})\n", - 1 * kPointerSize, - 2, - 769, - { - REPEAT_127(COMMA, // - B(LoadICSloppy), A(1, 2), U8(0), U8((wide_idx_1 += 2)), // - B(Star), R(0)), // - B(LoadICSloppyWide), A(1, 2), U16(0), U16(wide_idx_1 + 2), // - B(Return), // - }, - 1, - {"name"}}, - { - "function f(a) {\n" - " 'use strict'; var b;\n" - REPEAT_127(SPACE, " b = a.name; ") - " return a.name; }\n" - "f({name : \"test\"})\n", - 1 * kPointerSize, - 2, - 769, - { - REPEAT_127(COMMA, // - B(LoadICStrict), A(1, 2), U8(0), U8((wide_idx_2 += 2)), // - B(Star), R(0)), // - B(LoadICStrictWide), A(1, 2), U16(0), U16(wide_idx_2 + 2), // - B(Return), // - }, - 1, - {"name"}}, - { - "function f(a, b) {\n" - " var c;\n" - REPEAT_127(SPACE, " c = a[b]; ") - " return a[b]; }\n" - "f({name : \"test\"}, \"name\")\n", - 1 * kPointerSize, - 3, - 896, - { - REPEAT_127(COMMA, // - B(Ldar), A(2, 3), // - B(KeyedLoadICSloppy), A(1, 3), U8((wide_idx_3 += 2)), // - B(Star), R(0)), // - B(Ldar), A(2, 3), // - B(KeyedLoadICSloppyWide), A(1, 3), U16(wide_idx_3 + 2), // - B(Return), // - }}, - { - "function f(a, b) {\n" - " 'use strict'; var c;\n" - REPEAT_127(SPACE, " c = a[b]; ") - " return a[b]; }\n" - "f({name : \"test\"}, \"name\")\n", - 1 * kPointerSize, - 3, - 896, - { - REPEAT_127(COMMA, // - B(Ldar), A(2, 3), // - B(KeyedLoadICStrict), A(1, 3), U8((wide_idx_4 += 2)), // - B(Star), R(0)), // - B(Ldar), A(2, 3), // - B(KeyedLoadICStrictWide), A(1, 3), U16(wide_idx_4 + 2), // - B(Return), // - }}, - }; + {"function f(a, b) { \"use strict\"; return a[b]; }\n" + "f({arg : \"test\"}, \"arg\")", + 1 * kPointerSize, + 3, + 10, + { + B(Ldar), A(1, 3), // + B(Star), R(0), // + B(Ldar), A(2, 3), // + B(KeyedLoadICStrict), R(0), U8(vector->GetIndex(slot1)), // + B(Return), // + }, + 0}, + {"function f(a) {\n" + " var b;\n" + "b = a.name;" + REPEAT_127(SPACE, " b = a.name; ") + " return a.name; }\n" + "f({name : \"test\"})\n", + 2 * kPointerSize, + 2, + 1291, + { + B(Ldar), A(1, 2), // + B(Star), R(1), // + B(LoadICSloppy), R(1), U8(0), U8(wide_idx_1 += 2), // + B(Star), R(0), // + REPEAT_127(COMMA, // + B(Ldar), A(1, 2), // + B(Star), R(1), // + B(LoadICSloppy), R(1), U8(0), // + U8((wide_idx_1 += 2)), // + B(Star), R(0)), // + B(Ldar), A(1, 2), // + B(Star), R(1), // + B(LoadICSloppyWide), R(1), U16(0), U16(wide_idx_1 + 2), // + B(Return), // + }, + 1, + {"name"}}, + {"function f(a) {\n" + " 'use strict'; var b;\n" + " b = a.name;\n" + REPEAT_127(SPACE, " b = a.name; ") + " return a.name; }\n" + "f({name : \"test\"})\n", + 2 * kPointerSize, + 2, + 1291, + { + B(Ldar), A(1, 2), // + B(Star), R(1), // + B(LoadICStrict), R(1), U8(0), U8((wide_idx_2 += 2)), // + B(Star), R(0), // + REPEAT_127(COMMA, // + B(Ldar), A(1, 2), // + B(Star), R(1), // + B(LoadICStrict), R(1), U8(0), // + U8((wide_idx_2 += 2)), // + B(Star), R(0)), // + B(Ldar), A(1, 2), // + B(Star), R(1), // + B(LoadICStrictWide), R(1), U16(0), U16(wide_idx_2 + 2), // + B(Return), // + }, + 1, + {"name"}}, + {"function f(a, b) {\n" + " var c;\n" + " c = a[b];" + REPEAT_127(SPACE, " c = a[b]; ") + " return a[b]; }\n" + "f({name : \"test\"}, \"name\")\n", + 2 * kPointerSize, + 3, + 1419, + { + B(Ldar), A(1, 3), // + B(Star), R(1), // + B(Ldar), A(2, 3), // + B(KeyedLoadICSloppy), R(1), U8((wide_idx_3 += 2)), // + B(Star), R(0), // + REPEAT_127(COMMA, // + B(Ldar), A(1, 3), // + B(Star), R(1), // + B(Ldar), A(2, 3), // + B(KeyedLoadICSloppy), R(1), U8((wide_idx_3 += 2)), // + B(Star), R(0)), // + B(Ldar), A(1, 3), // + B(Star), R(1), // + B(Ldar), A(2, 3), // + B(KeyedLoadICSloppyWide), R(1), U16(wide_idx_3 + 2), // + B(Return), // + }}, + {"function f(a, b) {\n" + " 'use strict'; var c;\n" + " c = a[b];" + REPEAT_127(SPACE, " c = a[b]; ") + " return a[b]; }\n" + "f({name : \"test\"}, \"name\")\n", + 2 * kPointerSize, + 3, + 1419, + { + B(Ldar), A(1, 3), // + B(Star), R(1), // + B(Ldar), A(2, 3), // + B(KeyedLoadICStrict), R(1), U8((wide_idx_4 += 2)), // + B(Star), R(0), // + REPEAT_127(COMMA, // + B(Ldar), A(1, 3), // + B(Star), R(1), // + B(Ldar), A(2, 3), // + B(KeyedLoadICStrict), R(1), U8((wide_idx_4 += 2)), // + B(Star), R(0)), // + B(Ldar), A(1, 3), // + B(Star), R(1), // + B(Ldar), A(2, 3), // + B(KeyedLoadICStrictWide), R(1), U16(wide_idx_4 + 2), // + B(Return), // + }}, + }; for (size_t i = 0; i < arraysize(snippets); i++) { Handle<BytecodeArray> bytecode_array = helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName); @@ -1032,171 +1121,238 @@ TEST(PropertyStores) { ExpectedSnippet<const char*> snippets[] = { {"function f(a) { a.name = \"val\"; }\nf({name : \"test\"})", - 0, + kPointerSize, 2, - 8, + 12, { - B(LdaConstant), U8(1), // - B(StoreICSloppy), A(1, 2), U8(0), U8(vector->GetIndex(slot1)), // - B(LdaUndefined), // - B(Return), // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LdaConstant), U8(0), // + B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), // + B(LdaUndefined), // + B(Return), // }, 2, - {"name", "val"}}, + {"val", "name"}}, {"function f(a) { a[\"key\"] = \"val\"; }\nf({key : \"test\"})", - 0, + kPointerSize, 2, - 8, + 12, { - B(LdaConstant), U8(1), // - B(StoreICSloppy), A(1, 2), U8(0), U8(vector->GetIndex(slot1)), // - B(LdaUndefined), // - B(Return), // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LdaConstant), U8(0), // + B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), // + B(LdaUndefined), // + B(Return), // }, 2, - {"key", "val"}}, + {"val", "key"}}, {"function f(a) { a[100] = \"val\"; }\nf({100 : \"test\"})", - kPointerSize, + 2 * kPointerSize, 2, - 12, + 16, { - B(LdaSmi8), U8(100), // - B(Star), R(0), // - B(LdaConstant), U8(0), // - B(KeyedStoreICSloppy), A(1, 2), R(0), // - U8(vector->GetIndex(slot1)), // - B(LdaUndefined), // - B(Return), // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LdaSmi8), U8(100), // + B(Star), R(1), // + B(LdaConstant), U8(0), // + B(KeyedStoreICSloppy), R(0), R(1), // + U8(vector->GetIndex(slot1)), // + B(LdaUndefined), // + B(Return), // }, 1, {"val"}}, {"function f(a, b) { a[b] = \"val\"; }\nf({arg : \"test\"}, \"arg\")", - 0, + 2 * kPointerSize, 3, - 8, + 16, { - B(LdaConstant), U8(0), // - B(KeyedStoreICSloppy), A(1, 3), A(2, 3), // - U8(vector->GetIndex(slot1)), // - B(LdaUndefined), // - B(Return), // + B(Ldar), A(1, 3), // + B(Star), R(0), // + B(Ldar), A(2, 3), // + B(Star), R(1), // + B(LdaConstant), U8(0), // + B(KeyedStoreICSloppy), R(0), R(1), // + U8(vector->GetIndex(slot1)), // + B(LdaUndefined), // + B(Return), // }, 1, {"val"}}, {"function f(a) { a.name = a[-124]; }\n" "f({\"-124\" : \"test\", name : 123 })", - 0, + 2 * kPointerSize, 2, - 11, + 19, { - B(LdaSmi8), U8(-124), // - B(KeyedLoadICSloppy), A(1, 2), U8(vector->GetIndex(slot1)), // - B(StoreICSloppy), A(1, 2), U8(0), U8(vector->GetIndex(slot2)), // - B(LdaUndefined), // - B(Return), // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(Ldar), A(1, 2), // + B(Star), R(1), // + B(LdaSmi8), U8(-124), // + B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot1)), // + B(StoreICSloppy), R(0), U8(0), U8(vector->GetIndex(slot2)), // + B(LdaUndefined), // + B(Return), // }, 1, {"name"}}, {"function f(a) { \"use strict\"; a.name = \"val\"; }\n" "f({name : \"test\"})", - 0, + kPointerSize, 2, - 8, + 12, { - B(LdaConstant), U8(1), // - B(StoreICStrict), A(1, 2), U8(0), U8(vector->GetIndex(slot1)), // - B(LdaUndefined), // - B(Return), // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LdaConstant), U8(0), // + B(StoreICStrict), R(0), U8(1), U8(vector->GetIndex(slot1)), // + B(LdaUndefined), // + B(Return), // }, 2, - {"name", "val"}}, + {"val", "name"}}, {"function f(a, b) { \"use strict\"; a[b] = \"val\"; }\n" "f({arg : \"test\"}, \"arg\")", - 0, + 2 * kPointerSize, 3, - 8, + 16, { - B(LdaConstant), U8(0), // - B(KeyedStoreICStrict), A(1, 3), A(2, 3), // - U8(vector->GetIndex(slot1)), // - B(LdaUndefined), // - B(Return), // + B(Ldar), A(1, 3), // + B(Star), R(0), // + B(Ldar), A(2, 3), // + B(Star), R(1), // + B(LdaConstant), U8(0), // + B(KeyedStoreICStrict), R(0), R(1), U8(vector->GetIndex(slot1)), // + B(LdaUndefined), // + B(Return), // }, 1, {"val"}}, {"function f(a) {\n" + "a.name = 1;" REPEAT_127(SPACE, " a.name = 1; ") " a.name = 2; }\n" "f({name : \"test\"})\n", - 0, + kPointerSize, 2, - 772, + 1294, { - REPEAT_127(COMMA, // - B(LdaSmi8), U8(1), // - B(StoreICSloppy), A(1, 2), U8(0), U8((wide_idx_1 += 2))), // - B(LdaSmi8), U8(2), // - B(StoreICSloppyWide), A(1, 2), U16(0), U16(wide_idx_1 + 2), // - B(LdaUndefined), // - B(Return), // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LdaSmi8), U8(1), // + B(StoreICSloppy), R(0), U8(0), U8((wide_idx_1 += 2)), // + REPEAT_127(COMMA, // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LdaSmi8), U8(1), // + B(StoreICSloppy), R(0), U8(0), // + U8((wide_idx_1 += 2))), // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LdaSmi8), U8(2), // + B(StoreICSloppyWide), R(0), U16(0), U16(wide_idx_1 + 2), // + B(LdaUndefined), // + B(Return), // }, 1, {"name"}}, {"function f(a) {\n" - "'use strict';\n" + " 'use strict';\n" + " a.name = 1;" REPEAT_127(SPACE, " a.name = 1; ") " a.name = 2; }\n" "f({name : \"test\"})\n", - 0, + kPointerSize, 2, - 772, + 1294, { - REPEAT_127(COMMA, // - B(LdaSmi8), U8(1), // - B(StoreICStrict), A(1, 2), U8(0), U8((wide_idx_2 += 2))), // - B(LdaSmi8), U8(2), // - B(StoreICStrictWide), A(1, 2), U16(0), U16(wide_idx_2 + 2), // - B(LdaUndefined), // - B(Return), // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LdaSmi8), U8(1), // + B(StoreICStrict), R(0), U8(0), U8(wide_idx_2 += 2), // + REPEAT_127(COMMA, // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LdaSmi8), U8(1), // + B(StoreICStrict), R(0), U8(0), // + U8((wide_idx_2 += 2))), // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LdaSmi8), U8(2), // + B(StoreICStrictWide), R(0), U16(0), U16(wide_idx_2 + 2), // + B(LdaUndefined), // + B(Return), // }, 1, {"name"}}, {"function f(a, b) {\n" - REPEAT_127(SPACE, " a[b] = 1; ") + " a[b] = 1;" + REPEAT_127(SPACE, " a[b] = 1; ") " a[b] = 2; }\n" "f({name : \"test\"})\n", - 0, + 2 * kPointerSize, 3, - 771, - { - REPEAT_127(COMMA, // - B(LdaSmi8), U8(1), // - B(KeyedStoreICSloppy), A(1, 3), A(2, 3), // - U8((wide_idx_3 += 2))), // - B(LdaSmi8), U8(2), // - B(KeyedStoreICSloppyWide), A(1, 3), A(2, 3), // - U16(wide_idx_3 + 2), // - B(LdaUndefined), // - B(Return), // + 1809, + { + B(Ldar), A(1, 3), // + B(Star), R(0), // + B(Ldar), A(2, 3), // + B(Star), R(1), // + B(LdaSmi8), U8(1), // + B(KeyedStoreICSloppy), R(0), R(1), U8(wide_idx_3 += 2), // + REPEAT_127(COMMA, // + B(Ldar), A(1, 3), // + B(Star), R(0), // + B(Ldar), A(2, 3), // + B(Star), R(1), // + B(LdaSmi8), U8(1), // + B(KeyedStoreICSloppy), R(0), R(1), // + U8((wide_idx_3 += 2))), // + B(Ldar), A(1, 3), // + B(Star), R(0), // + B(Ldar), A(2, 3), // + B(Star), R(1), // + B(LdaSmi8), U8(2), // + B(KeyedStoreICSloppyWide), R(0), R(1), U16(wide_idx_3 + 2), // + B(LdaUndefined), // + B(Return), // }}, {"function f(a, b) {\n" - "'use strict';\n" - REPEAT_127(SPACE, " a[b] = 1; ") + " 'use strict';\n" + " a[b] = 1;" + REPEAT_127(SPACE, " a[b] = 1; ") " a[b] = 2; }\n" "f({name : \"test\"})\n", - 0, + 2 * kPointerSize, 3, - 771, - { - REPEAT_127(COMMA, // - B(LdaSmi8), U8(1), // - B(KeyedStoreICStrict), A(1, 3), A(2, 3), // - U8((wide_idx_4 += 2))), // - B(LdaSmi8), U8(2), // - B(KeyedStoreICStrictWide), A(1, 3), A(2, 3), // - U16(wide_idx_4 + 2), // - B(LdaUndefined), // - B(Return), // + 1809, + { + B(Ldar), A(1, 3), // + B(Star), R(0), // + B(Ldar), A(2, 3), // + B(Star), R(1), // + B(LdaSmi8), U8(1), // + B(KeyedStoreICStrict), R(0), R(1), U8(wide_idx_4 += 2), // + REPEAT_127(COMMA, // + B(Ldar), A(1, 3), // + B(Star), R(0), // + B(Ldar), A(2, 3), // + B(Star), R(1), // + B(LdaSmi8), U8(1), // + B(KeyedStoreICStrict), R(0), R(1), // + U8((wide_idx_4 += 2))), // + B(Ldar), A(1, 3), // + B(Star), R(0), // + B(Ldar), A(2, 3), // + B(Star), R(1), // + B(LdaSmi8), U8(2), // + B(KeyedStoreICStrictWide), R(0), R(1), U16(wide_idx_4 + 2), // + B(LdaUndefined), // + B(Return), // }}}; for (size_t i = 0; i < arraysize(snippets); i++) { Handle<BytecodeArray> bytecode_array = @@ -1215,24 +1371,26 @@ TEST(PropertyCall) { Zone zone; FeedbackVectorSpec feedback_spec(&zone); - FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot(); + FeedbackVectorSlot slot1 = feedback_spec.AddCallICSlot(); FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot(); - USE(slot1); Handle<i::TypeFeedbackVector> vector = i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); + // These are a hack used by the CallWide test below. + int wide_idx = vector->GetIndex(slot1) - 2; + ExpectedSnippet<const char*> snippets[] = { {"function f(a) { return a.func(); }\nf(" FUNC_ARG ")", 2 * kPointerSize, 2, - 15, + 16, { B(Ldar), A(1, 2), // B(Star), R(1), // B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)), // B(Star), R(0), // - B(Call), R(0), R(1), U8(0), // + B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot1)), // B(Return), // }, 1, @@ -1240,7 +1398,7 @@ TEST(PropertyCall) { {"function f(a, b, c) { return a.func(b, c); }\nf(" FUNC_ARG ", 1, 2)", 4 * kPointerSize, 4, - 23, + 24, { B(Ldar), A(1, 4), // B(Star), R(1), // @@ -1250,7 +1408,7 @@ TEST(PropertyCall) { B(Star), R(2), // B(Ldar), A(3, 4), // B(Star), R(3), // - B(Call), R(0), R(1), U8(2), // + B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot1)), // B(Return) // }, 1, @@ -1258,22 +1416,49 @@ TEST(PropertyCall) { {"function f(a, b) { return a.func(b + b, b); }\nf(" FUNC_ARG ", 1)", 4 * kPointerSize, 3, - 25, + 30, { B(Ldar), A(1, 3), // B(Star), R(1), // B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)), // B(Star), R(0), // B(Ldar), A(2, 3), // - B(Add), A(2, 3), // + B(Star), R(3), // + B(Ldar), A(2, 3), // + B(Add), R(3), // B(Star), R(2), // B(Ldar), A(2, 3), // B(Star), R(3), // - B(Call), R(0), R(1), U8(2), // + B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot1)), // B(Return), // }, 1, - {"func"}}}; + {"func"}}, + {"function f(a) {\n" + " a.func;\n" + REPEAT_127(SPACE, " a.func;\n") + " return a.func(); }\nf(" FUNC_ARG ")", + 2 * kPointerSize, + 2, + 1044, + { + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LoadICSloppy), R(0), U8(0), U8(wide_idx += 2), // + REPEAT_127(COMMA, // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LoadICSloppy), R(0), U8(0), U8((wide_idx += 2))), // + B(Ldar), A(1, 2), // + B(Star), R(1), // + B(LoadICSloppyWide), R(1), U16(0), U16(wide_idx + 4), // + B(Star), R(0), // + B(CallWide), R(0), R(1), U16(0), U16(wide_idx + 2), // + B(Return), // + }, + 1, + {"func"}}, + }; for (size_t i = 0; i < arraysize(snippets); i++) { Handle<BytecodeArray> bytecode_array = helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName); @@ -1338,32 +1523,48 @@ TEST(LoadGlobal) { }, 1, {"a"}}, - {"a = 1; function f(b) {\n" - REPEAT_127(SPACE, "b.name; ") - " return a; }\nf({name: 1});", - 0, + {"a = 1;" + "function f(b) {\n" + " b.name;\n" + REPEAT_127(SPACE, "b.name; ") + " return a;" + "}\nf({name: 1});", + kPointerSize, 2, - 514, + 1030, { - REPEAT_127(COMMA, // - B(LoadICSloppy), A(1, 2), U8(0), U8(wide_idx_1 += 2)), // - B(LdaGlobalSloppyWide), U16(1), U16(wide_idx_1 + 2), // - B(Return), // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2), // + REPEAT_127(COMMA, // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2)), // + B(LdaGlobalSloppyWide), U16(1), U16(wide_idx_1 + 2), // + B(Return), // }, 2, {"name", "a"}}, - {"a = 1; function f(b) {\n" + {"a = 1;" + "function f(b) {\n" " 'use strict';\n" - REPEAT_127(SPACE, "b.name; ") - " return a; }\nf({name: 1});", - 0, + " b.name\n" + REPEAT_127(SPACE, "b.name; ") + " return a;" + "}\nf({name: 1});", + kPointerSize, 2, - 514, + 1030, { - REPEAT_127(COMMA, // - B(LoadICStrict), A(1, 2), U8(0), U8(wide_idx_2 += 2)), // - B(LdaGlobalStrictWide), U16(1), U16(wide_idx_2 + 2), // - B(Return), // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2), // + REPEAT_127(COMMA, // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2)), // + B(LdaGlobalStrictWide), U16(1), U16(wide_idx_2 + 2), // + B(Return), // }, 2, {"name", "a"}}, @@ -1441,36 +1642,52 @@ TEST(StoreGlobal) { }, 1, {"a"}}, - {"a = 1; function f(b) {\n" + {"a = 1;" + "function f(b) {" + " b.name;\n" REPEAT_127(SPACE, "b.name; ") - " a = 2; }\nf({name: 1});", - 0, + " a = 2; }\n" + "f({name: 1});", + kPointerSize, 2, - 517, + 1033, { - REPEAT_127(COMMA, // - B(LoadICSloppy), A(1, 2), U8(0), U8(wide_idx_1 += 2)), // - B(LdaSmi8), U8(2), // - B(StaGlobalSloppyWide), U16(1), U16(wide_idx_1 + 2), // - B(LdaUndefined), // - B(Return), // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2), // + REPEAT_127(COMMA, // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2)), // + B(LdaSmi8), U8(2), // + B(StaGlobalSloppyWide), U16(1), U16(wide_idx_1 + 2), // + B(LdaUndefined), // + B(Return), // }, 2, {"name", "a"}}, - {"a = 1; function f(b) {\n" + {"a = 1;" + "function f(b) {\n" " 'use strict';\n" + " b.name;\n" REPEAT_127(SPACE, "b.name; ") - " a = 2; }\nf({name: 1});", - 0, + " a = 2; }\n" + "f({name: 1});", + kPointerSize, 2, - 517, + 1033, { - REPEAT_127(COMMA, // - B(LoadICStrict), A(1, 2), U8(0), U8(wide_idx_2 += 2)), // - B(LdaSmi8), U8(2), // - B(StaGlobalStrictWide), U16(1), U16(wide_idx_2 + 2), // - B(LdaUndefined), // - B(Return), // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2), // + REPEAT_127(COMMA, // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2)), // + B(LdaSmi8), U8(2), // + B(StaGlobalStrictWide), U16(1), U16(wide_idx_2 + 2), // + B(LdaUndefined), // + B(Return), // }, 2, {"name", "a"}}, @@ -1490,9 +1707,8 @@ TEST(CallGlobal) { Zone zone; FeedbackVectorSpec feedback_spec(&zone); - FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot(); + FeedbackVectorSlot slot1 = feedback_spec.AddCallICSlot(); FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot(); - USE(slot1); Handle<i::TypeFeedbackVector> vector = i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); @@ -1501,34 +1717,34 @@ TEST(CallGlobal) { {"function t() { }\nfunction f() { return t(); }\nf()", 2 * kPointerSize, 1, - 13, + 14, { - B(LdaUndefined), // - B(Star), R(1), // - B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), // - B(Star), R(0), // - B(Call), R(0), R(1), U8(0), // - B(Return) // + B(LdaUndefined), // + B(Star), R(1), // + B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), // + B(Star), R(0), // + B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot1)), // + B(Return) // }, 1, {"t"}}, {"function t(a, b, c) { }\nfunction f() { return t(1, 2, 3); }\nf()", 5 * kPointerSize, 1, - 25, + 26, { - B(LdaUndefined), // - B(Star), R(1), // - B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), // - B(Star), R(0), // - B(LdaSmi8), U8(1), // - B(Star), R(2), // - B(LdaSmi8), U8(2), // - B(Star), R(3), // - B(LdaSmi8), U8(3), // - B(Star), R(4), // - B(Call), R(0), R(1), U8(3), // - B(Return) // + B(LdaUndefined), // + B(Star), R(1), // + B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), // + B(Star), R(0), // + B(LdaSmi8), U8(1), // + B(Star), R(2), // + B(LdaSmi8), U8(2), // + B(Star), R(3), // + B(LdaSmi8), U8(3), // + B(Star), R(4), // + B(Call), R(0), R(1), U8(3), U8(vector->GetIndex(slot1)), // + B(Return) // }, 1, {"t"}}, @@ -1589,12 +1805,11 @@ TEST(CallRuntime) { "function f() { return %spread_iterable([1]) }\nf()", 2 * kPointerSize, 1, - 16, + 15, { B(LdaUndefined), // B(Star), R(0), // - B(LdaConstant), U8(0), // - B(CreateArrayLiteral), U8(0), U8(3), // + B(CreateArrayLiteral), U8(0), U8(0), U8(3), // B(Star), R(1), // B(CallJSRuntime), U16(Context::SPREAD_ITERABLE_INDEX), R(0), // U8(1), // @@ -1661,16 +1876,17 @@ TEST(IfConditions) { 0, {unused, unused, unused, unused, unused, unused}}, {"function f() { var a = 1; if (a) { a += 1; } else { return 2; } } f();", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 21, + 23, { B(LdaSmi8), U8(1), // B(Star), R(0), // + B(JumpIfToBooleanFalse), U8(14), // B(Ldar), R(0), // - B(JumpIfToBooleanFalse), U8(10), // + B(Star), R(1), // B(LdaSmi8), U8(1), // - B(Add), R(0), // + B(Add), R(1), // B(Star), R(0), // B(Jump), U8(5), // B(LdaSmi8), U8(2), // @@ -1682,19 +1898,21 @@ TEST(IfConditions) { {unused, unused, unused, unused, unused, unused}}, {"function f(a) { if (a <= 0) { return 200; } else { return -200; } }" "f(99);", - 0, + kPointerSize, 2, - 13, + 17, { - B(LdaZero), // - B(TestLessThanOrEqual), A(1, 2), // - B(JumpIfFalse), U8(5), // - B(LdaConstant), U8(0), // - B(Return), // - B(LdaConstant), U8(1), // - B(Return), // - B(LdaUndefined), // - B(Return), // + B(Ldar), A(1, 2), // + B(Star), R(0), // + B(LdaZero), // + B(TestLessThanOrEqual), R(0), // + B(JumpIfFalse), U8(5), // + B(LdaConstant), U8(0), // + B(Return), // + B(LdaConstant), U8(1), // + B(Return), // + B(LdaUndefined), // + B(Return), // }, 2, {helper.factory()->NewNumberFromInt(200), @@ -1702,12 +1920,14 @@ TEST(IfConditions) { unused}}, {"function f(a, b) { if (a in b) { return 200; } }" "f('prop', { prop: 'yes'});", - 0, + kPointerSize, 3, - 11, + 15, { + B(Ldar), A(1, 3), // + B(Star), R(0), // B(Ldar), A(2, 3), // - B(TestIn), A(1, 3), // + B(TestIn), R(0), // B(JumpIfFalse), U8(5), // B(LdaConstant), U8(0), // B(Return), // @@ -1718,23 +1938,24 @@ TEST(IfConditions) { {helper.factory()->NewNumberFromInt(200), unused, unused, unused, unused, unused}}, {"function f(z) { var a = 0; var b = 0; if (a === 0.01) { " - REPEAT_32(SPACE, "b = a; a = b; ") + REPEAT_64(SPACE, "b = a; a = b; ") " return 200; } else { return -200; } } f(0.001)", - 2 * kPointerSize, + 3 * kPointerSize, 2, - 276, + 282, { B(LdaZero), // B(Star), R(0), // B(LdaZero), // B(Star), R(1), // + B(Ldar), R(0), // + B(Star), R(2), // B(LdaConstant), U8(0), // - B(TestEqualStrict), R(0), // + B(TestEqualStrict), R(2), // B(JumpIfFalseConstant), U8(2), // - REPEAT_32(COMMA, // - B(Ldar), R(0), // + B(Ldar), R(0), // + REPEAT_64(COMMA, // B(Star), R(1), // - B(Ldar), R(1), // B(Star), R(0)), // B(LdaConstant), U8(1), // B(Return), // @@ -1745,14 +1966,14 @@ TEST(IfConditions) { 4, {helper.factory()->NewHeapNumber(0.01), helper.factory()->NewNumberFromInt(200), - helper.factory()->NewNumberFromInt(261), + helper.factory()->NewNumberFromInt(263), helper.factory()->NewNumberFromInt(-200), unused, unused}}, {"function f() { var a = 0; var b = 0; if (a) { " - REPEAT_32(SPACE, "b = a; a = b; ") + REPEAT_64(SPACE, "b = a; a = b; ") " return 200; } else { return -200; } } f()", 2 * kPointerSize, 1, - 274, + 276, { B(LdaZero), // B(Star), R(0), // @@ -1760,10 +1981,9 @@ TEST(IfConditions) { B(Star), R(1), // B(Ldar), R(0), // B(JumpIfToBooleanFalseConstant), U8(1), // - REPEAT_32(COMMA, // - B(Ldar), R(0), // + B(Ldar), R(0), // + REPEAT_64(COMMA, // B(Star), R(1), // - B(Ldar), R(1), // B(Star), R(0)), // B(LdaConstant), U8(0), // B(Return), // @@ -1773,7 +1993,7 @@ TEST(IfConditions) { B(Return)}, // 3, {helper.factory()->NewNumberFromInt(200), - helper.factory()->NewNumberFromInt(261), + helper.factory()->NewNumberFromInt(263), helper.factory()->NewNumberFromInt(-200), unused, unused, unused}}, {"function f(a, b) {\n" @@ -1787,13 +2007,15 @@ TEST(IfConditions) { " if (a instanceof b) { return 1; }\n" " return 0;\n" "} f(1, 1);", - 0, + kPointerSize, 3, - 74, + 106, { #define IF_CONDITION_RETURN(condition) \ + B(Ldar), A(1, 3), \ + B(Star), R(0), \ B(Ldar), A(2, 3), \ - B(condition), A(1, 3), \ + B(condition), R(0), \ B(JumpIfFalse), U8(5), \ B(LdaSmi8), U8(1), \ B(Return), @@ -1820,11 +2042,10 @@ TEST(IfConditions) { "f();", 1 * kPointerSize, 1, - 15, + 13, { B(LdaZero), // B(Star), R(0), // - B(Ldar), R(0), // B(JumpIfToBooleanFalse), U8(5), // B(LdaSmi8), U8(20), // B(Return), // @@ -1834,8 +2055,7 @@ TEST(IfConditions) { B(Return) }, 0, - {unused, unused, unused, unused, unused, unused}} - }; + {unused, unused, unused, unused, unused, unused}}}; for (size_t i = 0; i < arraysize(snippets); i++) { Handle<BytecodeArray> bytecode_array = @@ -1861,6 +2081,7 @@ TEST(DeclareGlobals) { FeedbackVectorSpec feedback_spec_loads(&zone); FeedbackVectorSlot load_slot_1 = feedback_spec_loads.AddLoadICSlot(); + FeedbackVectorSlot call_slot_1 = feedback_spec_loads.AddCallICSlot(); Handle<i::TypeFeedbackVector> load_vector = i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec_loads); @@ -1907,7 +2128,7 @@ TEST(DeclareGlobals) { {"var a = 1;\na=2;", 4 * kPointerSize, 1, - 38, + 36, { B(LdaConstant), U8(0), // B(Star), R(1), // @@ -1925,7 +2146,6 @@ TEST(DeclareGlobals) { B(StaGlobalSloppy), U8(1), // U8(store_vector->GetIndex(store_slot_2)), // B(Star), R(0), // - B(Ldar), R(0), // B(Return) // }, 2, @@ -1934,22 +2154,22 @@ TEST(DeclareGlobals) { {"function f() {}\nf();", 3 * kPointerSize, 1, - 29, + 28, { - B(LdaConstant), U8(0), // - B(Star), R(1), // - B(LdaZero), // - B(Star), R(2), // - B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), // - B(LdaUndefined), // - B(Star), R(2), // - B(LdaGlobalSloppy), U8(1), // - U8(load_vector->GetIndex(load_slot_1)), // - B(Star), R(1), // - B(Call), R(1), R(2), U8(0), // - B(Star), R(0), // - B(Ldar), R(0), // - B(Return) // + B(LdaConstant), U8(0), // + B(Star), R(1), // + B(LdaZero), // + B(Star), R(2), // + B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), // + B(LdaUndefined), // + B(Star), R(2), // + B(LdaGlobalSloppy), U8(1), // + U8(load_vector->GetIndex(load_slot_1)), // + B(Star), R(1), // + B(Call), R(1), R(2), U8(0), // + U8(load_vector->GetIndex(call_slot_1)), // + B(Star), R(0), // + B(Return) // }, 2, {InstanceType::FIXED_ARRAY_TYPE, @@ -1964,42 +2184,178 @@ TEST(DeclareGlobals) { } +TEST(BreakableBlocks) { + InitializedHandleScope handle_scope; + BytecodeGeneratorHelper helper; + + ExpectedSnippet<int> snippets[] = { + {"var x = 0;\n" + "label: {\n" + " x = x + 1;\n" + " break label;\n" + " x = x + 1;\n" + "}\n" + "return x;", + 2 * kPointerSize, + 1, + 16, + { + B(LdaZero), // + B(Star), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(1), // + B(Add), R(1), // + B(Star), R(0), // + B(Jump), U8(2), // + B(Ldar), R(0), // + B(Return) // + }}, + {"var sum = 0;\n" + "outer: {\n" + " for (var x = 0; x < 10; ++x) {\n" + " for (var y = 0; y < 3; ++y) {\n" + " ++sum;\n" + " if (x + y == 12) { break outer; }\n" + " }\n" + " }\n" + "}\n" + "return sum;", + 5 * kPointerSize, + 1, + 72, + { + B(LdaZero), // + B(Star), R(0), // + B(LdaZero), // + B(Star), R(1), // + B(Ldar), R(1), // + B(Star), R(3), // + B(LdaSmi8), U8(10), // + B(TestLessThan), R(3), // + B(JumpIfFalse), U8(55), // + B(LdaZero), // + B(Star), R(2), // + B(Ldar), R(2), // + B(Star), R(3), // + B(LdaSmi8), U8(3), // + B(TestLessThan), R(3), // + B(JumpIfFalse), U8(34), // + B(Ldar), R(0), // + B(ToNumber), // + B(Inc), // + B(Star), R(0), // + B(Ldar), R(1), // + B(Star), R(3), // + B(Ldar), R(2), // + B(Add), R(3), // + B(Star), R(4), // + B(LdaSmi8), U8(12), // + B(TestEqual), R(4), // + B(JumpIfFalse), U8(4), // + B(Jump), U8(18), // + B(Ldar), R(2), // + B(ToNumber), // + B(Inc), // + B(Star), R(2), // + B(Jump), U8(-40), // + B(Ldar), R(1), // + B(ToNumber), // + B(Inc), // + B(Star), R(1), // + B(Jump), U8(-61), // + B(Ldar), R(0), // + B(Return), // + }}, + }; + + for (size_t i = 0; i < arraysize(snippets); i++) { + Handle<BytecodeArray> bytecode_array = + helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); + CheckBytecodeArrayEqual(snippets[i], bytecode_array); + } +} + + TEST(BasicLoops) { InitializedHandleScope handle_scope; BytecodeGeneratorHelper helper; ExpectedSnippet<int> snippets[] = { + {"var x = 0;\n" + "while (false) { x = 99; break; continue; }\n" + "return x;", + 1 * kPointerSize, + 1, + 4, + { + B(LdaZero), // + B(Star), R(0), // + B(Return) // + }}, + {"var x = 0;" + "while (false) {" + " x = x + 1;" + "};" + "return x;", + 1 * kPointerSize, + 1, + 4, + { + B(LdaZero), // + B(Star), R(0), // + B(Return), // + }, + 0}, {"var x = 0;" "var y = 1;" "while (x < 10) {" " y = y * 12;" " x = x + 1;" + " if (x == 3) continue;" + " if (x == 4) break;" "}" "return y;", - 2 * kPointerSize, + 3 * kPointerSize, 1, - 30, + 64, { B(LdaZero), // B(Star), R(0), // B(LdaSmi8), U8(1), // B(Star), R(1), // - B(Jump), U8(14), // + B(Ldar), R(0), // + B(Star), R(2), // + B(LdaSmi8), U8(10), // + B(TestLessThan), R(2), // + B(JumpIfFalse), U8(46), // + B(Ldar), R(1), // + B(Star), R(2), // B(LdaSmi8), U8(12), // - B(Mul), R(1), // + B(Mul), R(2), // B(Star), R(1), // + B(Ldar), R(0), // + B(Star), R(2), // B(LdaSmi8), U8(1), // - B(Add), R(0), // + B(Add), R(2), // B(Star), R(0), // - B(LdaSmi8), U8(10), // - B(TestLessThan), R(0), // - B(JumpIfTrue), U8(-16), // + B(Star), R(2), // + B(LdaSmi8), U8(3), // + B(TestEqual), R(2), // + B(JumpIfFalse), U8(4), // + B(Jump), U8(-38), // + B(Ldar), R(0), // + B(Star), R(2), // + B(LdaSmi8), U8(4), // + B(TestEqual), R(2), // + B(JumpIfFalse), U8(4), // + B(Jump), U8(4), // + B(Jump), U8(-52), // B(Ldar), R(1), // B(Return), // }, 0}, {"var i = 0;" - "while(true) {" + "while (true) {" " if (i < 0) continue;" " if (i == 3) break;" " if (i == 4) break;" @@ -2008,130 +2364,54 @@ TEST(BasicLoops) { " i = i + 1;" "}" "return i;", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 53, + 77, { B(LdaZero), // B(Star), R(0), // + B(Ldar), R(0), // + B(Star), R(1), // B(LdaZero), // - B(TestLessThan), R(0), // + B(TestLessThan), R(1), // B(JumpIfFalse), U8(4), // - B(Jump), U8(40), // + B(Jump), U8(-9), // + B(Ldar), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(3), // - B(TestEqual), R(0), // + B(TestEqual), R(1), // B(JumpIfFalse), U8(4), // - B(Jump), U8(34), // + B(Jump), U8(50), // + B(Ldar), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(4), // - B(TestEqual), R(0), // + B(TestEqual), R(1), // B(JumpIfFalse), U8(4), // - B(Jump), U8(26), // + B(Jump), U8(38), // + B(Ldar), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(10), // - B(TestEqual), R(0), // - B(JumpIfFalse), U8(4), // - B(Jump), U8(16), // - B(LdaSmi8), U8(5), // - B(TestEqual), R(0), // + B(TestEqual), R(1), // B(JumpIfFalse), U8(4), // - B(Jump), U8(10), // - B(LdaSmi8), U8(1), // - B(Add), R(0), // - B(Star), R(0), // B(Jump), U8(-45), // B(Ldar), R(0), // - B(Return), // - }, - 0}, - {"var x = 0; var y = 1;" - "do {" - " y = y * 10;" - " if (x == 5) break;" - " if (x == 6) continue;" - " x = x + 1;" - "} while (x < 10);" - "return y;", - 2 * kPointerSize, - 1, - 44, - { - B(LdaZero), // - B(Star), R(0), // - B(LdaSmi8), U8(1), // - B(Star), R(1), // - B(LdaSmi8), U8(10), // - B(Mul), R(1), // - B(Star), R(1), // - B(LdaSmi8), U8(5), // - B(TestEqual), R(0), // - B(JumpIfFalse), U8(4), // - B(Jump), U8(22), // - B(LdaSmi8), U8(6), // - B(TestEqual), R(0), // - B(JumpIfFalse), U8(4), // - B(Jump), U8(8), // - B(LdaSmi8), U8(1), // - B(Add), R(0), // - B(Star), R(0), // - B(LdaSmi8), U8(10), // - B(TestLessThan), R(0), // - B(JumpIfTrue), U8(-32), // - B(Ldar), R(1), // - B(Return), // - }, - 0}, - {"var x = 0; " - "for(;;) {" - " if (x == 1) break;" - " x = x + 1;" - "}", - 1 * kPointerSize, - 1, - 21, - { - B(LdaZero), // - B(Star), R(0), // - B(LdaSmi8), U8(1), // - B(TestEqual), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(5), // + B(TestEqual), R(1), // B(JumpIfFalse), U8(4), // - B(Jump), U8(10), // + B(Jump), U8(14), // + B(Ldar), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(1), // - B(Add), R(0), // + B(Add), R(1), // B(Star), R(0), // - B(Jump), U8(-14), // - B(LdaUndefined), // + B(Jump), U8(-69), // + B(Ldar), R(0), // B(Return), // }, 0}, - {"var u = 0;" - "for(var i = 0; i < 100; i = i + 1) {" - " u = u + 1;" - " continue;" - "}", - 2 * kPointerSize, - 1, - 30, - { - B(LdaZero), // - B(Star), R(0), // - B(LdaZero), // - B(Star), R(1), // - B(Jump), U8(16), // - B(LdaSmi8), U8(1), // - B(Add), R(0), // - B(Star), R(0), // - B(Jump), U8(2), // - B(LdaSmi8), U8(1), // - B(Add), R(1), // - B(Star), R(1), // - B(LdaSmi8), U8(100), // - B(TestLessThan), R(1), // - B(JumpIfTrue), U8(-18), // - B(LdaUndefined), // - B(Return), // - }, - 0}, {"var i = 0;" - "while(true) {" + "while (true) {" " while (i < 3) {" " if (i == 2) break;" " i = i + 1;" @@ -2140,28 +2420,36 @@ TEST(BasicLoops) { " break;" "}" "return i;", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 38, + 54, { B(LdaZero), // B(Star), R(0), // - B(Jump), U8(16), // + B(Ldar), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(3), // + B(TestLessThan), R(1), // + B(JumpIfFalse), U8(26), // + B(Ldar), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(2), // - B(TestEqual), R(0), // + B(TestEqual), R(1), // B(JumpIfFalse), U8(4), // B(Jump), U8(14), // + B(Ldar), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(1), // - B(Add), R(0), // + B(Add), R(1), // B(Star), R(0), // - B(LdaSmi8), U8(3), // - B(TestLessThan), R(0), // - B(JumpIfTrue), U8(-18), // + B(Jump), U8(-32), // + B(Ldar), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(1), // - B(Add), R(0), // + B(Add), R(1), // B(Star), R(0), // B(Jump), U8(4), // - B(Jump), U8(-30), // + B(Jump), U8(-46), // B(Ldar), R(0), // B(Return), // }, @@ -2173,78 +2461,106 @@ TEST(BasicLoops) { " x = x - 1;" "}" "return y;", - 2 * kPointerSize, + 3 * kPointerSize, 1, - 29, + 37, { B(LdaSmi8), U8(10), // B(Star), R(0), // B(LdaSmi8), U8(1), // B(Star), R(1), // - B(Jump), U8(14), // - B(LdaSmi8), U8(12), // - B(Mul), R(1), // - B(Star), R(1), // - B(LdaSmi8), U8(1), // - B(Sub), R(0), // - B(Star), R(0), // B(Ldar), R(0), // - B(JumpIfToBooleanTrue), U8(-14), // + B(JumpIfToBooleanFalse), U8(24), // B(Ldar), R(1), // - B(Return), // - }, - 0}, - {"var x = 10;" - "var y = 1;" - "do {" - " y = y * 12;" - " x = x - 1;" - "} while(x);" - "return y;", - 2 * kPointerSize, - 1, - 27, - { - B(LdaSmi8), U8(10), // - B(Star), R(0), // - B(LdaSmi8), U8(1), // - B(Star), R(1), // + B(Star), R(2), // B(LdaSmi8), U8(12), // - B(Mul), R(1), // + B(Mul), R(2), // B(Star), R(1), // + B(Ldar), R(0), // + B(Star), R(2), // B(LdaSmi8), U8(1), // - B(Sub), R(0), // + B(Sub), R(2), // B(Star), R(0), // - B(Ldar), R(0), // - B(JumpIfToBooleanTrue), U8(-14), // + B(Jump), U8(-24), // B(Ldar), R(1), // B(Return), // - }, + }, 0}, - {"var y = 1;" - "for (var x = 10; x; --x) {" + {"var x = 0; var y = 1;" + "do {" + " y = y * 10;" + " if (x == 5) break;" + " if (x == 6) continue;" + " x = x + 1;" + "} while (x < 10);" + "return y;", + 3 * kPointerSize, + 1, + 64, + { + B(LdaZero), // + B(Star), R(0), // + B(LdaSmi8), U8(1), // + B(Star), R(1), // + B(Ldar), R(1), // + B(Star), R(2), // + B(LdaSmi8), U8(10), // + B(Mul), R(2), // + B(Star), R(1), // + B(Ldar), R(0), // + B(Star), R(2), // + B(LdaSmi8), U8(5), // + B(TestEqual), R(2), // + B(JumpIfFalse), U8(4), // + B(Jump), U8(34), // + B(Ldar), R(0), // + B(Star), R(2), // + B(LdaSmi8), U8(6), // + B(TestEqual), R(2), // + B(JumpIfFalse), U8(4), // + B(Jump), U8(12), // + B(Ldar), R(0), // + B(Star), R(2), // + B(LdaSmi8), U8(1), // + B(Add), R(2), // + B(Star), R(0), // + B(Ldar), R(0), // + B(Star), R(2), // + B(LdaSmi8), U8(10), // + B(TestLessThan), R(2), // + B(JumpIfTrue), U8(-52), // + B(Ldar), R(1), // + B(Return), // + }, + 0}, + {"var x = 10;" + "var y = 1;" + "do {" " y = y * 12;" - "}" + " x = x - 1;" + "} while (x);" "return y;", - 2 * kPointerSize, + 3 * kPointerSize, 1, - 29, + 35, { - B(LdaSmi8), U8(1), // - B(Star), R(0), // B(LdaSmi8), U8(10), // - B(Star), R(1), // - B(Jump), U8(14), // - B(LdaSmi8), U8(12), // - B(Mul), R(0), // B(Star), R(0), // - B(Ldar), R(1), // - B(ToNumber), // - B(Dec), // + B(LdaSmi8), U8(1), // B(Star), R(1), // B(Ldar), R(1), // - B(JumpIfToBooleanTrue), U8(-14), // + B(Star), R(2), // + B(LdaSmi8), U8(12), // + B(Mul), R(2), // + B(Star), R(1), // B(Ldar), R(0), // + B(Star), R(2), // + B(LdaSmi8), U8(1), // + B(Sub), R(2), // + B(Star), R(0), // + B(Ldar), R(0), // + B(JumpIfToBooleanTrue), U8(-22), // + B(Ldar), R(1), // B(Return), // }, 0}, @@ -2256,26 +2572,33 @@ TEST(BasicLoops) { " if (x == 6) continue;" "} while (false);" "return y;", - 2 * kPointerSize, + 3 * kPointerSize, 1, - 38, + 52, { B(LdaZero), // B(Star), R(0), // B(LdaSmi8), U8(1), // B(Star), R(1), // + B(Ldar), R(1), // + B(Star), R(2), // B(LdaSmi8), U8(10), // - B(Mul), R(1), // + B(Mul), R(2), // B(Star), R(1), // + B(Ldar), R(0), // + B(Star), R(2), // B(LdaSmi8), U8(5), // - B(TestEqual), R(0), // + B(TestEqual), R(2), // B(JumpIfFalse), U8(4), // - B(Jump), U8(16), // + B(Jump), U8(22), // + B(Ldar), R(0), // + B(Star), R(2), // B(LdaSmi8), U8(1), // - B(Add), R(0), // + B(Add), R(2), // B(Star), R(0), // + B(Star), R(2), // B(LdaSmi8), U8(6), // - B(TestEqual), R(0), // + B(TestEqual), R(2), // B(JumpIfFalse), U8(4), // B(Jump), U8(2), // B(Ldar), R(1), // @@ -2290,50 +2613,237 @@ TEST(BasicLoops) { " if (x == 6) continue;" "} while (true);" "return y;", - 2 * kPointerSize, + 3 * kPointerSize, 1, - 40, + 54, { B(LdaZero), // B(Star), R(0), // B(LdaSmi8), U8(1), // B(Star), R(1), // + B(Ldar), R(1), // + B(Star), R(2), // B(LdaSmi8), U8(10), // - B(Mul), R(1), // + B(Mul), R(2), // B(Star), R(1), // + B(Ldar), R(0), // + B(Star), R(2), // B(LdaSmi8), U8(5), // - B(TestEqual), R(0), // + B(TestEqual), R(2), // B(JumpIfFalse), U8(4), // - B(Jump), U8(18), // + B(Jump), U8(24), // + B(Ldar), R(0), // + B(Star), R(2), // B(LdaSmi8), U8(1), // - B(Add), R(0), // + B(Add), R(2), // B(Star), R(0), // + B(Star), R(2), // B(LdaSmi8), U8(6), // - B(TestEqual), R(0), // + B(TestEqual), R(2), // B(JumpIfFalse), U8(4), // - B(Jump), U8(2), // - B(Jump), U8(-28), // + B(Jump), U8(-40), // + B(Jump), U8(-42), // B(Ldar), R(1), // B(Return), // }, 0}, - {"var x = 0;" - "while(false) {" + {"var x = 0; " + "for (;;) {" + " if (x == 1) break;" + " if (x == 2) continue;" " x = x + 1;" - "};" - "return x;", - 1 * kPointerSize, + "}", + 2 * kPointerSize, 1, - 6, + 41, { - B(LdaZero), // - B(Star), R(0), // - B(Ldar), R(0), // - B(Return), // + B(LdaZero), // + B(Star), R(0), // + B(Ldar), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(1), // + B(TestEqual), R(1), // + B(JumpIfFalse), U8(4), // + B(Jump), U8(26), // + B(Ldar), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(2), // + B(TestEqual), R(1), // + B(JumpIfFalse), U8(4), // + B(Jump), U8(-22), // + B(Ldar), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(1), // + B(Add), R(1), // + B(Star), R(0), // + B(Jump), U8(-34), // + B(LdaUndefined), // + B(Return), // + }, + 0}, + {"for (var x = 0;;) {" + " if (x == 1) break;" + " if (x == 2) continue;" + " x = x + 1;" + "}", + 2 * kPointerSize, + 1, + 41, + { + B(LdaZero), // + B(Star), R(0), // + B(Ldar), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(1), // + B(TestEqual), R(1), // + B(JumpIfFalse), U8(4), // + B(Jump), U8(26), // + B(Ldar), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(2), // + B(TestEqual), R(1), // + B(JumpIfFalse), U8(4), // + B(Jump), U8(-22), // + B(Ldar), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(1), // + B(Add), R(1), // + B(Star), R(0), // + B(Jump), U8(-34), // + B(LdaUndefined), // + B(Return), // + }, + 0}, + {"var x = 0; " + "for (;; x = x + 1) {" + " if (x == 1) break;" + " if (x == 2) continue;" + "}", + 2 * kPointerSize, + 1, + 41, + { + B(LdaZero), // + B(Star), R(0), // + B(Ldar), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(1), // + B(TestEqual), R(1), // + B(JumpIfFalse), U8(4), // + B(Jump), U8(26), // + B(Ldar), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(2), // + B(TestEqual), R(1), // + B(JumpIfFalse), U8(4), // + B(Jump), U8(2), // + B(Ldar), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(1), // + B(Add), R(1), // + B(Star), R(0), // + B(Jump), U8(-34), // + B(LdaUndefined), // + B(Return), // + }, + 0}, + {"for (var x = 0;; x = x + 1) {" + " if (x == 1) break;" + " if (x == 2) continue;" + "}", + 2 * kPointerSize, + 1, + 41, + { + B(LdaZero), // + B(Star), R(0), // + B(Ldar), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(1), // + B(TestEqual), R(1), // + B(JumpIfFalse), U8(4), // + B(Jump), U8(26), // + B(Ldar), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(2), // + B(TestEqual), R(1), // + B(JumpIfFalse), U8(4), // + B(Jump), U8(2), // + B(Ldar), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(1), // + B(Add), R(1), // + B(Star), R(0), // + B(Jump), U8(-34), // + B(LdaUndefined), // + B(Return), // + }, + 0}, + {"var u = 0;" + "for (var i = 0; i < 100; i = i + 1) {" + " u = u + 1;" + " continue;" + "}", + 3 * kPointerSize, + 1, + 42, + { + B(LdaZero), // + B(Star), R(0), // + B(LdaZero), // + B(Star), R(1), // + B(Ldar), R(1), // + B(Star), R(2), // + B(LdaSmi8), U8(100), // + B(TestLessThan), R(2), // + B(JumpIfFalse), U8(26), // + B(Ldar), R(0), // + B(Star), R(2), // + B(LdaSmi8), U8(1), // + B(Add), R(2), // + B(Star), R(0), // + B(Jump), U8(2), // + B(Ldar), R(1), // + B(Star), R(2), // + B(LdaSmi8), U8(1), // + B(Add), R(2), // + B(Star), R(1), // + B(Jump), U8(-32), // + B(LdaUndefined), // + B(Return), // + }, + 0}, + {"var y = 1;" + "for (var x = 10; x; --x) {" + " y = y * 12;" + "}" + "return y;", + 3 * kPointerSize, + 1, + 33, + { + B(LdaSmi8), U8(1), // + B(Star), R(0), // + B(LdaSmi8), U8(10), // + B(Star), R(1), // + B(Ldar), R(1), // + B(JumpIfToBooleanFalse), U8(20), // + B(Ldar), R(0), // + B(Star), R(2), // + B(LdaSmi8), U8(12), // + B(Mul), R(2), // + B(Star), R(0), // + B(Ldar), R(1), // + B(ToNumber), // + B(Dec), // + B(Star), R(1), // + B(Jump), U8(-20), // + B(Ldar), R(0), // + B(Return), // }, 0}, {"var x = 0;" - "for( var i = 0; false; i++) {" + "for (var i = 0; false; i++) {" " x = x + 1;" "};" "return x;", @@ -2350,31 +2860,34 @@ TEST(BasicLoops) { }, 0}, {"var x = 0;" - "for( var i = 0; true; ++i) {" + "for (var i = 0; true; ++i) {" " x = x + 1;" " if (x == 20) break;" "};" "return x;", - 2 * kPointerSize, + 3 * kPointerSize, 1, - 31, + 37, { B(LdaZero), // B(Star), R(0), // B(LdaZero), // B(Star), R(1), // + B(Ldar), R(0), // + B(Star), R(2), // B(LdaSmi8), U8(1), // - B(Add), R(0), // + B(Add), R(2), // B(Star), R(0), // + B(Star), R(2), // B(LdaSmi8), U8(20), // - B(TestEqual), R(0), // + B(TestEqual), R(2), // B(JumpIfFalse), U8(4), // B(Jump), U8(10), // B(Ldar), R(1), // B(ToNumber), // B(Inc), // B(Star), R(1), // - B(Jump), U8(-20), // + B(Jump), U8(-26), // B(Ldar), R(0), // B(Return), // }, @@ -2389,6 +2902,83 @@ TEST(BasicLoops) { } +TEST(JumpsRequiringConstantWideOperands) { + InitializedHandleScope handle_scope; + BytecodeGeneratorHelper helper; + + int constant_count = 0; + ExpectedSnippet<Handle<Object>, 316> snippets[] = { + { + REPEAT_256(SPACE, "var x = 0.1;") + REPEAT_32(SPACE, "var x = 0.2;") + REPEAT_16(SPACE, "var x = 0.3;") + REPEAT_8(SPACE, "var x = 0.4;") + "for (var i = 0; i < 3; i++) {\n" + " if (i == 1) continue;\n" + " if (i == 2) break;\n" + "}\n" + "return 3;", + kPointerSize * 3, + 1, + 1359, + { +#define L(c) B(LdaConstant), U8(c), B(Star), R(0) + REPEAT_256(COMMA, L(constant_count++)), +#undef L +#define LW(c) B(LdaConstantWide), U16I(c), B(Star), R(0) + REPEAT_32(COMMA, LW(constant_count)), + REPEAT_16(COMMA, LW(constant_count)), + REPEAT_8(COMMA, LW(constant_count)), +#undef LW + B(LdaZero), // + B(Star), R(1), // + B(Ldar), R(1), // + B(Star), R(2), // + B(LdaSmi8), U8(3), // + B(TestLessThan), R(2), // + B(JumpIfFalseConstantWide), U16(313), // + B(Ldar), R(1), // + B(Star), R(2), // + B(LdaSmi8), U8(1), // + B(TestEqual), R(2), // + B(JumpIfFalseConstantWide), U16(312), // + B(JumpConstantWide), U16(315), // + B(Ldar), R(1), // + B(Star), R(2), // + B(LdaSmi8), U8(2), // + B(TestEqual), R(2), // + B(JumpIfFalseConstantWide), U16(312), // + B(JumpConstantWide), U16(314), // + B(Ldar), R(1), // + B(ToNumber), // + B(Star), R(2), // + B(Inc), // + B(Star), R(1), // + B(Jump), U8(-47), // + B(LdaSmi8), U8(3), // + B(Return) // + }, + 316, + { +#define S(x) CcTest::i_isolate()->factory()->NewNumber(x) + REPEAT_256(COMMA, S(0.1)), + REPEAT_32(COMMA, S(0.2)), + REPEAT_16(COMMA, S(0.3)), + REPEAT_8(COMMA, S(0.4)), +#undef S +#define N(x) CcTest::i_isolate()->factory()->NewNumberFromInt(x) + N(6), N(41), N(13), N(17) +#undef N + }}}; + + for (size_t i = 0; i < arraysize(snippets); i++) { + Handle<BytecodeArray> bytecode_array = + helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); + CheckBytecodeArrayEqual(snippets[i], bytecode_array); + } +} + + TEST(UnaryOperators) { InitializedHandleScope handle_scope; BytecodeGeneratorHelper helper; @@ -2399,20 +2989,24 @@ TEST(UnaryOperators) { " x = x + 10;" "}" "return x;", - kPointerSize, + 2 * kPointerSize, 1, - 21, + 29, { B(LdaZero), // B(Star), R(0), // - B(Jump), U8(8), // - B(LdaSmi8), U8(10), // - B(Add), R(0), // - B(Star), R(0), // + B(Ldar), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(10), // - B(TestEqual), R(0), // + B(TestEqual), R(1), // B(LogicalNot), // - B(JumpIfTrue), U8(-11), // + B(JumpIfFalse), U8(14), // + B(Ldar), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(10), // + B(Add), R(1), // + B(Star), R(0), // + B(Jump), U8(-21), // B(Ldar), R(0), // B(Return), // }, @@ -2422,32 +3016,35 @@ TEST(UnaryOperators) { " x = !x;" "} while(x == false);" "return x;", - kPointerSize, + 2 * kPointerSize, 1, - 16, + 20, { B(LdaFalse), // B(Star), R(0), // B(Ldar), R(0), // B(LogicalNot), // B(Star), R(0), // + B(Ldar), R(0), // + B(Star), R(1), // B(LdaFalse), // - B(TestEqual), R(0), // - B(JumpIfTrue), U8(-8), // + B(TestEqual), R(1), // + B(JumpIfTrue), U8(-12), // B(Ldar), R(0), // B(Return), // }, 0}, {"var x = 101;" "return void(x * 3);", - kPointerSize, + 2 * kPointerSize, 1, - 10, + 12, { B(LdaSmi8), U8(101), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(3), // - B(Mul), R(0), // + B(Mul), R(1), // B(LdaUndefined), // B(Return), // }, @@ -2455,60 +3052,63 @@ TEST(UnaryOperators) { {"var x = 1234;" "var y = void (x * x - 1);" "return y;", - 3 * kPointerSize, + 4 * kPointerSize, 1, 20, { B(LdaConstant), U8(0), // B(Star), R(0), // - B(Ldar), R(0), // - B(Mul), R(0), // B(Star), R(2), // + B(Ldar), R(0), // + B(Mul), R(2), // + B(Star), R(3), // B(LdaSmi8), U8(1), // - B(Sub), R(2), // + B(Sub), R(3), // B(LdaUndefined), // B(Star), R(1), // - B(Ldar), R(1), // B(Return), // }, 1, {1234}}, {"var x = 13;" "return ~x;", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 9, + 11, { B(LdaSmi8), U8(13), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(-1), // - B(BitwiseXor), R(0), // + B(BitwiseXor), R(1), // B(Return), // }, 0}, {"var x = 13;" "return +x;", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 9, + 11, { B(LdaSmi8), U8(13), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(1), // - B(Mul), R(0), // + B(Mul), R(1), // B(Return), // }, 0}, {"var x = 13;" "return -x;", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 9, + 11, { B(LdaSmi8), U8(13), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(-1), // - B(Mul), R(0), // + B(Mul), R(1), // B(Return), // }, 0}}; @@ -2539,11 +3139,10 @@ TEST(Typeof) { "}; f();", kPointerSize, 1, - 8, + 6, { B(LdaSmi8), U8(13), // - B(Star), R(0), // TODO(oth): Ldar R(X) following Star R(X) - B(Ldar), R(0), // could be culled in bytecode array builder. + B(Star), R(0), // B(TypeOf), // B(Return), // }}, @@ -2599,45 +3198,45 @@ TEST(Delete) { ExpectedSnippet<InstanceType> snippets[] = { {"var a = {x:13, y:14}; return delete a.x;", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 12, + 13, { - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // - B(Star), R(0), // - B(LdaConstant), U8(1), // - B(DeletePropertySloppy), R(0), // + B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // + B(Star), R(0), // + B(Star), R(1), // + B(LdaConstant), U8(1), // + B(DeletePropertySloppy), R(1), // B(Return) }, 2, {InstanceType::FIXED_ARRAY_TYPE, InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, {"'use strict'; var a = {x:13, y:14}; return delete a.x;", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 12, + 13, { - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // - B(Star), R(0), // - B(LdaConstant), U8(1), // - B(DeletePropertyStrict), R(0), // + B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // + B(Star), R(0), // + B(Star), R(1), // + B(LdaConstant), U8(1), // + B(DeletePropertyStrict), R(1), // B(Return) }, 2, {InstanceType::FIXED_ARRAY_TYPE, InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, {"var a = {1:13, 2:14}; return delete a[2];", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 12, + 13, { - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // - B(Star), R(0), // - B(LdaSmi8), U8(2), // - B(DeletePropertySloppy), R(0), // + B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // + B(Star), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(2), // + B(DeletePropertySloppy), R(1), // B(Return) }, 1, @@ -2659,20 +3258,18 @@ TEST(Delete) { "return delete a[1];", 2 * kPointerSize, 1, - 29, + 27, { - B(CallRuntime), U16(Runtime::kNewFunctionContext), // - R(closure), U8(1), // - B(PushContext), R(0), // - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // - B(StaContextSlot), R(0), U8(first_context_slot), // - B(LdaConstant), U8(1), // - B(CreateClosure), U8(0), // - B(LdaContextSlot), R(0), U8(first_context_slot), // - B(Star), R(1), // - B(LdaSmi8), U8(1), // - B(DeletePropertyStrict), R(1), // + B(CallRuntime), U16(Runtime::kNewFunctionContext), // + R(closure), U8(1), // + B(PushContext), R(0), // + B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // + B(StaContextSlot), R(0), U8(first_context_slot), // + B(CreateClosure), U8(1), U8(0), // + B(LdaContextSlot), R(0), U8(first_context_slot), // + B(Star), R(1), // + B(LdaSmi8), U8(1), // + B(DeletePropertyStrict), R(1), // B(Return) }, 2, @@ -2703,7 +3300,8 @@ TEST(GlobalDelete) { Zone zone; int context = Register::function_context().index(); - int global_object_index = Context::GLOBAL_OBJECT_INDEX; + int native_context_index = Context::NATIVE_CONTEXT_INDEX; + int global_context_index = Context::EXTENSION_INDEX; FeedbackVectorSpec feedback_spec(&zone); FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot(); @@ -2715,13 +3313,11 @@ TEST(GlobalDelete) { 1 * kPointerSize, 1, 10, - { - B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), // - B(Star), R(0), // - B(LdaConstant), U8(1), // - B(DeletePropertySloppy), R(0), // - B(Return) - }, + {B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), // + B(Star), R(0), // + B(LdaConstant), U8(1), // + B(DeletePropertySloppy), R(0), // + B(Return)}, 2, {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, @@ -2730,39 +3326,37 @@ TEST(GlobalDelete) { 1 * kPointerSize, 1, 10, - { - B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot)), // - B(Star), R(0), // - B(LdaSmi8), U8(1), // - B(DeletePropertyStrict), R(0), // - B(Return) - }, + {B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot)), // + B(Star), R(0), // + B(LdaSmi8), U8(1), // + B(DeletePropertyStrict), R(0), // + B(Return)}, 1, {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, {"var a = {x:13, y:14};\n function f() { return delete a; };\n f();", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 10, - { - B(LdaContextSlot), R(context), U8(global_object_index), // - B(Star), R(0), // - B(LdaConstant), U8(0), // - B(DeletePropertySloppy), R(0), // - B(Return) - }, + 15, + {B(LdaContextSlot), R(context), U8(native_context_index), // + B(Star), R(0), // + B(LdaContextSlot), R(0), U8(global_context_index), // + B(Star), R(1), // + B(LdaConstant), U8(0), // + B(DeletePropertySloppy), R(1), // + B(Return)}, 1, {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, {"b = 30;\n function f() { return delete b; };\n f();", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 10, - { - B(LdaContextSlot), R(context), U8(global_object_index), // - B(Star), R(0), // - B(LdaConstant), U8(0), // - B(DeletePropertySloppy), R(0), // - B(Return) - }, + 15, + {B(LdaContextSlot), R(context), U8(native_context_index), // + B(Star), R(0), // + B(LdaContextSlot), R(0), U8(global_context_index), // + B(Star), R(1), // + B(LdaConstant), U8(0), // + B(DeletePropertySloppy), R(1), // + B(Return)}, 1, {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}}; @@ -2777,16 +3371,22 @@ TEST(GlobalDelete) { TEST(FunctionLiterals) { InitializedHandleScope handle_scope; BytecodeGeneratorHelper helper; + Zone zone; + + FeedbackVectorSpec feedback_spec(&zone); + FeedbackVectorSlot slot = feedback_spec.AddCallICSlot(); + + Handle<i::TypeFeedbackVector> vector = + i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); ExpectedSnippet<InstanceType> snippets[] = { {"return function(){ }", 0, 1, - 5, + 4, { - B(LdaConstant), U8(0), // - B(CreateClosure), U8(0), // - B(Return) // + B(CreateClosure), U8(0), U8(0), // + B(Return) // }, 1, {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, @@ -2795,13 +3395,12 @@ TEST(FunctionLiterals) { 1, 14, { - B(LdaUndefined), // - B(Star), R(1), // - B(LdaConstant), U8(0), // - B(CreateClosure), U8(0), // - B(Star), R(0), // - B(Call), R(0), R(1), U8(0), // - B(Return) // + B(LdaUndefined), // + B(Star), R(1), // + B(CreateClosure), U8(0), U8(0), // + B(Star), R(0), // + B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot)), // + B(Return) // }, 1, {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, @@ -2810,15 +3409,14 @@ TEST(FunctionLiterals) { 1, 18, { - B(LdaUndefined), // - B(Star), R(1), // - B(LdaConstant), U8(0), // - B(CreateClosure), U8(0), // - B(Star), R(0), // - B(LdaSmi8), U8(1), // - B(Star), R(2), // - B(Call), R(0), R(1), U8(1), // - B(Return) // + B(LdaUndefined), // + B(Star), R(1), // + B(CreateClosure), U8(0), U8(0), // + B(Star), R(0), // + B(LdaSmi8), U8(1), // + B(Star), R(2), // + B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot)), // + B(Return) // }, 1, {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, @@ -2838,58 +3436,82 @@ TEST(RegExpLiterals) { Zone zone; FeedbackVectorSpec feedback_spec(&zone); - feedback_spec.AddLoadICSlot(); + FeedbackVectorSlot slot1 = feedback_spec.AddCallICSlot(); FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot(); + uint8_t i_flags = JSRegExp::kIgnoreCase; Handle<i::TypeFeedbackVector> vector = i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); ExpectedSnippet<const char*> snippets[] = { {"return /ab+d/;", - 1 * kPointerSize, + 0 * kPointerSize, 1, - 10, + 5, { - B(LdaConstant), U8(0), // - B(Star), R(0), // - B(LdaConstant), U8(1), // - B(CreateRegExpLiteral), U8(0), R(0), // - B(Return), // + B(CreateRegExpLiteral), U8(0), U8(0), U8(0), // + B(Return), // }, - 2, - {"", "ab+d"}}, + 1, + {"ab+d"}}, {"return /(\\w+)\\s(\\w+)/i;", - 1 * kPointerSize, + 0 * kPointerSize, 1, - 10, + 5, { - B(LdaConstant), U8(0), // - B(Star), R(0), // - B(LdaConstant), U8(1), // - B(CreateRegExpLiteral), U8(0), R(0), // - B(Return), // + B(CreateRegExpLiteral), U8(0), U8(0), U8(i_flags), // + B(Return), // }, - 2, - {"i", "(\\w+)\\s(\\w+)"}}, + 1, + {"(\\w+)\\s(\\w+)"}}, {"return /ab+d/.exec('abdd');", 3 * kPointerSize, 1, - 26, + 22, { - B(LdaConstant), U8(0), // - B(Star), R(2), // - B(LdaConstant), U8(1), // - B(CreateRegExpLiteral), U8(0), R(2), // + B(CreateRegExpLiteral), U8(0), U8(0), U8(0), // B(Star), R(1), // - B(LoadICSloppy), R(1), U8(2), U8(vector->GetIndex(slot2)), // + B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)), // B(Star), R(0), // - B(LdaConstant), U8(3), // + B(LdaConstant), U8(2), // B(Star), R(2), // - B(Call), R(0), R(1), U8(1), // + B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot1)), // B(Return), // }, - 4, - {"", "ab+d", "exec", "abdd"}}, + 3, + {"ab+d", "exec", "abdd"}}, + }; + + for (size_t i = 0; i < arraysize(snippets); i++) { + Handle<BytecodeArray> bytecode_array = + helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); + CheckBytecodeArrayEqual(snippets[i], bytecode_array); + } +} + + +TEST(RegExpLiteralsWide) { + InitializedHandleScope handle_scope; + BytecodeGeneratorHelper helper; + Zone zone; + + int wide_idx = 0; + + ExpectedSnippet<InstanceType, 257> snippets[] = { + {"var a;" REPEAT_256(SPACE, "a = 1.23;") "return /ab+d/;", + 1 * kPointerSize, + 1, + 1031, + { + REPEAT_256(COMMA, // + B(LdaConstant), U8(wide_idx++), // + B(Star), R(0)), // + B(CreateRegExpLiteralWide), U16(256), U16(0), U8(0), // + B(Return) // + }, + 257, + {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE), + InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, }; for (size_t i = 0; i < arraysize(snippets); i++) { @@ -2920,23 +3542,21 @@ TEST(ArrayLiterals) { {"return [ 1, 2 ];", 0, 1, - 6, + 5, { - B(LdaConstant), U8(0), // - B(CreateArrayLiteral), U8(0), U8(simple_flags), // - B(Return) // + B(CreateArrayLiteral), U8(0), U8(0), U8(simple_flags), // + B(Return) // }, 1, {InstanceType::FIXED_ARRAY_TYPE}}, {"var a = 1; return [ a, a + 1 ];", - 3 * kPointerSize, + 4 * kPointerSize, 1, - 35, + 38, { B(LdaSmi8), U8(1), // B(Star), R(0), // - B(LdaConstant), U8(0), // - B(CreateArrayLiteral), U8(0), U8(3), // + B(CreateArrayLiteral), U8(0), U8(0), U8(3), // B(Star), R(2), // B(LdaZero), // B(Star), R(1), // @@ -2944,8 +3564,10 @@ TEST(ArrayLiterals) { B(KeyedStoreICSloppy), R(2), R(1), U8(vector->GetIndex(slot1)), // B(LdaSmi8), U8(1), // B(Star), R(1), // + B(Ldar), R(0), // + B(Star), R(3), // B(LdaSmi8), U8(1), // - B(Add), R(0), // + B(Add), R(3), // B(KeyedStoreICSloppy), R(2), R(1), U8(vector->GetIndex(slot1)), // B(Ldar), R(2), // B(Return), // @@ -2955,28 +3577,25 @@ TEST(ArrayLiterals) { {"return [ [ 1, 2 ], [ 3 ] ];", 0, 1, - 6, + 5, { - B(LdaConstant), U8(0), // - B(CreateArrayLiteral), U8(2), U8(deep_elements_flags), // - B(Return) // + B(CreateArrayLiteral), U8(0), U8(2), U8(deep_elements_flags), // + B(Return) // }, 1, {InstanceType::FIXED_ARRAY_TYPE}}, {"var a = 1; return [ [ a, 2 ], [ a + 2 ] ];", - 5 * kPointerSize, + 6 * kPointerSize, 1, - 67, + 68, { B(LdaSmi8), U8(1), // B(Star), R(0), // - B(LdaConstant), U8(0), // - B(CreateArrayLiteral), U8(2), U8(deep_elements_flags), // + B(CreateArrayLiteral), U8(0), U8(2), U8(deep_elements_flags), // B(Star), R(2), // B(LdaZero), // B(Star), R(1), // - B(LdaConstant), U8(1), // - B(CreateArrayLiteral), U8(0), U8(simple_flags), // + B(CreateArrayLiteral), U8(1), U8(0), U8(simple_flags), // B(Star), R(4), // B(LdaZero), // B(Star), R(3), // @@ -2986,13 +3605,14 @@ TEST(ArrayLiterals) { B(KeyedStoreICSloppy), R(2), R(1), U8(vector->GetIndex(slot3)), // B(LdaSmi8), U8(1), // B(Star), R(1), // - B(LdaConstant), U8(2), // - B(CreateArrayLiteral), U8(1), U8(simple_flags), // + B(CreateArrayLiteral), U8(2), U8(1), U8(simple_flags), // B(Star), R(4), // B(LdaZero), // B(Star), R(3), // + B(Ldar), R(0), // + B(Star), R(5), // B(LdaSmi8), U8(2), // - B(Add), R(0), // + B(Add), R(5), // B(KeyedStoreICSloppy), R(4), R(3), U8(vector->GetIndex(slot2)), // B(Ldar), R(4), // B(KeyedStoreICSloppy), R(2), R(1), U8(vector->GetIndex(slot3)), // @@ -3012,6 +3632,40 @@ TEST(ArrayLiterals) { } +TEST(ArrayLiteralsWide) { + InitializedHandleScope handle_scope; + BytecodeGeneratorHelper helper; + Zone zone; + + int wide_idx = 0; + int simple_flags = + ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements; + + ExpectedSnippet<InstanceType, 257> snippets[] = { + {"var a;" REPEAT_256(SPACE, "a = 1.23;") "return [ 1 , 2 ];", + 1 * kPointerSize, + 1, + 1031, + { + REPEAT_256(COMMA, // + B(LdaConstant), U8(wide_idx++), // + B(Star), R(0)), // + B(CreateArrayLiteralWide), U16(256), U16(0), U8(simple_flags), // + B(Return) // + }, + 257, + {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE), + InstanceType::FIXED_ARRAY_TYPE}}, + }; + + for (size_t i = 0; i < arraysize(snippets); i++) { + Handle<BytecodeArray> bytecode_array = + helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); + CheckBytecodeArrayEqual(snippets[i], bytecode_array); + } +} + + TEST(ObjectLiterals) { InitializedHandleScope handle_scope; BytecodeGeneratorHelper helper; @@ -3032,58 +3686,56 @@ TEST(ObjectLiterals) { {"return { };", 0, 1, - 6, + 5, { - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(simple_flags), // - B(Return) // + B(CreateObjectLiteral), U8(0), U8(0), U8(simple_flags), // + B(Return) // }, 1, {InstanceType::FIXED_ARRAY_TYPE}}, {"return { name: 'string', val: 9.2 };", 0, 1, - 6, + 5, { - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // - B(Return) // + B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // + B(Return) // }, 1, {InstanceType::FIXED_ARRAY_TYPE}}, {"var a = 1; return { name: 'string', val: a };", 2 * kPointerSize, 1, - 20, + 19, { - B(LdaSmi8), U8(1), // - B(Star), R(0), // - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // - B(Star), R(1), // - B(Ldar), R(0), // - B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), // - B(Ldar), R(1), // - B(Return), // + B(LdaSmi8), U8(1), // + B(Star), R(0), // + B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // + B(Star), R(1), // + B(Ldar), R(0), // + B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), // + B(Ldar), R(1), // + B(Return), // }, 2, {InstanceType::FIXED_ARRAY_TYPE, InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, {"var a = 1; return { val: a, val: a + 1 };", - 2 * kPointerSize, + 3 * kPointerSize, 1, - 22, + 25, { - B(LdaSmi8), U8(1), // - B(Star), R(0), // - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // - B(Star), R(1), // - B(LdaSmi8), U8(1), // - B(Add), R(0), // - B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), // - B(Ldar), R(1), // - B(Return), // + B(LdaSmi8), U8(1), // + B(Star), R(0), // + B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // + B(Star), R(1), // + B(Ldar), R(0), // + B(Star), R(2), // + B(LdaSmi8), U8(1), // + B(Add), R(2), // + B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), // + B(Ldar), R(1), // + B(Return), // }, 2, {InstanceType::FIXED_ARRAY_TYPE, @@ -3091,51 +3743,45 @@ TEST(ObjectLiterals) { {"return { func: function() { } };", 1 * kPointerSize, 1, - 18, + 16, { - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // - B(Star), R(0), // - B(LdaConstant), U8(2), // - B(CreateClosure), U8(0), // - B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), // - B(Ldar), R(0), // - B(Return), // + B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // + B(Star), R(0), // + B(CreateClosure), U8(1), U8(0), // + B(StoreICSloppy), R(0), U8(2), U8(vector->GetIndex(slot1)), // + B(Ldar), R(0), // + B(Return), // }, 3, {InstanceType::FIXED_ARRAY_TYPE, - InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, - InstanceType::SHARED_FUNCTION_INFO_TYPE}}, + InstanceType::SHARED_FUNCTION_INFO_TYPE, + InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, {"return { func(a) { return a; } };", 1 * kPointerSize, 1, - 18, + 16, { - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // - B(Star), R(0), // - B(LdaConstant), U8(2), // - B(CreateClosure), U8(0), // - B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), // - B(Ldar), R(0), // - B(Return), // + B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // + B(Star), R(0), // + B(CreateClosure), U8(1), U8(0), // + B(StoreICSloppy), R(0), U8(2), U8(vector->GetIndex(slot1)), // + B(Ldar), R(0), // + B(Return), // }, 3, {InstanceType::FIXED_ARRAY_TYPE, - InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, - InstanceType::SHARED_FUNCTION_INFO_TYPE}}, + InstanceType::SHARED_FUNCTION_INFO_TYPE, + InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, {"return { get a() { return 2; } };", 5 * kPointerSize, 1, - 31, + 29, { - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // + B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // B(Star), R(0), // B(LdaConstant), U8(1), // B(Star), R(1), // - B(LdaConstant), U8(2), // - B(CreateClosure), U8(0), // + B(CreateClosure), U8(2), U8(0), // B(Star), R(2), // B(LdaNull), // B(Star), R(3), // @@ -3153,18 +3799,15 @@ TEST(ObjectLiterals) { {"return { get a() { return this.x; }, set a(val) { this.x = val } };", 5 * kPointerSize, 1, - 34, + 31, { - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // + B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // B(Star), R(0), // B(LdaConstant), U8(1), // B(Star), R(1), // - B(LdaConstant), U8(2), // - B(CreateClosure), U8(0), // + B(CreateClosure), U8(2), U8(0), // B(Star), R(2), // - B(LdaConstant), U8(3), // - B(CreateClosure), U8(0), // + B(CreateClosure), U8(3), U8(0), // B(Star), R(3), // B(LdaZero), // B(Star), R(4), // @@ -3181,17 +3824,15 @@ TEST(ObjectLiterals) { {"return { set b(val) { this.y = val } };", 5 * kPointerSize, 1, - 31, + 29, { - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // + B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // B(Star), R(0), // B(LdaConstant), U8(1), // B(Star), R(1), // B(LdaNull), // B(Star), R(2), // - B(LdaConstant), U8(2), // - B(CreateClosure), U8(0), // + B(CreateClosure), U8(2), U8(0), // B(Star), R(3), // B(LdaZero), // B(Star), R(4), // @@ -3207,32 +3848,30 @@ TEST(ObjectLiterals) { {"var a = 1; return { 1: a };", 5 * kPointerSize, 1, - 30, + 29, { - B(LdaSmi8), U8(1), // - B(Star), R(0), // - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // - B(Star), R(1), // - B(LdaSmi8), U8(1), // - B(Star), R(2), // - B(Ldar), R(0), // - B(Star), R(3), // - B(LdaZero), // - B(Star), R(4), // - B(CallRuntime), U16(Runtime::kSetProperty), R(1), U8(4), // - B(Ldar), R(1), // - B(Return), // + B(LdaSmi8), U8(1), // + B(Star), R(0), // + B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // + B(Star), R(1), // + B(LdaSmi8), U8(1), // + B(Star), R(2), // + B(Ldar), R(0), // + B(Star), R(3), // + B(LdaZero), // + B(Star), R(4), // + B(CallRuntime), U16(Runtime::kSetProperty), R(1), U8(4), // + B(Ldar), R(1), // + B(Return), // }, 1, {InstanceType::FIXED_ARRAY_TYPE}}, {"return { __proto__: null }", 2 * kPointerSize, 1, - 18, + 17, { - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(simple_flags), // + B(CreateObjectLiteral), U8(0), U8(0), U8(simple_flags), // B(Star), R(0), // B(LdaNull), B(Star), R(1), // B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(0), U8(2), // @@ -3244,12 +3883,11 @@ TEST(ObjectLiterals) { {"var a = 'test'; return { [a]: 1 }", 5 * kPointerSize, 1, - 31, + 30, { B(LdaConstant), U8(0), // B(Star), R(0), // - B(LdaConstant), U8(1), // - B(CreateObjectLiteral), U8(0), U8(simple_flags), // + B(CreateObjectLiteral), U8(1), U8(0), U8(simple_flags), // B(Star), R(1), // B(Ldar), R(0), // B(ToName), // @@ -3269,12 +3907,11 @@ TEST(ObjectLiterals) { {"var a = 'test'; return { val: a, [a]: 1 }", 5 * kPointerSize, 1, - 37, + 36, { B(LdaConstant), U8(0), // B(Star), R(0), // - B(LdaConstant), U8(1), // - B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // + B(CreateObjectLiteral), U8(1), U8(0), U8(deep_elements_flags), // B(Star), R(1), // B(Ldar), R(0), // B(StoreICSloppy), R(1), U8(2), U8(vector->GetIndex(slot1)), // @@ -3297,12 +3934,11 @@ TEST(ObjectLiterals) { {"var a = 'test'; return { [a]: 1, __proto__: {} }", 5 * kPointerSize, 1, - 43, + 41, { B(LdaConstant), U8(0), // B(Star), R(0), // - B(LdaConstant), U8(1), // - B(CreateObjectLiteral), U8(1), U8(simple_flags), // + B(CreateObjectLiteral), U8(1), U8(1), U8(simple_flags), // B(Star), R(1), // B(Ldar), R(0), // B(ToName), // @@ -3313,8 +3949,7 @@ TEST(ObjectLiterals) { B(Star), R(4), // B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), // U8(4), // - B(LdaConstant), U8(1), // - B(CreateObjectLiteral), U8(0), U8(13), // + B(CreateObjectLiteral), U8(1), U8(0), U8(13), // B(Star), R(2), // B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(1), U8(2), // B(Ldar), R(1), // @@ -3326,12 +3961,11 @@ TEST(ObjectLiterals) { {"var n = 'name'; return { [n]: 'val', get a() { }, set a(b) {} };", 5 * kPointerSize, 1, - 69, + 64, { B(LdaConstant), U8(0), // B(Star), R(0), // - B(LdaConstant), U8(1), // - B(CreateObjectLiteral), U8(0), U8(simple_flags), // + B(CreateObjectLiteral), U8(1), U8(0), U8(simple_flags), // B(Star), R(1), // B(Ldar), R(0), // B(ToName), // @@ -3343,20 +3977,16 @@ TEST(ObjectLiterals) { B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), // U8(4), // B(LdaConstant), U8(3), // - B(ToName), // B(Star), R(2), // - B(LdaConstant), U8(4), // - B(CreateClosure), U8(0), // + B(CreateClosure), U8(4), U8(0), // B(Star), R(3), // B(LdaZero), // B(Star), R(4), // B(CallRuntime), U16(Runtime::kDefineGetterPropertyUnchecked), // R(1), U8(4), // B(LdaConstant), U8(3), // - B(ToName), // B(Star), R(2), // - B(LdaConstant), U8(5), // - B(CreateClosure), U8(0), // + B(CreateClosure), U8(5), U8(0), // B(Star), R(3), // B(LdaZero), // B(Star), R(4), // @@ -3382,6 +4012,42 @@ TEST(ObjectLiterals) { } +TEST(ObjectLiteralsWide) { + InitializedHandleScope handle_scope; + BytecodeGeneratorHelper helper; + Zone zone; + + int deep_elements_flags = + ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos; + int wide_idx = 0; + + ExpectedSnippet<InstanceType, 257> snippets[] = { + {"var a;" REPEAT_256(SPACE, + "a = 1.23;") "return { name: 'string', val: 9.2 };", + 1 * kPointerSize, + 1, + 1031, + { + REPEAT_256(COMMA, // + B(LdaConstant), U8(wide_idx++), // + B(Star), R(0)), // + B(CreateObjectLiteralWide), U16(256), U16(0), // + U8(deep_elements_flags), // + B(Return) // + }, + 257, + {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE), + InstanceType::FIXED_ARRAY_TYPE}}, + }; + + for (size_t i = 0; i < arraysize(snippets); i++) { + Handle<BytecodeArray> bytecode_array = + helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); + CheckBytecodeArrayEqual(snippets[i], bytecode_array); + } +} + + TEST(TopLevelObjectLiterals) { InitializedHandleScope handle_scope; BytecodeGeneratorHelper helper; @@ -3393,7 +4059,7 @@ TEST(TopLevelObjectLiterals) { {"var a = { func: function() { } };", 5 * kPointerSize, 1, - 50, + 48, { B(LdaConstant), U8(0), // B(Star), R(1), // @@ -3404,12 +4070,10 @@ TEST(TopLevelObjectLiterals) { B(Star), R(1), // B(LdaZero), // B(Star), R(2), // - B(LdaConstant), U8(2), // - B(CreateObjectLiteral), U8(0), U8(has_function_flags), // + B(CreateObjectLiteral), U8(2), U8(0), U8(has_function_flags), // B(Star), R(4), // - B(LdaConstant), U8(4), // - B(CreateClosure), U8(1), // - B(StoreICSloppy), R(4), U8(3), U8(5), // + B(CreateClosure), U8(3), U8(1), // + B(StoreICSloppy), R(4), U8(4), U8(3), // B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1), // B(Ldar), R(4), // B(Star), R(3), // @@ -3421,8 +4085,8 @@ TEST(TopLevelObjectLiterals) { {InstanceType::FIXED_ARRAY_TYPE, InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, InstanceType::FIXED_ARRAY_TYPE, - InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, - InstanceType::SHARED_FUNCTION_INFO_TYPE}}, + InstanceType::SHARED_FUNCTION_INFO_TYPE, + InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, }; for (size_t i = 0; i < arraysize(snippets); i++) { @@ -3532,11 +4196,10 @@ TEST(Throw) { {"var a = 1; if (a) { throw 'Error'; };", 1 * kPointerSize, 1, - 13, + 11, { B(LdaSmi8), U8(1), // B(Star), R(0), // - B(Ldar), R(0), // B(JumpIfToBooleanFalse), U8(5), // B(LdaConstant), U8(0), // B(Throw), // @@ -3637,20 +4300,34 @@ TEST(CallNew) { TEST(ContextVariables) { InitializedHandleScope handle_scope; BytecodeGeneratorHelper helper; + Zone zone; + + FeedbackVectorSpec feedback_spec(&zone); + FeedbackVectorSlot slot = feedback_spec.AddCallICSlot(); + + Handle<i::TypeFeedbackVector> vector = + i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); int closure = Register::function_closure().index(); + int new_target = Register::new_target().index(); 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[] = { {"var a; return function() { a = 1; };", 1 * kPointerSize, 1, - 12, + 11, { B(CallRuntime), U16(Runtime::kNewFunctionContext), // R(closure), U8(1), // B(PushContext), R(0), // - B(LdaConstant), U8(0), // - B(CreateClosure), U8(0), // + B(CreateClosure), U8(0), U8(0), // B(Return), // }, 1, @@ -3658,15 +4335,14 @@ TEST(ContextVariables) { {"var a = 1; return function() { a = 2; };", 1 * kPointerSize, 1, - 17, + 16, { B(CallRuntime), U16(Runtime::kNewFunctionContext), // R(closure), U8(1), // B(PushContext), R(0), // B(LdaSmi8), U8(1), // B(StaContextSlot), R(0), U8(first_context_slot), // - B(LdaConstant), U8(0), // - B(CreateClosure), U8(0), // + B(CreateClosure), U8(0), U8(0), // B(Return), // }, 1, @@ -3674,7 +4350,7 @@ TEST(ContextVariables) { {"var a = 1; var b = 2; return function() { a = 2; b = 3 };", 1 * kPointerSize, 1, - 22, + 21, { B(CallRuntime), U16(Runtime::kNewFunctionContext), // R(closure), U8(1), // @@ -3683,8 +4359,7 @@ TEST(ContextVariables) { B(StaContextSlot), R(0), U8(first_context_slot), // B(LdaSmi8), U8(2), // B(StaContextSlot), R(0), U8(first_context_slot + 1), // - B(LdaConstant), U8(0), // - B(CreateClosure), U8(0), // + B(CreateClosure), U8(0), U8(0), // B(Return), // }, 1, @@ -3694,24 +4369,23 @@ TEST(ContextVariables) { 1, 24, { - B(CallRuntime), U16(Runtime::kNewFunctionContext), // - R(closure), U8(1), // - B(PushContext), R(0), // - B(LdaUndefined), // - B(Star), R(2), // - B(LdaConstant), U8(0), // - B(CreateClosure), U8(0), // - B(Star), R(1), // - B(Call), R(1), R(2), U8(0), // - B(LdaContextSlot), R(0), U8(first_context_slot), // - B(Return), // + B(CallRuntime), U16(Runtime::kNewFunctionContext), // + R(closure), U8(1), // + B(PushContext), R(0), // + B(LdaUndefined), // + B(Star), R(2), // + B(CreateClosure), U8(0), U8(0), // + B(Star), R(1), // + B(Call), R(1), R(2), U8(0), U8(vector->GetIndex(slot)), // + B(LdaContextSlot), R(0), U8(first_context_slot), // + B(Return), // }, 1, {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, {"'use strict'; let a = 1; { let b = 2; return function() { a + b; }; }", 4 * kPointerSize, 1, - 45, + 44, { B(CallRuntime), U16(Runtime::kNewFunctionContext), // R(closure), U8(1), // @@ -3730,13 +4404,45 @@ TEST(ContextVariables) { B(StaContextSlot), R(1), U8(first_context_slot), // B(LdaSmi8), U8(2), // B(StaContextSlot), R(1), U8(first_context_slot), // - B(LdaConstant), U8(1), // - B(CreateClosure), U8(0), // + B(CreateClosure), U8(1), U8(0), // B(Return), // }, 2, {InstanceType::FIXED_ARRAY_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++) { @@ -3758,15 +4464,14 @@ TEST(ContextParameters) { {"function f(arg1) { return function() { arg1 = 2; }; }", 1 * kPointerSize, 2, - 17, + 16, { B(CallRuntime), U16(Runtime::kNewFunctionContext), // R(closure), U8(1), // B(PushContext), R(0), // B(Ldar), R(helper.kLastParamIndex), // B(StaContextSlot), R(0), U8(first_context_slot), // - B(LdaConstant), U8(0), // - B(CreateClosure), U8(0), // + B(CreateClosure), U8(0), U8(0), // B(Return), // }, 1, @@ -3774,15 +4479,14 @@ TEST(ContextParameters) { {"function f(arg1) { var a = function() { arg1 = 2; }; return arg1; }", 2 * kPointerSize, 2, - 22, + 21, { B(CallRuntime), U16(Runtime::kNewFunctionContext), // R(closure), U8(1), // B(PushContext), R(1), // B(Ldar), R(helper.kLastParamIndex), // B(StaContextSlot), R(1), U8(first_context_slot), // - B(LdaConstant), U8(0), // - B(CreateClosure), U8(0), // + B(CreateClosure), U8(0), U8(0), // B(Star), R(0), // B(LdaContextSlot), R(1), U8(first_context_slot), // B(Return), // @@ -3792,7 +4496,7 @@ TEST(ContextParameters) { {"function f(a1, a2, a3, a4) { return function() { a1 = a3; }; }", 1 * kPointerSize, 5, - 22, + 21, { B(CallRuntime), U16(Runtime::kNewFunctionContext), // R(closure), U8(1), // @@ -3801,8 +4505,7 @@ TEST(ContextParameters) { B(StaContextSlot), R(0), U8(first_context_slot + 1), // B(Ldar), R(helper.kLastParamIndex -1), // B(StaContextSlot), R(0), U8(first_context_slot), // - B(LdaConstant), U8(0), // - B(CreateClosure), U8(0), // + B(CreateClosure), U8(0), U8(0), // B(Return), // }, 1, @@ -3810,15 +4513,14 @@ TEST(ContextParameters) { {"function f() { var self = this; return function() { self = 2; }; }", 1 * kPointerSize, 1, - 17, + 16, { B(CallRuntime), U16(Runtime::kNewFunctionContext), // R(closure), U8(1), // B(PushContext), R(0), // B(Ldar), R(helper.kLastParamIndex), // B(StaContextSlot), R(0), U8(first_context_slot), // - B(LdaConstant), U8(0), // - B(CreateClosure), U8(0), // + B(CreateClosure), U8(0), U8(0), // B(Return), // }, 1, @@ -3924,11 +4626,10 @@ TEST(CountOperators) { {"var a = 1; return ++a;", 1 * kPointerSize, 1, - 11, + 9, { B(LdaSmi8), U8(1), // B(Star), R(0), // - B(Ldar), R(0), // B(ToNumber), // B(Inc), // B(Star), R(0), // @@ -3937,11 +4638,10 @@ TEST(CountOperators) { {"var a = 1; return a++;", 2 * kPointerSize, 1, - 15, + 13, { B(LdaSmi8), U8(1), // B(Star), R(0), // - B(Ldar), R(0), // B(ToNumber), // B(Star), R(1), // B(Inc), // @@ -3952,11 +4652,10 @@ TEST(CountOperators) { {"var a = 1; return --a;", 1 * kPointerSize, 1, - 11, + 9, { B(LdaSmi8), U8(1), // B(Star), R(0), // - B(Ldar), R(0), // B(ToNumber), // B(Dec), // B(Star), R(0), // @@ -3965,11 +4664,10 @@ TEST(CountOperators) { {"var a = 1; return a--;", 2 * kPointerSize, 1, - 15, + 13, { B(LdaSmi8), U8(1), // B(Star), R(0), // - B(Ldar), R(0), // B(ToNumber), // B(Star), R(1), // B(Dec), // @@ -3978,80 +4676,80 @@ TEST(CountOperators) { B(Return), // }}, {"var a = { val: 1 }; return a.val++;", - 2 * kPointerSize, + 3 * kPointerSize, 1, - 22, + 23, { - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(object_literal_flags), // - B(Star), R(0), // - B(LoadICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), // - B(ToNumber), // - B(Star), R(1), // - B(Inc), // - B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot2)), // - B(Ldar), R(1), // - B(Return), // + B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), // + B(Star), R(0), // + B(Star), R(1), // + B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), // + B(ToNumber), // + B(Star), R(2), // + B(Inc), // + B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)), // + B(Ldar), R(2), // + B(Return), // }, 2, {InstanceType::FIXED_ARRAY_TYPE, InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, {"var a = { val: 1 }; return --a.val;", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 18, + 19, { - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(object_literal_flags), // - B(Star), R(0), // - B(LoadICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), // - B(ToNumber), // - B(Dec), // - B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot2)), // - B(Return), // + B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), // + B(Star), R(0), // + B(Star), R(1), // + B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), // + B(ToNumber), // + B(Dec), // + B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)), // + B(Return), // }, 2, {InstanceType::FIXED_ARRAY_TYPE, InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, {"var name = 'var'; var a = { val: 1 }; return a[name]--;", - 4 * kPointerSize, + 5 * kPointerSize, 1, - 29, + 30, { B(LdaConstant), U8(0), // B(Star), R(0), // - B(LdaConstant), U8(1), // - B(CreateObjectLiteral), U8(0), U8(object_literal_flags), // + B(CreateObjectLiteral), U8(1), U8(0), U8(object_literal_flags), // B(Star), R(1), // - B(Ldar), R(0), // B(Star), R(2), // - B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot1)), // - B(ToNumber), // + B(Ldar), R(0), // B(Star), R(3), // + B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot1)), // + B(ToNumber), // + B(Star), R(4), // B(Dec), // - B(KeyedStoreICSloppy), R(1), R(2), U8(vector->GetIndex(slot2)), // - B(Ldar), R(3), // + B(KeyedStoreICSloppy), R(2), R(3), U8(vector->GetIndex(slot2)), // + B(Ldar), R(4), // B(Return), // }, 2, {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, InstanceType::FIXED_ARRAY_TYPE}}, {"var name = 'var'; var a = { val: 1 }; return ++a[name];", - 3 * kPointerSize, + 4 * kPointerSize, 1, - 25, + 26, { B(LdaConstant), U8(0), // B(Star), R(0), // - B(LdaConstant), U8(1), // - B(CreateObjectLiteral), U8(0), U8(object_literal_flags), // + B(CreateObjectLiteral), U8(1), U8(0), U8(object_literal_flags), // B(Star), R(1), // - B(Ldar), R(0), // B(Star), R(2), // - B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot1)), // + B(Ldar), R(0), // + B(Star), R(3), // + B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot1)), // B(ToNumber), // B(Inc), // - B(KeyedStoreICSloppy), R(1), R(2), U8(vector->GetIndex(slot2)), // + B(KeyedStoreICSloppy), R(2), R(3), U8(vector->GetIndex(slot2)), // B(Return), // }, 2, @@ -4060,15 +4758,14 @@ TEST(CountOperators) { {"var a = 1; var b = function() { return a }; return ++a;", 2 * kPointerSize, 1, - 27, + 26, { B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // U8(1), // B(PushContext), R(1), // B(LdaSmi8), U8(1), // B(StaContextSlot), R(1), U8(first_context_slot), // - B(LdaConstant), U8(0), // - B(CreateClosure), U8(0), // + B(CreateClosure), U8(0), U8(0), // B(Star), R(0), // B(LdaContextSlot), R(1), U8(first_context_slot), // B(ToNumber), // @@ -4081,15 +4778,14 @@ TEST(CountOperators) { {"var a = 1; var b = function() { return a }; return a--;", 3 * kPointerSize, 1, - 31, + 30, { B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // U8(1), // B(PushContext), R(1), // B(LdaSmi8), U8(1), // B(StaContextSlot), R(1), U8(first_context_slot), // - B(LdaConstant), U8(0), // - B(CreateClosure), U8(0), // + B(CreateClosure), U8(0), U8(0), // B(Star), R(0), // B(LdaContextSlot), R(1), U8(first_context_slot), // B(ToNumber), // @@ -4102,22 +4798,22 @@ TEST(CountOperators) { 1, {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, {"var idx = 1; var a = [1, 2]; return a[idx++] = 2;", - 3 * kPointerSize, + 4 * kPointerSize, 1, - 26, + 27, { B(LdaSmi8), U8(1), // B(Star), R(0), // - B(LdaConstant), U8(0), // - B(CreateArrayLiteral), U8(0), U8(array_literal_flags), // + B(CreateArrayLiteral), U8(0), U8(0), U8(array_literal_flags), // B(Star), R(1), // + B(Star), R(2), // B(Ldar), R(0), // B(ToNumber), // - B(Star), R(2), // + B(Star), R(3), // B(Inc), // B(Star), R(0), // B(LdaSmi8), U8(2), // - B(KeyedStoreICSloppy), R(1), R(2), // + B(KeyedStoreICSloppy), R(2), R(3), // U8(store_vector->GetIndex(store_slot)), // B(Return), // }, @@ -4232,65 +4928,67 @@ TEST(CompoundExpressions) { ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos; ExpectedSnippet<InstanceType> snippets[] = { {"var a = 1; a += 2;", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 12, + 14, { B(LdaSmi8), U8(1), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(2), // - B(Add), R(0), // + B(Add), R(1), // B(Star), R(0), // B(LdaUndefined), // B(Return), // }}, {"var a = 1; a /= 2;", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 12, + 14, { B(LdaSmi8), U8(1), // B(Star), R(0), // + B(Star), R(1), // B(LdaSmi8), U8(2), // - B(Div), R(0), // + B(Div), R(1), // B(Star), R(0), // B(LdaUndefined), // B(Return), // }}, {"var a = { val: 2 }; a.name *= 2;", - 2 * kPointerSize, + 3 * kPointerSize, 1, - 23, + 24, { - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(object_literal_flags), // - B(Star), R(0), // - B(LoadICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), // - B(Star), R(1), // - B(LdaSmi8), U8(2), // - B(Mul), R(1), // - B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot2)), // - B(LdaUndefined), // - B(Return), // + B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), // + B(Star), R(0), // + B(Star), R(1), // + B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), // + B(Star), R(2), // + B(LdaSmi8), U8(2), // + B(Mul), R(2), // + B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)), // + B(LdaUndefined), // + B(Return), // }, 2, {InstanceType::FIXED_ARRAY_TYPE, InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, {"var a = { 1: 2 }; a[1] ^= 2;", - 3 * kPointerSize, + 4 * kPointerSize, 1, - 26, + 27, { - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(object_literal_flags), // + B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), // B(Star), R(0), // - B(LdaSmi8), U8(1), // B(Star), R(1), // - B(KeyedLoadICSloppy), R(0), U8(vector->GetIndex(slot1)), // + B(LdaSmi8), U8(1), // B(Star), R(2), // + B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot1)), // + B(Star), R(3), // B(LdaSmi8), U8(2), // - B(BitwiseXor), R(2), // - B(KeyedStoreICSloppy), R(0), R(1), U8(vector->GetIndex(slot2)), // + B(BitwiseXor), R(3), // + B(KeyedStoreICSloppy), R(1), R(2), U8(vector->GetIndex(slot2)), // B(LdaUndefined), // B(Return), // }, @@ -4299,15 +4997,14 @@ TEST(CompoundExpressions) { {"var a = 1; (function f() { return a; }); a |= 24;", 2 * kPointerSize, 1, - 30, + 29, { B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // U8(1), // B(PushContext), R(0), // B(LdaSmi8), U8(1), // B(StaContextSlot), R(0), U8(first_context_slot), // - B(LdaConstant), U8(0), // - B(CreateClosure), U8(0), // + B(CreateClosure), U8(0), U8(0), // B(LdaContextSlot), R(0), U8(first_context_slot), // B(Star), R(1), // B(LdaSmi8), U8(24), // @@ -4397,38 +5094,37 @@ TEST(CreateArguments) { {"function f() { return arguments; }", 1 * kPointerSize, 1, - 6, + 4, { B(CreateMappedArguments), // B(Star), R(0), // - B(Ldar), R(0), // B(Return), // }}, {"function f() { return arguments[0]; }", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 8, + 10, { B(CreateMappedArguments), // B(Star), R(0), // + B(Star), R(1), // B(LdaZero), // - B(KeyedLoadICSloppy), R(0), U8(vector->GetIndex(slot)), // + B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot)), // B(Return), // }}, {"function f() { 'use strict'; return arguments; }", 1 * kPointerSize, 1, - 6, + 4, { B(CreateUnmappedArguments), // B(Star), R(0), // - B(Ldar), R(0), // B(Return), // }}, {"function f(a) { return arguments[0]; }", - 2 * kPointerSize, + 3 * kPointerSize, 2, - 20, + 22, { B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // U8(1), // @@ -4437,14 +5133,15 @@ TEST(CreateArguments) { B(StaContextSlot), R(1), U8(first_context_slot), // B(CreateMappedArguments), // B(Star), R(0), // + B(Star), R(2), // B(LdaZero), // - B(KeyedLoadICSloppy), R(0), U8(vector->GetIndex(slot)), // + B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot)), // B(Return), // }}, {"function f(a, b, c) { return arguments; }", 2 * kPointerSize, 4, - 28, + 26, { B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // U8(1), // @@ -4457,17 +5154,15 @@ TEST(CreateArguments) { B(StaContextSlot), R(1), U8(first_context_slot), // B(CreateMappedArguments), // B(Star), R(0), // - B(Ldar), R(0), // B(Return), // }}, {"function f(a, b, c) { 'use strict'; return arguments; }", 1 * kPointerSize, 4, - 6, + 4, { B(CreateUnmappedArguments), // B(Star), R(0), // - B(Ldar), R(0), // B(Return), // }}, }; @@ -4484,21 +5179,25 @@ TEST(IllegalRedeclaration) { InitializedHandleScope handle_scope; BytecodeGeneratorHelper helper; - ExpectedSnippet<const char*> snippets[] = { + CHECK_GE(MessageTemplate::kVarRedeclaration, 128); + // Must adapt bytecode if this changes. + + ExpectedSnippet<Handle<Object>, 2> snippets[] = { {"const a = 1; { var a = 2; }", 3 * kPointerSize, 1, 14, { - B(LdaSmi8), U8(MessageTemplate::kVarRedeclaration), // - B(Star), R(1), // B(LdaConstant), U8(0), // + B(Star), R(1), // + B(LdaConstant), U8(1), // B(Star), R(2), // B(CallRuntime), U16(Runtime::kNewSyntaxError), R(1), U8(2), // B(Throw), // }, - 1, - {"a"}}, + 2, + {helper.factory()->NewNumberFromInt(MessageTemplate::kVarRedeclaration), + helper.factory()->NewStringFromAsciiChecked("a")}}, }; for (size_t i = 0; i < arraysize(snippets); i++) { @@ -4540,77 +5239,76 @@ TEST(ForIn) { 2, {B(LdaUndefined), B(Return)}, 0}, + {"for (var p in undefined) {}", + 2 * kPointerSize, + 1, + 2, + {B(LdaUndefined), B(Return)}, + 0}, {"var x = 'potatoes';\n" "for (var p in x) { return p; }", - 5 * kPointerSize, + 8 * kPointerSize, 1, - 52, + 45, { - B(LdaConstant), U8(0), // - B(Star), R(1), // - B(Ldar), R(1), // - B(JumpIfUndefined), U8(44), // - B(JumpIfNull), U8(42), // - B(ToObject), // - B(Star), R(3), // - B(CallRuntime), U16(Runtime::kGetPropertyNamesFast), R(3), U8(1), // - B(ForInPrepare), R(3), // - B(JumpIfUndefined), U8(30), // - B(Star), R(4), // - B(LdaZero), // - B(Star), R(3), // - B(ForInDone), R(4), // - B(JumpIfTrue), U8(21), // - B(ForInNext), R(4), R(3), // - B(JumpIfUndefined), U8(11), // - B(Star), R(0), // - B(Ldar), R(0), // - B(Star), R(2), // - B(Ldar), R(2), // - B(Return), // - B(Ldar), R(3), // - B(Inc), // - B(Jump), U8(-23), // - B(LdaUndefined), // - B(Return), // + B(LdaConstant), U8(0), // + B(Star), R(1), // + B(JumpIfUndefined), U8(39), // + B(JumpIfNull), U8(37), // + B(ToObject), // + B(JumpIfNull), U8(34), // + B(Star), R(3), // + B(ForInPrepare), R(4), R(5), R(6), // + B(LdaZero), // + B(Star), R(7), // + B(ForInDone), R(7), R(6), // + B(JumpIfTrue), U8(20), // + B(ForInNext), R(3), R(4), R(5), R(7), // + B(JumpIfUndefined), U8(7), // + B(Star), R(0), // + B(Star), R(2), // + B(Return), // + B(ForInStep), R(7), // + B(Star), R(7), // + B(Jump), U8(-21), // + B(LdaUndefined), // + B(Return), // }, 1, {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, {"var x = 0;\n" "for (var p in [1,2,3]) { x += p; }", - 5 * kPointerSize, + 9 * kPointerSize, 1, 57, { - B(LdaZero), // - B(Star), R(1), // - B(LdaConstant), U8(0), // - B(CreateArrayLiteral), U8(0), U8(simple_flags), // - B(JumpIfUndefined), U8(47), // - B(JumpIfNull), U8(45), // - B(ToObject), // - B(Star), R(3), // - B(CallRuntime), U16(Runtime::kGetPropertyNamesFast), R(3), U8(1), // - B(ForInPrepare), R(3), // - B(JumpIfUndefined), U8(33), // - B(Star), R(4), // - B(LdaZero), // - B(Star), R(3), // - B(ForInDone), R(4), // - B(JumpIfTrue), U8(24), // - B(ForInNext), R(4), R(3), // - B(JumpIfUndefined), U8(14), // - B(Star), R(0), // - B(Ldar), R(0), // - B(Star), R(2), // - B(Ldar), R(2), // - B(Add), R(1), // - B(Star), R(1), // - B(Ldar), R(3), // - B(Inc), // - B(Jump), U8(-26), // - B(LdaUndefined), // - B(Return), // + B(LdaZero), // + B(Star), R(1), // + B(CreateArrayLiteral), U8(0), U8(0), U8(3), // + B(JumpIfUndefined), U8(48), // + B(JumpIfNull), U8(46), // + B(ToObject), // + B(JumpIfNull), U8(43), // + B(Star), R(3), // + B(ForInPrepare), R(4), R(5), R(6), // + B(LdaZero), // + B(Star), R(7), // + B(ForInDone), R(7), R(6), // + B(JumpIfTrue), U8(29), // + B(ForInNext), R(3), R(4), R(5), R(7), // + B(JumpIfUndefined), U8(16), // + B(Star), R(0), // + B(Star), R(2), // + B(Ldar), R(1), // + B(Star), R(8), // + B(Ldar), R(2), // + B(Add), R(8), // + B(Star), R(1), // + B(ForInStep), R(7), // + B(Star), R(7), // + B(Jump), U8(-30), // + B(LdaUndefined), // + B(Return), // }, 1, {InstanceType::FIXED_ARRAY_TYPE}}, @@ -4619,90 +5317,93 @@ TEST(ForIn) { " if (x['a'] == 10) continue;\n" " if (x['a'] == 20) break;\n" "}", - 4 * kPointerSize, + 8 * kPointerSize, 1, - 83, + 94, { - B(LdaConstant), U8(0), // - B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // - B(Star), R(0), // - B(LdaConstant), U8(1), // - B(CreateArrayLiteral), U8(1), U8(simple_flags), // - B(JumpIfUndefined), U8(69), // - B(JumpIfNull), U8(67), // - B(ToObject), // - B(Star), R(1), // - B(CallRuntime), U16(Runtime::kGetPropertyNamesFast), R(1), U8(1), // - B(ForInPrepare), R(1), // - B(JumpIfUndefined), U8(55), // - B(Star), R(2), // - B(LdaZero), // - B(Star), R(1), // - B(ForInDone), R(2), // - B(JumpIfTrue), U8(46), // - B(ForInNext), R(2), R(1), // - B(JumpIfUndefined), U8(36), // - B(Star), R(3), // - B(StoreICSloppy), R(0), U8(2), U8(vector->GetIndex(slot4)), // - B(LoadICSloppy), R(0), U8(2), U8(vector->GetIndex(slot2)), // - B(Star), R(3), // - B(LdaSmi8), U8(10), // - B(TestEqual), R(3), // - B(JumpIfFalse), U8(4), // - B(Jump), U8(16), // - B(LoadICSloppy), R(0), U8(2), U8(vector->GetIndex(slot3)), // - B(Star), R(3), // - B(LdaSmi8), U8(20), // - B(TestEqual), R(3), // - B(JumpIfFalse), U8(4), // - B(Jump), U8(7), // - B(Ldar), R(1), // - B(Inc), // - B(Jump), U8(-48), // - B(LdaUndefined), // - B(Return), // + B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // + B(Star), R(0), // + B(CreateArrayLiteral), U8(1), U8(1), U8(simple_flags), // + B(JumpIfUndefined), U8(82), // + B(JumpIfNull), U8(80), // + B(ToObject), // + B(JumpIfNull), U8(77), // + B(Star), R(1), // + B(ForInPrepare), R(2), R(3), R(4), // + B(LdaZero), // + B(Star), R(5), // + B(ForInDone), R(5), R(4), // + B(JumpIfTrue), U8(63), // + B(ForInNext), R(1), R(2), R(3), R(5), // + B(JumpIfUndefined), U8(50), // + B(Star), R(6), // + B(Ldar), R(0), // + B(Star), R(7), // + B(Ldar), R(6), // + B(StoreICSloppy), R(7), U8(2), U8(vector->GetIndex(slot4)), // + B(Ldar), R(0), // + B(Star), R(6), // + B(LoadICSloppy), R(6), U8(2), U8(vector->GetIndex(slot2)), // + B(Star), R(7), // + B(LdaSmi8), U8(10), // + B(TestEqual), R(7), // + B(JumpIfFalse), U8(4), // + B(Jump), U8(20), // + B(Ldar), R(0), // + B(Star), R(6), // + B(LoadICSloppy), R(6), U8(2), U8(vector->GetIndex(slot3)), // + B(Star), R(7), // + B(LdaSmi8), U8(20), // + B(TestEqual), R(7), // + B(JumpIfFalse), U8(4), // + B(Jump), U8(8), // + B(ForInStep), R(5), // + B(Star), R(5), // + B(Jump), U8(-64), // + B(LdaUndefined), // + B(Return), // }, 3, {InstanceType::FIXED_ARRAY_TYPE, InstanceType::FIXED_ARRAY_TYPE, InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, {"var x = [ 10, 11, 12 ] ;\n" "for (x[0] in [1,2,3]) { return x[3]; }", - 5 * kPointerSize, + 9 * kPointerSize, 1, - 66, + 71, { - B(LdaConstant), U8(0), // - B(CreateArrayLiteral), U8(0), U8(simple_flags), // - B(Star), R(0), // - B(LdaConstant), U8(1), // - B(CreateArrayLiteral), U8(1), U8(simple_flags), // - B(JumpIfUndefined), U8(52), // - B(JumpIfNull), U8(50), // - B(ToObject), // - B(Star), R(1), // - B(CallRuntime), U16(Runtime::kGetPropertyNamesFast), R(1), U8(1), // - B(ForInPrepare), R(1), // - B(JumpIfUndefined), U8(38), // - B(Star), R(2), // - B(LdaZero), // - B(Star), R(1), // - B(ForInDone), R(2), // - B(JumpIfTrue), U8(29), // - B(ForInNext), R(2), R(1), // - B(JumpIfUndefined), U8(19), // - B(Star), R(3), // - B(LdaZero), // - B(Star), R(4), // - B(Ldar), R(3), // - B(KeyedStoreICSloppy), R(0), R(4), U8(vector->GetIndex(slot3)), // - B(LdaSmi8), U8(3), // - B(KeyedLoadICSloppy), R(0), U8(vector->GetIndex(slot2)), // - B(Return), // - B(Ldar), R(1), // - B(Inc), // - B(Jump), U8(-31), // - B(LdaUndefined), // - B(Return), // + B(CreateArrayLiteral), U8(0), U8(0), U8(simple_flags), // + B(Star), R(0), // + B(CreateArrayLiteral), U8(1), U8(1), U8(simple_flags), // + B(JumpIfUndefined), U8(59), // + B(JumpIfNull), U8(57), // + B(ToObject), // + B(JumpIfNull), U8(54), // + B(Star), R(1), // + B(ForInPrepare), R(2), R(3), R(4), // + B(LdaZero), // + B(Star), R(5), // + B(ForInDone), R(5), R(4), // + B(JumpIfTrue), U8(40), // + B(ForInNext), R(1), R(2), R(3), R(5), // + B(JumpIfUndefined), U8(27), // + B(Star), R(6), // + B(Ldar), R(0), // + B(Star), R(7), // + B(LdaZero), // + B(Star), R(8), // + B(Ldar), R(6), // + B(KeyedStoreICSloppy), R(7), R(8), U8(vector->GetIndex(slot3)), // + B(Ldar), R(0), // + B(Star), R(6), // + B(LdaSmi8), U8(3), // + B(KeyedLoadICSloppy), R(6), U8(vector->GetIndex(slot2)), // + B(Return), // + B(ForInStep), R(5), // + B(Star), R(5), // + B(Jump), U8(-41), // + B(LdaUndefined), // + B(Return), // }, 2, {InstanceType::FIXED_ARRAY_TYPE, InstanceType::FIXED_ARRAY_TYPE}}, @@ -4769,19 +5470,19 @@ TEST(Switch) { " case 1: return 2;\n" " case 2: return 3;\n" "}\n", - 2 * kPointerSize, + 3 * kPointerSize, 1, 30, { B(LdaSmi8), U8(1), // B(Star), R(1), // The tag variable is allocated as a - B(Ldar), R(1), // local by the parser, hence this - B(Star), R(0), // strange shuffling. + B(Star), R(0), // local by the parser, hence the store + B(Star), R(2), // to another local register. B(LdaSmi8), U8(1), // - B(TestEqualStrict), R(0), // + B(TestEqualStrict), R(2), // B(JumpIfTrue), U8(10), // B(LdaSmi8), U8(2), // - B(TestEqualStrict), R(0), // + B(TestEqualStrict), R(2), // B(JumpIfTrue), U8(7), // B(Jump), U8(8), // B(LdaSmi8), U8(2), // @@ -4796,19 +5497,19 @@ TEST(Switch) { " case 1: a = 2; break;\n" " case 2: a = 3; break;\n" "}\n", - 2 * kPointerSize, + 3 * kPointerSize, 1, 36, { B(LdaSmi8), U8(1), // B(Star), R(1), // - B(Ldar), R(1), // B(Star), R(0), // + B(Star), R(2), // B(LdaSmi8), U8(1), // - B(TestEqualStrict), R(0), // + B(TestEqualStrict), R(2), // B(JumpIfTrue), U8(10), // B(LdaSmi8), U8(2), // - B(TestEqualStrict), R(0), // + B(TestEqualStrict), R(2), // B(JumpIfTrue), U8(10), // B(Jump), U8(14), // B(LdaSmi8), U8(2), // @@ -4825,19 +5526,19 @@ TEST(Switch) { " case 1: a = 2; // fall-through\n" " case 2: a = 3; break;\n" "}\n", - 2 * kPointerSize, + 3 * kPointerSize, 1, 34, { B(LdaSmi8), U8(1), // B(Star), R(1), // - B(Ldar), R(1), // B(Star), R(0), // + B(Star), R(2), // B(LdaSmi8), U8(1), // - B(TestEqualStrict), R(0), // + B(TestEqualStrict), R(2), // B(JumpIfTrue), U8(10), // B(LdaSmi8), U8(2), // - B(TestEqualStrict), R(0), // + B(TestEqualStrict), R(2), // B(JumpIfTrue), U8(8), // B(Jump), U8(12), // B(LdaSmi8), U8(2), // @@ -4854,19 +5555,19 @@ TEST(Switch) { " case 3: break;\n" " default: a = 1; break;\n" "}\n", - 2 * kPointerSize, + 3 * kPointerSize, 1, 34, { B(LdaSmi8), U8(1), // B(Star), R(1), // - B(Ldar), R(1), // B(Star), R(0), // + B(Star), R(2), // B(LdaSmi8), U8(2), // - B(TestEqualStrict), R(0), // + B(TestEqualStrict), R(2), // B(JumpIfTrue), U8(10), // B(LdaSmi8), U8(3), // - B(TestEqualStrict), R(0), // + B(TestEqualStrict), R(2), // B(JumpIfTrue), U8(6), // B(Jump), U8(6), // B(Jump), U8(10), // @@ -4883,20 +5584,20 @@ TEST(Switch) { " case 3: a = 2; break;\n" " default: a = 3; break;\n" "}\n", - 2 * kPointerSize, + 3 * kPointerSize, 1, 43, { B(LdaSmi8), U8(1), // B(Star), R(1), // - B(Ldar), R(1), // B(TypeOf), // B(Star), R(0), // + B(Star), R(2), // B(LdaSmi8), U8(2), // - B(TestEqualStrict), R(0), // + B(TestEqualStrict), R(2), // B(JumpIfTrue), U8(10), // B(LdaSmi8), U8(3), // - B(TestEqualStrict), R(0), // + B(TestEqualStrict), R(2), // B(JumpIfTrue), U8(10), // B(Jump), U8(14), // B(LdaSmi8), U8(1), // @@ -4916,17 +5617,17 @@ TEST(Switch) { " case typeof(a): a = 1; break;\n" " default: a = 2; break;\n" "}\n", - 2 * kPointerSize, + 3 * kPointerSize, 1, 31, { B(LdaSmi8), U8(1), // B(Star), R(1), // - B(Ldar), R(1), // B(Star), R(0), // + B(Star), R(2), // B(Ldar), R(1), // B(TypeOf), // - B(TestEqualStrict), R(0), // + B(TestEqualStrict), R(2), // B(JumpIfTrue), U8(4), // B(Jump), U8(8), // B(LdaSmi8), U8(1), // @@ -4944,24 +5645,24 @@ TEST(Switch) { "break;\n" " case 2: a = 3; break;" "}\n", - 2 * kPointerSize, + 3 * kPointerSize, 1, 288, { B(LdaSmi8), U8(1), // B(Star), R(1), // - B(Ldar), R(1), // B(Star), R(0), // + B(Star), R(2), // B(LdaSmi8), U8(1), // - B(TestEqualStrict), R(0), // + B(TestEqualStrict), R(2), // B(JumpIfTrue), U8(10), // B(LdaSmi8), U8(2), // - B(TestEqualStrict), R(0), // + B(TestEqualStrict), R(2), // B(JumpIfTrueConstant), U8(0), // B(JumpConstant), U8(1), // REPEAT_64(COMMA, // - B(LdaSmi8), U8(2), // - B(Star), R(1)), // + B(LdaSmi8), U8(2), // + B(Star), R(1)), // B(Jump), U8(8), // B(LdaSmi8), U8(3), // B(Star), R(1), // @@ -4980,26 +5681,29 @@ TEST(Switch) { " } // fall-through\n" " case 2: a = 3;\n" "}\n", - 3 * kPointerSize, + 5 * kPointerSize, 1, - 54, + 60, { B(LdaSmi8), U8(1), // B(Star), R(2), // - B(Ldar), R(2), // B(Star), R(0), // + B(Star), R(3), // B(LdaSmi8), U8(1), // - B(TestEqualStrict), R(0), // + B(TestEqualStrict), R(3), // B(JumpIfTrue), U8(10), // B(LdaSmi8), U8(2), // - B(TestEqualStrict), R(0), // - B(JumpIfTrue), U8(30), // - B(Jump), U8(32), // + B(TestEqualStrict), R(3), // + B(JumpIfTrue), U8(36), // + B(Jump), U8(38), // + B(Ldar), R(2), // + B(Star), R(4), // B(LdaSmi8), U8(1), // - B(Add), R(2), // + B(Add), R(4), // B(Star), R(1), // + B(Star), R(4), // B(LdaSmi8), U8(2), // - B(TestEqualStrict), R(1), // + B(TestEqualStrict), R(4), // B(JumpIfTrue), U8(4), // B(Jump), U8(8), // B(LdaSmi8), U8(1), // @@ -5027,20 +5731,21 @@ TEST(BasicBlockToBoolean) { InitializedHandleScope handle_scope; BytecodeGeneratorHelper helper; - // Check that we don't omit ToBoolean calls if they are at the start of basic + // Check that we generate JumpIfToBoolean if they are at the start of basic // blocks. ExpectedSnippet<int> snippets[] = { {"var a = 1; if (a || a < 0) { return 1; }", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 18, + 20, { B(LdaSmi8), U8(1), // B(Star), R(0), // + B(JumpIfToBooleanTrue), U8(9), // B(Ldar), R(0), // - B(JumpIfToBooleanTrue), U8(5), // + B(Star), R(1), // B(LdaZero), // - B(TestLessThan), R(0), // + B(TestLessThan), R(1), // B(JumpIfToBooleanFalse), U8(5), // B(LdaSmi8), U8(1), // B(Return), // @@ -5048,16 +5753,17 @@ TEST(BasicBlockToBoolean) { B(Return), // }}, {"var a = 1; if (a && a < 0) { return 1; }", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 18, + 20, { B(LdaSmi8), U8(1), // B(Star), R(0), // + B(JumpIfToBooleanFalse), U8(9), // B(Ldar), R(0), // - B(JumpIfToBooleanFalse), U8(5), // + B(Star), R(1), // B(LdaZero), // - B(TestLessThan), R(0), // + B(TestLessThan), R(1), // B(JumpIfToBooleanFalse), U8(5), // B(LdaSmi8), U8(1), // B(Return), // @@ -5065,16 +5771,17 @@ TEST(BasicBlockToBoolean) { B(Return), // }}, {"var a = 1; a = (a || a < 0) ? 2 : 3;", - 1 * kPointerSize, + 2 * kPointerSize, 1, - 23, + 25, { B(LdaSmi8), U8(1), // B(Star), R(0), // + B(JumpIfToBooleanTrue), U8(9), // B(Ldar), R(0), // - B(JumpIfToBooleanTrue), U8(5), // + B(Star), R(1), // B(LdaZero), // - B(TestLessThan), R(0), // + B(TestLessThan), R(1), // B(JumpIfToBooleanFalse), U8(6), // B(LdaSmi8), U8(2), // B(Jump), U8(4), // @@ -5127,11 +5834,10 @@ TEST(DeadCodeRemoval) { {"var a = 1; if (a) { return 1; }; return 2;", 1 * kPointerSize, 1, - 14, + 12, { B(LdaSmi8), U8(1), // B(Star), R(0), // - B(Ldar), R(0), // B(JumpIfToBooleanFalse), U8(5), // B(LdaSmi8), U8(1), // B(Return), // @@ -5170,13 +5876,12 @@ TEST(ThisFunction) { {"var f;\n f = function f() { return f; }", 1 * kPointerSize, 1, - 10, + 8, { B(LdaTheHole), // B(Star), R(0), // B(Ldar), R(closure), // B(Star), R(0), // - B(Ldar), R(0), // B(Return), // }}, }; @@ -5193,17 +5898,27 @@ TEST(NewTarget) { InitializedHandleScope handle_scope; BytecodeGeneratorHelper helper; + int new_target = Register::new_target().index(); + ExpectedSnippet<int> snippets[] = { {"return new.target;", 1 * kPointerSize, 1, - 10, + 5, { - B(CallRuntime), U16(Runtime::kGetOriginalConstructor), R(0), // - U8(0), // - B(Star), R(0), // - B(Ldar), R(0), // - B(Return), // + B(Ldar), R(new_target), // + B(Star), R(0), // + B(Return), // + }}, + {"new.target;", + 1 * kPointerSize, + 1, + 6, + { + B(Ldar), R(new_target), // + B(Star), R(0), // + B(LdaUndefined), // + B(Return), // }}, }; @@ -5214,6 +5929,799 @@ TEST(NewTarget) { } } + +TEST(RemoveRedundantLdar) { + InitializedHandleScope handle_scope; + BytecodeGeneratorHelper helper; + + ExpectedSnippet<int> snippets[] = { + {"var ld_a = 1;\n" // This test is to check Ldar does not + "while(true) {\n" // get removed if the preceding Star is + " ld_a = ld_a + ld_a;\n" // in a different basicblock. + " if (ld_a > 10) break;\n" + "}\n" + "return ld_a;", + 2 * kPointerSize, + 1, + 29, + {B(LdaSmi8), U8(1), // + B(Star), R(0), // + B(Ldar), R(0), // This load should not be removed as it + B(Star), R(1), // is the target of the branch. + B(Ldar), R(0), // + B(Add), R(1), // + B(Star), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(10), // + B(TestGreaterThan), R(1), // + B(JumpIfFalse), U8(4), // + B(Jump), U8(4), // + B(Jump), U8(-20), // + B(Ldar), R(0), // + B(Return)}}, + {"var ld_a = 1;\n" + "do {\n" + " ld_a = ld_a + ld_a;\n" + " if (ld_a > 10) continue;\n" + "} while(false);\n" + "return ld_a;", + 2 * kPointerSize, + 1, + 27, + {B(LdaSmi8), U8(1), // + B(Star), R(0), // + B(Ldar), R(0), // + B(Star), R(1), // + B(Ldar), R(0), // + B(Add), R(1), // + B(Star), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(10), // + B(TestGreaterThan), R(1), // + B(JumpIfFalse), U8(4), // + B(Jump), U8(2), // + B(Ldar), R(0), // + B(Return)}}, + {"var ld_a = 1;\n" + " ld_a = ld_a + ld_a;\n" + " return ld_a;", + 2 * kPointerSize, + 1, + 13, + { + B(LdaSmi8), U8(1), // + B(Star), R(0), // + B(Star), R(1), // + B(Ldar), R(0), // + B(Add), R(1), // + B(Star), R(0), // + B(Return) // + }}, + }; + + for (size_t i = 0; i < arraysize(snippets); i++) { + Handle<BytecodeArray> bytecode_array = + helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); + CheckBytecodeArrayEqual(snippets[i], bytecode_array); + } +} + + +TEST(AssignmentsInBinaryExpression) { + InitializedHandleScope handle_scope; + BytecodeGeneratorHelper helper; + + ExpectedSnippet<const char*> snippets[] = { + {"var x = 0, y = 1;\n" + "return (x = 2, y = 3, x = 4, y = 5)", + 2 * kPointerSize, + 1, + 24, + { + B(LdaZero), B(Star), R(0), // + B(LdaSmi8), U8(1), // + B(Star), R(1), // + B(LdaSmi8), U8(2), // + B(Star), R(0), // + B(LdaSmi8), U8(3), // + B(Star), R(1), // + B(LdaSmi8), U8(4), // + B(Star), R(0), // + B(LdaSmi8), U8(5), // + B(Star), R(1), // + B(Return), // + }, + 0}, + {"var x = 55;\n" + "var y = (x = 100);\n" + "return y", + 2 * kPointerSize, + 1, + 11, + { + B(LdaSmi8), U8(55), // + B(Star), R(0), // + B(LdaSmi8), U8(100), // + B(Star), R(0), // + B(Star), R(1), // + B(Return), // + }, + 0}, + {"var x = 55;\n" + "x = x + (x = 100) + (x = 101);\n" + "return x;", + 3 * kPointerSize, + 1, + 23, + { + B(LdaSmi8), U8(55), // + B(Star), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(100), // + B(Star), R(0), // + B(Add), R(1), // + B(Star), R(2), // + B(LdaSmi8), U8(101), // + B(Star), R(0), // + B(Add), R(2), // + B(Star), R(0), // + B(Return), // + }, + 0}, + {"var x = 55;\n" + "x = (x = 56) - x + (x = 57);\n" + "x++;\n" + "return x;", + 3 * kPointerSize, + 1, + 31, + { + B(LdaSmi8), U8(55), // + B(Star), R(0), // + B(LdaSmi8), U8(56), // + B(Star), R(0), // + B(Star), R(1), // + B(Ldar), R(0), // + B(Sub), R(1), // + B(Star), R(2), // + B(LdaSmi8), U8(57), // + B(Star), R(0), // + B(Add), R(2), // + B(Star), R(0), // + B(ToNumber), // + B(Star), R(1), // + B(Inc), // + B(Star), R(0), // + B(Return), // + }, + 0}, + {"var x = 55;\n" + "var y = x + (x = 1) + (x = 2) + (x = 3);\n" + "return y;", + 4 * kPointerSize, + 1, + 31, + { + B(LdaSmi8), U8(55), // + B(Star), R(0), // + B(Star), R(2), // + B(LdaSmi8), U8(1), // + B(Star), R(0), // + B(Add), R(2), // + B(Star), R(3), // + B(LdaSmi8), U8(2), // + B(Star), R(0), // + B(Add), R(3), // + B(Star), R(2), // + B(LdaSmi8), U8(3), // + B(Star), R(0), // + B(Add), R(2), // + B(Star), R(1), // + B(Return), // + }, + 0}, + {"var x = 55;\n" + "var x = x + (x = 1) + (x = 2) + (x = 3);\n" + "return x;", + 3 * kPointerSize, + 1, + 31, + { + B(LdaSmi8), U8(55), // + B(Star), R(0), // + B(Star), R(1), // + B(LdaSmi8), U8(1), // + B(Star), R(0), // + B(Add), R(1), // + B(Star), R(2), // + B(LdaSmi8), U8(2), // + B(Star), R(0), // + B(Add), R(2), // + B(Star), R(1), // + B(LdaSmi8), U8(3), // + B(Star), R(0), // + B(Add), R(1), // + B(Star), R(0), // + B(Return), // + }, + 0}, + {"var x = 10, y = 20;\n" + "return x + (x = 1) + (x + 1) * (y = 2) + (y = 3) + (x = 4) + (y = 5) + " + "y;\n", + 5 * kPointerSize, + 1, + 69, + { + B(LdaSmi8), U8(10), // + B(Star), R(0), // + B(LdaSmi8), U8(20), // + B(Star), R(1), // + B(Ldar), R(0), // + B(Star), R(2), // + B(LdaSmi8), U8(1), // + B(Star), R(0), // + B(Add), R(2), // + B(Star), R(3), // + B(Ldar), R(0), // + B(Star), R(2), // + B(LdaSmi8), U8(1), // + B(Add), R(2), // + B(Star), R(4), // + B(LdaSmi8), U8(2), // + B(Star), R(1), // + B(Mul), R(4), // + B(Add), R(3), // + B(Star), R(2), // + B(LdaSmi8), U8(3), // + B(Star), R(1), // + B(Add), R(2), // + B(Star), R(3), // + B(LdaSmi8), U8(4), // + B(Star), R(0), // + B(Add), R(3), // + B(Star), R(2), // + B(LdaSmi8), U8(5), // + B(Star), R(1), // + B(Add), R(2), // + B(Star), R(3), // + B(Ldar), R(1), // + B(Add), R(3), // + B(Return), // + }, + 0}, + {"var x = 17;\n" + "return 1 + x + (x++) + (++x);\n", + 4 * kPointerSize, + 1, + 37, + { + B(LdaSmi8), U8(17), // + B(Star), R(0), // + B(LdaSmi8), U8(1), // + B(Star), R(1), // + B(Ldar), R(0), // + B(Add), R(1), // + B(Star), R(2), // + B(Ldar), R(0), // + B(ToNumber), // + B(Star), R(1), // + B(Inc), // + B(Star), R(0), // + B(Ldar), R(1), // + B(Add), R(2), // + B(Star), R(3), // + B(Ldar), R(0), // + B(ToNumber), // + B(Inc), // + B(Star), R(0), // + B(Add), R(3), // + B(Return), // + }, + 0}}; + + for (size_t i = 0; i < arraysize(snippets); i++) { + Handle<BytecodeArray> bytecode_array = + helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); + CheckBytecodeArrayEqual(snippets[i], bytecode_array); + } +} + + +TEST(Eval) { + InitializedHandleScope handle_scope; + BytecodeGeneratorHelper helper; + Zone zone; + + int closure = Register::function_closure().index(); + int context = Register::function_context().index(); + int new_target = Register::new_target().index(); + + int first_context_slot = Context::MIN_CONTEXT_SLOTS; + + ExpectedSnippet<const char*> snippets[] = { + {"return eval('1;');", + 9 * kPointerSize, + 1, + 67, + { + 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(CreateMappedArguments), // + B(StaContextSlot), R(0), U8(first_context_slot + 1), // + B(Ldar), R(new_target), // + B(StaContextSlot), R(0), U8(first_context_slot + 2), // + B(Mov), R(context), R(3), // + B(LdaConstant), U8(0), // + B(Star), R(4), // + B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), // + R(3), U8(2), R(1), // + B(LdaConstant), U8(1), // + B(Star), R(3), // + B(Mov), R(1), R(4), // + B(Mov), R(3), R(5), // + B(Mov), R(closure), R(6), // + B(LdaZero), // + B(Star), R(7), // + B(LdaSmi8), U8(10), // + B(Star), R(8), // + B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // + U8(5), // + B(Star), R(1), // + B(Call), R(1), R(2), U8(1), U8(0), // + B(Return), // + }, + 2, + {"eval", "1;"}}, + }; + + for (size_t i = 0; i < arraysize(snippets); i++) { + Handle<BytecodeArray> bytecode_array = + helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); + CheckBytecodeArrayEqual(snippets[i], bytecode_array); + } +} + + +TEST(LookupSlot) { + InitializedHandleScope handle_scope; + BytecodeGeneratorHelper helper; + + int closure = Register::function_closure().index(); + int first_context_slot = Context::MIN_CONTEXT_SLOTS; + int context = Register::function_context().index(); + int new_target = Register::new_target().index(); + + ExpectedSnippet<const char*> snippets[] = { + {"eval('var x = 10;'); return x;", + 9 * kPointerSize, + 1, + 69, + { + 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(CreateMappedArguments), // + B(StaContextSlot), R(0), U8(first_context_slot + 1), // + B(Ldar), R(new_target), // + B(StaContextSlot), R(0), U8(first_context_slot + 2), // + B(Mov), R(context), R(3), // + B(LdaConstant), U8(0), // + B(Star), R(4), // + B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), // + R(3), U8(2), R(1), // + B(LdaConstant), U8(1), // + B(Star), R(3), // + B(Mov), R(1), R(4), // + B(Mov), R(3), R(5), // + B(Mov), R(closure), R(6), // + B(LdaZero), // + B(Star), R(7), // + B(LdaSmi8), U8(10), // + B(Star), R(8), // + B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // + U8(5), // + B(Star), R(1), // + B(Call), R(1), R(2), U8(1), U8(0), // + B(LdaLookupSlot), U8(2), // + B(Return), // + }, + 3, + {"eval", "var x = 10;", "x"}}, + {"eval('var x = 10;'); return typeof x;", + 9 * kPointerSize, + 1, + 70, + { + 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(CreateMappedArguments), // + B(StaContextSlot), R(0), U8(first_context_slot + 1), // + B(Ldar), R(new_target), // + B(StaContextSlot), R(0), U8(first_context_slot + 2), // + B(Mov), R(context), R(3), // + B(LdaConstant), U8(0), // + B(Star), R(4), // + B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), // + R(3), U8(2), R(1), // + B(LdaConstant), U8(1), // + B(Star), R(3), // + B(Mov), R(1), R(4), // + B(Mov), R(3), R(5), // + B(Mov), R(closure), R(6), // + B(LdaZero), // + B(Star), R(7), // + B(LdaSmi8), U8(10), // + B(Star), R(8), // + B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // + U8(5), // + B(Star), R(1), // + B(Call), R(1), R(2), U8(1), U8(0), // + B(LdaLookupSlotInsideTypeof), U8(2), // + B(TypeOf), // + B(Return), // + }, + 3, + {"eval", "var x = 10;", "x"}}, + {"x = 20; return eval('');", + 9 * kPointerSize, + 1, + 71, + { + 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(CreateMappedArguments), // + B(StaContextSlot), R(0), U8(first_context_slot + 1), // + B(Ldar), R(new_target), // + B(StaContextSlot), R(0), U8(first_context_slot + 2), // + B(LdaSmi8), U8(20), // + B(StaLookupSlotSloppy), U8(0), // + B(Mov), R(context), R(3), // + B(LdaConstant), U8(1), // + B(Star), R(4), // + B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), // + R(3), U8(2), R(1), // + B(LdaConstant), U8(2), // + B(Star), R(3), // + B(Mov), R(1), R(4), // + B(Mov), R(3), R(5), // + B(Mov), R(closure), R(6), // + B(LdaZero), // + B(Star), R(7), // + B(LdaSmi8), U8(10), // + B(Star), R(8), // + B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // + U8(5), // + B(Star), R(1), // + B(Call), R(1), R(2), U8(1), U8(0), // + B(Return), // + }, + 3, + {"x", "eval", ""}}, + }; + + for (size_t i = 0; i < arraysize(snippets); i++) { + Handle<BytecodeArray> bytecode_array = + helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); + CheckBytecodeArrayEqual(snippets[i], bytecode_array); + } +} + + +TEST(CallLookupSlot) { + InitializedHandleScope handle_scope; + BytecodeGeneratorHelper helper; + Zone zone; + + FeedbackVectorSpec feedback_spec(&zone); + FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot(); + FeedbackVectorSlot slot2 = feedback_spec.AddCallICSlot(); + USE(slot1); + + Handle<i::TypeFeedbackVector> vector = + i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); + + int closure = Register::function_closure().index(); + int context = Register::function_context().index(); + int new_target = Register::new_target().index(); + + ExpectedSnippet<InstanceType> snippets[] = { + {"g = function(){}; eval(''); return g();", + 9 * kPointerSize, + 1, + 90, + { + B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // + U8(1), // + B(PushContext), R(0), // + B(Ldar), THIS(1), // + B(StaContextSlot), R(0), U8(4), // + B(CreateMappedArguments), // + B(StaContextSlot), R(0), U8(5), // + B(Ldar), R(new_target), // + B(StaContextSlot), R(0), U8(6), // + B(CreateClosure), U8(0), U8(0), // + B(StaLookupSlotSloppy), U8(1), // + B(Mov), R(context), R(3), // + B(LdaConstant), U8(2), // + B(Star), R(4), // + B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), // + R(3), U8(2), R(1), // + B(LdaConstant), U8(3), // + B(Star), R(3), // + B(Mov), R(1), R(4), // + B(Mov), R(3), R(5), // + B(Mov), R(closure), R(6), // + B(LdaZero), // + B(Star), R(7), // + B(LdaSmi8), U8(10), // + B(Star), R(8), // + B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // + U8(5), // + B(Star), R(1), // + B(Call), R(1), R(2), U8(1), U8(0), // + B(Mov), R(context), R(3), // + B(LdaConstant), U8(1), // + B(Star), R(4), // + B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), // + R(3), U8(2), R(1), // + B(Call), R(1), R(2), U8(0), U8(vector->GetIndex(slot2)), // + B(Return), // + }, + 4, + {InstanceType::SHARED_FUNCTION_INFO_TYPE, + InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, + InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, + InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, + }; + + for (size_t i = 0; i < arraysize(snippets); i++) { + Handle<BytecodeArray> bytecode_array = + helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); + CheckBytecodeArrayEqual(snippets[i], bytecode_array); + } +} + + +TEST(LookupSlotInEval) { + InitializedHandleScope handle_scope; + BytecodeGeneratorHelper helper; + + const char* function_prologue = "var f;" + "var x = 1;" + "function f1() {" + " eval(\"function t() {"; + const char* function_epilogue = " }; f = t; f();\");" + "}" + "f1();"; + + ExpectedSnippet<const char*> snippets[] = { + {"return x;", + 0 * kPointerSize, + 1, + 3, + { + B(LdaLookupSlot), U8(0), // + B(Return) // + }, + 1, + {"x"}}, + {"x = 10;", + 0 * kPointerSize, + 1, + 6, + { + B(LdaSmi8), U8(10), // + B(StaLookupSlotSloppy), U8(0), // + B(LdaUndefined), // + B(Return), // + }, + 1, + {"x"}}, + {"'use strict'; x = 10;", + 0 * kPointerSize, + 1, + 6, + { + B(LdaSmi8), U8(10), // + B(StaLookupSlotStrict), U8(0), // + B(LdaUndefined), // + B(Return), // + }, + 1, + {"x"}}, + {"return typeof x;", + 0 * kPointerSize, + 1, + 4, + { + B(LdaLookupSlotInsideTypeof), U8(0), // + B(TypeOf), // + B(Return), // + }, + 1, + {"x"}}, + }; + + for (size_t i = 0; i < arraysize(snippets); i++) { + std::string script = std::string(function_prologue) + + std::string(snippets[i].code_snippet) + + std::string(function_epilogue); + // TODO(mythria): use * as filter when function declarations are supported + // inside eval. + Handle<BytecodeArray> bytecode_array = + helper.MakeBytecode(script.c_str(), "t", "f"); + CheckBytecodeArrayEqual(snippets[i], bytecode_array); + } +} + + +TEST(LookupSlotWideInEval) { + InitializedHandleScope handle_scope; + BytecodeGeneratorHelper helper; + + const char* function_prologue = + "var f;" + "var x = 1;" + "function f1() {" + " eval(\"function t() {"; + const char* function_epilogue = + " }; f = t; f();\");" + "}" + "f1();"; + + int const_count[] = {0, 0, 0, 0}; + ExpectedSnippet<InstanceType, 257> snippets[] = { + {REPEAT_256(SPACE, "var y = 2.3;") + "return x;", + 1 * kPointerSize, + 1, + 1028, + { + REPEAT_256(SPACE, // + B(LdaConstant), U8(const_count[0]++), // + B(Star), R(0), ) // + B(LdaLookupSlotWide), U16(256), // + B(Return) // + }, + 257, + {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE), + InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, + {REPEAT_256(SPACE, "var y = 2.3;") + "return typeof x;", + 1 * kPointerSize, + 1, + 1029, + { + REPEAT_256(SPACE, // + B(LdaConstant), U8(const_count[1]++), // + B(Star), R(0), ) // + B(LdaLookupSlotInsideTypeofWide), U16(256), // + B(TypeOf), // + B(Return) // + }, + 257, + {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE), + InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, + {REPEAT_256(SPACE, "var y = 2.3;") + "x = 10;", + 1 * kPointerSize, + 1, + 1031, + { + REPEAT_256(SPACE, // + B(LdaConstant), U8(const_count[2]++), // + B(Star), R(0), ) // + B(LdaSmi8), U8(10), // + B(StaLookupSlotSloppyWide), U16(256), // + B(LdaUndefined), // + B(Return) // + }, + 257, + {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE), + InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, + {"'use strict';" + REPEAT_256(SPACE, "var y = 2.3;") + "x = 10;", + 1 * kPointerSize, + 1, + 1031, + { + REPEAT_256(SPACE, + B(LdaConstant), U8(const_count[3]++), // + B(Star), R(0), ) // + B(LdaSmi8), U8(10), // + B(StaLookupSlotStrictWide), U16(256), // + B(LdaUndefined), // + B(Return) // + }, + 257, + {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE), + InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, + }; + + for (size_t i = 0; i < arraysize(snippets); i++) { + std::string script = std::string(function_prologue) + + std::string(snippets[i].code_snippet) + + std::string(function_epilogue); + // TODO(mythria): use * as filter when function declarations are supported + // inside eval. + Handle<BytecodeArray> bytecode_array = + helper.MakeBytecode(script.c_str(), "t", "f"); + CheckBytecodeArrayEqual(snippets[i], bytecode_array); + } +} + + +TEST(DeleteLookupSlotInEval) { + InitializedHandleScope handle_scope; + BytecodeGeneratorHelper helper; + + const char* function_prologue = "var f;" + "var x = 1;" + "z = 10;" + "function f1() {" + " var y;" + " eval(\"function t() {"; + const char* function_epilogue = " }; f = t; f();\");" + "}" + "f1();"; + + ExpectedSnippet<const char*> snippets[] = { + {"delete x;", + 0 * kPointerSize, + 1, + 5, + { + B(LdaConstant), U8(0), // + B(DeleteLookupSlot), // + B(LdaUndefined), // + B(Return) // + }, + 1, + {"x"}}, + {"return delete y;", + 0 * kPointerSize, + 1, + 2, + { + B(LdaFalse), // + B(Return) // + }, + 0}, + {"return delete z;", + 0 * kPointerSize, + 1, + 4, + { + B(LdaConstant), U8(0), // + B(DeleteLookupSlot), // + B(Return) // + }, + 1, + {"z"}}, + }; + + for (size_t i = 0; i < arraysize(snippets); i++) { + std::string script = std::string(function_prologue) + + std::string(snippets[i].code_snippet) + + std::string(function_epilogue); + Handle<BytecodeArray> bytecode_array = + helper.MakeBytecode(script.c_str(), "t", "f"); + CheckBytecodeArrayEqual(snippets[i], bytecode_array); + } +} + } // namespace interpreter } // namespace internal } // namespace v8 diff --git a/deps/v8/test/cctest/interpreter/test-interpreter.cc b/deps/v8/test/cctest/interpreter/test-interpreter.cc index d274fa73cb..506cf00cd0 100644 --- a/deps/v8/test/cctest/interpreter/test-interpreter.cc +++ b/deps/v8/test/cctest/interpreter/test-interpreter.cc @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// TODO(rmcilroy): Remove this define after this flag is turned on globally -#define V8_IMMINENT_DEPRECATION_WARNINGS - #include "src/v8.h" #include "src/execution.h" @@ -67,9 +64,9 @@ class InterpreterTester { source_(source), bytecode_(bytecode), feedback_vector_(feedback_vector) { - i::FLAG_vector_stores = true; i::FLAG_ignition = true; i::FLAG_ignition_fake_try_catch = true; + i::FLAG_ignition_fallback_on_eval_and_catch = false; i::FLAG_always_opt = false; // Set ignition filter flag via SetFlagsFromString to avoid double-free // (or potential leak with StrDup() based on ownership confusion). @@ -344,7 +341,7 @@ TEST(InterpreterLoadLiteral) { TEST(InterpreterLoadStoreRegisters) { HandleAndZoneScope handles; Handle<Object> true_value = handles.main_isolate()->factory()->true_value(); - for (int i = 0; i <= Register::kMaxRegisterIndex; i++) { + for (int i = 0; i <= kMaxInt8; i++) { BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); builder.set_locals_count(i + 1); builder.set_context_count(0); @@ -365,6 +362,117 @@ TEST(InterpreterLoadStoreRegisters) { } +TEST(InterpreterExchangeRegisters) { + for (int locals_count = 2; locals_count < 300; locals_count += 126) { + HandleAndZoneScope handles; + for (int exchanges = 1; exchanges < 4; exchanges++) { + BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); + builder.set_locals_count(locals_count); + builder.set_context_count(0); + builder.set_parameter_count(0); + + Register r0(0); + Register r1(locals_count - 1); + builder.LoadTrue(); + builder.StoreAccumulatorInRegister(r0); + builder.ExchangeRegisters(r0, r1); + builder.LoadFalse(); + builder.StoreAccumulatorInRegister(r0); + + bool expected = false; + for (int i = 0; i < exchanges; i++) { + builder.ExchangeRegisters(r0, r1); + expected = !expected; + } + builder.LoadAccumulatorWithRegister(r0); + builder.Return(); + Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); + InterpreterTester tester(handles.main_isolate(), bytecode_array); + auto callable = tester.GetCallable<>(); + Handle<Object> return_val = callable().ToHandleChecked(); + Handle<Object> expected_val = + handles.main_isolate()->factory()->ToBoolean(expected); + CHECK(return_val.is_identical_to(expected_val)); + } + } +} + + +TEST(InterpreterExchangeRegistersWithParameter) { + for (int locals_count = 2; locals_count < 300; locals_count += 126) { + HandleAndZoneScope handles; + for (int exchanges = 1; exchanges < 4; exchanges++) { + BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); + builder.set_locals_count(locals_count); + builder.set_context_count(0); + builder.set_parameter_count(3); + + Register r0 = Register::FromParameterIndex(2, 3); + Register r1(locals_count - 1); + builder.LoadTrue(); + builder.StoreAccumulatorInRegister(r0); + builder.ExchangeRegisters(r0, r1); + builder.LoadFalse(); + builder.StoreAccumulatorInRegister(r0); + + bool expected = false; + for (int i = 0; i < exchanges; i++) { + builder.ExchangeRegisters(r0, r1); + expected = !expected; + } + builder.LoadAccumulatorWithRegister(r0); + builder.Return(); + Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); + InterpreterTester tester(handles.main_isolate(), bytecode_array); + auto callable = tester.GetCallable<>(); + Handle<Object> return_val = callable().ToHandleChecked(); + Handle<Object> expected_val = + handles.main_isolate()->factory()->ToBoolean(expected); + CHECK(return_val.is_identical_to(expected_val)); + } + } +} + + +TEST(InterpreterExchangeWideRegisters) { + for (int locals_count = 3; locals_count < 300; locals_count += 126) { + HandleAndZoneScope handles; + for (int exchanges = 0; exchanges < 7; exchanges++) { + BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); + builder.set_locals_count(locals_count); + builder.set_context_count(0); + builder.set_parameter_count(0); + + Register r0(0); + Register r1(locals_count - 1); + Register r2(locals_count - 2); + builder.LoadLiteral(Smi::FromInt(200)); + builder.StoreAccumulatorInRegister(r0); + builder.ExchangeRegisters(r0, r1); + builder.LoadLiteral(Smi::FromInt(100)); + builder.StoreAccumulatorInRegister(r0); + builder.ExchangeRegisters(r0, r2); + builder.LoadLiteral(Smi::FromInt(0)); + builder.StoreAccumulatorInRegister(r0); + for (int i = 0; i < exchanges; i++) { + builder.ExchangeRegisters(r1, r2); + builder.ExchangeRegisters(r0, r1); + } + builder.LoadAccumulatorWithRegister(r0); + builder.Return(); + Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); + InterpreterTester tester(handles.main_isolate(), bytecode_array); + auto callable = tester.GetCallable<>(); + Handle<Object> return_val = callable().ToHandleChecked(); + Handle<Object> expected_val = + handles.main_isolate()->factory()->NewNumberFromInt(100 * + (exchanges % 3)); + CHECK(return_val.is_identical_to(expected_val)); + } + } +} + + static const Token::Value kShiftOperators[] = { Token::Value::SHL, Token::Value::SAR, Token::Value::SHR}; @@ -778,9 +886,8 @@ TEST(InterpreterLoadNamedProperty) { builder.set_locals_count(0); builder.set_context_count(0); builder.set_parameter_count(1); - size_t name_index = builder.GetConstantPoolEntry(name); - builder.LoadNamedProperty(builder.Parameter(0), name_index, - vector->GetIndex(slot), i::SLOPPY) + builder.LoadNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot), + i::SLOPPY) .Return(); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); @@ -880,10 +987,9 @@ TEST(InterpreterStoreNamedProperty) { builder.set_locals_count(0); builder.set_context_count(0); builder.set_parameter_count(1); - size_t name_index = builder.GetConstantPoolEntry(name); builder.LoadLiteral(Smi::FromInt(999)) - .StoreNamedProperty(builder.Parameter(0), name_index, - vector->GetIndex(slot), i::STRICT) + .StoreNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot), + i::STRICT) .Return(); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); @@ -995,11 +1101,9 @@ TEST(InterpreterCall) { builder.set_locals_count(1); builder.set_context_count(0); builder.set_parameter_count(1); - size_t name_index = builder.GetConstantPoolEntry(name); - builder.LoadNamedProperty(builder.Parameter(0), name_index, slot_index, - i::SLOPPY) + builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY) .StoreAccumulatorInRegister(Register(0)) - .Call(Register(0), builder.Parameter(0), 0) + .Call(Register(0), builder.Parameter(0), 0, 0) .Return(); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); @@ -1018,11 +1122,9 @@ TEST(InterpreterCall) { builder.set_locals_count(1); builder.set_context_count(0); builder.set_parameter_count(1); - size_t name_index = builder.GetConstantPoolEntry(name); - builder.LoadNamedProperty(builder.Parameter(0), name_index, slot_index, - i::SLOPPY) + builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY) .StoreAccumulatorInRegister(Register(0)) - .Call(Register(0), builder.Parameter(0), 0) + .Call(Register(0), builder.Parameter(0), 0, 0) .Return(); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); @@ -1044,9 +1146,7 @@ TEST(InterpreterCall) { builder.set_locals_count(4); builder.set_context_count(0); builder.set_parameter_count(1); - size_t name_index = builder.GetConstantPoolEntry(name); - builder.LoadNamedProperty(builder.Parameter(0), name_index, slot_index, - i::SLOPPY) + builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY) .StoreAccumulatorInRegister(Register(0)) .LoadAccumulatorWithRegister(builder.Parameter(0)) .StoreAccumulatorInRegister(Register(1)) @@ -1054,7 +1154,7 @@ TEST(InterpreterCall) { .StoreAccumulatorInRegister(Register(2)) .LoadLiteral(Smi::FromInt(11)) .StoreAccumulatorInRegister(Register(3)) - .Call(Register(0), Register(1), 2) + .Call(Register(0), Register(1), 2, 0) .Return(); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); @@ -1075,9 +1175,7 @@ TEST(InterpreterCall) { builder.set_locals_count(12); builder.set_context_count(0); builder.set_parameter_count(1); - size_t name_index = builder.GetConstantPoolEntry(name); - builder.LoadNamedProperty(builder.Parameter(0), name_index, slot_index, - i::SLOPPY) + builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY) .StoreAccumulatorInRegister(Register(0)) .LoadAccumulatorWithRegister(builder.Parameter(0)) .StoreAccumulatorInRegister(Register(1)) @@ -1101,7 +1199,7 @@ TEST(InterpreterCall) { .StoreAccumulatorInRegister(Register(10)) .LoadLiteral(factory->NewStringFromAsciiChecked("j")) .StoreAccumulatorInRegister(Register(11)) - .Call(Register(0), Register(1), 10) + .Call(Register(0), Register(1), 10, 0) .Return(); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); @@ -1245,8 +1343,8 @@ TEST(InterpreterConditionalJumps2) { static const Token::Value kComparisonTypes[] = { - Token::Value::EQ, Token::Value::NE, Token::Value::EQ_STRICT, - Token::Value::NE_STRICT, Token::Value::LTE, Token::Value::LTE, + Token::Value::EQ, Token::Value::NE, Token::Value::EQ_STRICT, + Token::Value::NE_STRICT, Token::Value::LT, Token::Value::LTE, Token::Value::GT, Token::Value::GTE}; @@ -1566,43 +1664,6 @@ static void LoadAny(BytecodeArrayBuilder* builder, } -TEST(InterpreterToBoolean) { - HandleAndZoneScope handles; - i::Factory* factory = handles.main_isolate()->factory(); - - std::pair<Handle<Object>, bool> object_type_tuples[] = { - std::make_pair(factory->undefined_value(), false), - std::make_pair(factory->null_value(), false), - std::make_pair(factory->false_value(), false), - std::make_pair(factory->true_value(), true), - std::make_pair(factory->NewNumber(9.1), true), - std::make_pair(factory->NewNumberFromInt(0), false), - std::make_pair( - Handle<Object>::cast(factory->NewStringFromStaticChars("hello")), - true), - std::make_pair( - Handle<Object>::cast(factory->NewStringFromStaticChars("")), false), - }; - - for (size_t i = 0; i < arraysize(object_type_tuples); i++) { - BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); - Register r0(0); - builder.set_locals_count(0); - builder.set_context_count(0); - builder.set_parameter_count(0); - LoadAny(&builder, factory, object_type_tuples[i].first); - builder.CastAccumulatorToBoolean(); - builder.Return(); - Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); - InterpreterTester tester(handles.main_isolate(), bytecode_array); - auto callable = tester.GetCallable<>(); - Handle<Object> return_value = callable().ToHandleChecked(); - CHECK(return_value->IsBoolean()); - CHECK_EQ(return_value->BooleanValue(), object_type_tuples[i].second); - } -} - - TEST(InterpreterUnaryNotNonBoolean) { HandleAndZoneScope handles; i::Factory* factory = handles.main_isolate()->factory(); @@ -1883,7 +1944,11 @@ TEST(InterpreterContextVariables) { HandleAndZoneScope handles; 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;", handle(Smi::FromInt(1), isolate)), std::make_pair("var a = 10; (function() { a; })(); return a;", @@ -1898,10 +1963,14 @@ TEST(InterpreterContextVariables) { "{ let b = 20; var c = function() { [a, b] };\n" " return a + b; }", 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++) { - 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()); auto callable = tester.GetCallable<>(); @@ -2162,6 +2231,19 @@ TEST(InterpreterCountOperators) { handle(Smi::FromInt(3), isolate)), std::make_pair("var a = 1; (function() { a = 2 })(); return a--;", handle(Smi::FromInt(2), isolate)), + std::make_pair("var i = 5; while(i--) {}; return i;", + handle(Smi::FromInt(-1), isolate)), + std::make_pair("var i = 1; if(i--) { return 1; } else { return 2; };", + handle(Smi::FromInt(1), isolate)), + std::make_pair("var i = -2; do {} while(i++) {}; return i;", + handle(Smi::FromInt(1), isolate)), + std::make_pair("var i = -1; for(; i++; ) {}; return i", + handle(Smi::FromInt(1), isolate)), + std::make_pair("var i = 20; switch(i++) {\n" + " case 20: return 1;\n" + " default: return 2;\n" + "}", + handle(Smi::FromInt(1), isolate)), }; for (size_t i = 0; i < arraysize(count_ops); i++) { @@ -2618,7 +2700,6 @@ TEST(InterpreterBasicLoops) { TEST(InterpreterForIn) { HandleAndZoneScope handles; - // TODO(oth): Add a test here for delete mid-loop when delete is ready. std::pair<const char*, int> for_in_samples[] = { {"function f() {\n" " var r = -1;\n" @@ -2795,7 +2876,27 @@ TEST(InterpreterForIn) { " }\n" " return flags;\n" " }", - 0}}; + 0}, + {"function f() {\n" + " var data = {x:23, y:34};\n" + " var result = 0;\n" + " var o = {};\n" + " var arr = [o];\n" + " for (arr[0].p in data)\n" // This is to test if value is loaded + " result += data[arr[0].p];\n" // back from accumulator before storing + " return result;\n" // named properties. + "}", + 57}, + {"function f() {\n" + " var data = {x:23, y:34};\n" + " var result = 0;\n" + " var o = {};\n" + " var i = 0;\n" + " for (o[i++] in data)\n" // This is to test if value is loaded + " result += data[o[i-1]];\n" // back from accumulator before + " return result;\n" // storing keyed properties. + "}", + 57}}; for (size_t i = 0; i < arraysize(for_in_samples); i++) { InterpreterTester tester(handles.main_isolate(), for_in_samples[i].first); @@ -2951,6 +3052,516 @@ TEST(InterpreterNewTarget) { CHECK(new_target_name->SameValue(*factory->NewStringFromStaticChars("f"))); } + +TEST(InterpreterAssignmentInExpressions) { + HandleAndZoneScope handles; + + std::pair<const char*, int> samples[] = { + {"function f() {\n" + " var x = 7;\n" + " var y = x + (x = 1) + (x = 2);\n" + " return y;\n" + "}", + 10}, + {"function f() {\n" + " var x = 7;\n" + " var y = x + (x = 1) + (x = 2);\n" + " return x;\n" + "}", + 2}, + {"function f() {\n" + " var x = 55;\n" + " x = x + (x = 100) + (x = 101);\n" + " return x;\n" + "}", + 256}, + {"function f() {\n" + " var x = 7;\n" + " return ++x + x + x++;\n" + "}", + 24}, + {"function f() {\n" + " var x = 7;\n" + " var y = 1 + ++x + x + x++;\n" + " return x;\n" + "}", + 9}, + {"function f() {\n" + " var x = 7;\n" + " var y = ++x + x + x++;\n" + " return x;\n" + "}", + 9}, + {"function f() {\n" + " var x = 7, y = 100, z = 1000;\n" + " return x + (x += 3) + y + (y *= 10) + (z *= 7) + z;\n" + "}", + 15117}, + {"function f() {\n" + " var inner = function (x) { return x + (x = 2) + (x = 4) + x; };\n" + " return inner(1);\n" + "}", + 11}, + {"function f() {\n" + " var x = 1, y = 2;\n" + " x = x + (x = 3) + y + (y = 4), y = y + (y = 5) + y + x;\n" + " return x + y;\n" + "}", + 10 + 24}, + {"function f() {\n" + " var x = 0;\n" + " var y = x | (x = 1) | (x = 2);\n" + " return x;\n" + "}", + 2}, + {"function f() {\n" + " var x = 0;\n" + " var y = x || (x = 1);\n" + " return x;\n" + "}", + 1}, + {"function f() {\n" + " var x = 1;\n" + " var y = x && (x = 2) && (x = 3);\n" + " return x;\n" + "}", + 3}, + {"function f() {\n" + " var x = 1;\n" + " var y = x || (x = 2);\n" + " return x;\n" + "}", + 1}, + {"function f() {\n" + " var x = 1;\n" + " x = (x << (x = 3)) | (x = 16);\n" + " return x;\n" + "}", + 24}, + {"function f() {\n" + " var r = 7;\n" + " var s = 11;\n" + " var t = 13;\n" + " var u = r + s + t + (r = 10) + (s = 20) +" + " (t = (r + s)) + r + s + t;\n" + " return r + s + t + u;\n" + "}", + 211}, + {"function f() {\n" + " var r = 7;\n" + " var s = 11;\n" + " var t = 13;\n" + " return r > (3 * s * (s = 1)) ? (t + (t += 1)) : (r + (r = 4));\n" + "}", + 11}, + {"function f() {\n" + " var r = 7;\n" + " var s = 11;\n" + " var t = 13;\n" + " return r > (3 * s * (s = 0)) ? (t + (t += 1)) : (r + (r = 4));\n" + "}", + 27}, + {"function f() {\n" + " var r = 7;\n" + " var s = 11;\n" + " var t = 13;\n" + " return (r + (r = 5)) > s ? r : t;\n" + "}", + 5}, + {"function f(a) {\n" + " return a + (arguments[0] = 10);\n" + "}", + 50}, + {"function f(a) {\n" + " return a + (arguments[0] = 10) + a;\n" + "}", + 60}, + {"function f(a) {\n" + " return a + (arguments[0] = 10) + arguments[0];\n" + "}", + 60}, + }; + + const int arg_value = 40; + for (size_t i = 0; i < arraysize(samples); i++) { + InterpreterTester tester(handles.main_isolate(), samples[i].first); + auto callable = tester.GetCallable<Handle<Object>>(); + Handle<Object> return_val = + callable(handle(Smi::FromInt(arg_value), handles.main_isolate())) + .ToHandleChecked(); + CHECK_EQ(Handle<Smi>::cast(return_val)->value(), samples[i].second); + } +} + + +TEST(InterpreterToName) { + HandleAndZoneScope handles; + i::Isolate* isolate = handles.main_isolate(); + i::Factory* factory = isolate->factory(); + + std::pair<const char*, Handle<Object>> to_name_tests[] = { + {"var a = 'val'; var obj = {[a] : 10}; return obj.val;", + factory->NewNumberFromInt(10)}, + {"var a = 20; var obj = {[a] : 10}; return obj['20'];", + factory->NewNumberFromInt(10)}, + {"var a = 20; var obj = {[a] : 10}; return obj[20];", + factory->NewNumberFromInt(10)}, + {"var a = {val:23}; var obj = {[a] : 10}; return obj[a];", + factory->NewNumberFromInt(10)}, + {"var a = {val:23}; var obj = {[a] : 10};\n" + "return obj['[object Object]'];", + factory->NewNumberFromInt(10)}, + {"var a = {toString : function() { return 'x'}};\n" + "var obj = {[a] : 10};\n" + "return obj.x;", + factory->NewNumberFromInt(10)}, + {"var a = {valueOf : function() { return 'x'}};\n" + "var obj = {[a] : 10};\n" + "return obj.x;", + factory->undefined_value()}, + {"var a = {[Symbol.toPrimitive] : function() { return 'x'}};\n" + "var obj = {[a] : 10};\n" + "return obj.x;", + factory->NewNumberFromInt(10)}, + }; + + for (size_t i = 0; i < arraysize(to_name_tests); i++) { + std::string source( + InterpreterTester::SourceForBody(to_name_tests[i].first)); + InterpreterTester tester(handles.main_isolate(), source.c_str()); + auto callable = tester.GetCallable<>(); + + Handle<i::Object> return_value = callable().ToHandleChecked(); + CHECK(return_value->SameValue(*to_name_tests[i].second)); + } +} + + +TEST(TemporaryRegisterAllocation) { + HandleAndZoneScope handles; + i::Isolate* isolate = handles.main_isolate(); + i::Factory* factory = isolate->factory(); + + std::pair<const char*, Handle<Object>> reg_tests[] = { + {"function add(a, b, c) {" + " return a + b + c;" + "}" + "function f() {" + " var a = 10, b = 10;" + " return add(a, b++, b);" + "}", + factory->NewNumberFromInt(31)}, + {"function add(a, b, c, d) {" + " return a + b + c + d;" + "}" + "function f() {" + " var x = 10, y = 20, z = 30;" + " return x + add(x, (y= x++), x, z);" + "}", + factory->NewNumberFromInt(71)}, + }; + + for (size_t i = 0; i < arraysize(reg_tests); i++) { + InterpreterTester tester(handles.main_isolate(), reg_tests[i].first); + auto callable = tester.GetCallable<>(); + + Handle<i::Object> return_value = callable().ToHandleChecked(); + CHECK(return_value->SameValue(*reg_tests[i].second)); + } +} + + +TEST(InterpreterLookupSlot) { + HandleAndZoneScope handles; + i::Isolate* isolate = handles.main_isolate(); + i::Factory* factory = isolate->factory(); + + // TODO(mythria): Add more tests when we have support for eval/with. + const char* function_prologue = "var f;" + "var x = 1;" + "function f1() {" + " eval(\"function t() {"; + const char* function_epilogue = " }; f = t;\");" + "}" + "f1();"; + + + std::pair<const char*, Handle<Object>> lookup_slot[] = { + {"return x;", handle(Smi::FromInt(1), isolate)}, + {"return typeof x;", factory->NewStringFromStaticChars("number")}, + {"return typeof dummy;", factory->NewStringFromStaticChars("undefined")}, + {"x = 10; return x;", handle(Smi::FromInt(10), isolate)}, + {"'use strict'; x = 20; return x;", handle(Smi::FromInt(20), isolate)}, + }; + + for (size_t i = 0; i < arraysize(lookup_slot); i++) { + std::string script = std::string(function_prologue) + + std::string(lookup_slot[i].first) + + std::string(function_epilogue); + + InterpreterTester tester(handles.main_isolate(), script.c_str(), "t"); + auto callable = tester.GetCallable<>(); + + Handle<i::Object> return_value = callable().ToHandleChecked(); + CHECK(return_value->SameValue(*lookup_slot[i].second)); + } +} + + +TEST(InterpreterCallLookupSlot) { + HandleAndZoneScope handles; + i::Isolate* isolate = handles.main_isolate(); + + std::pair<const char*, Handle<Object>> call_lookup[] = { + {"g = function(){ return 2 }; eval(''); return g();", + handle(Smi::FromInt(2), isolate)}, + {"g = function(){ return 2 }; eval('g = function() {return 3}');\n" + "return g();", + handle(Smi::FromInt(3), isolate)}, + {"g = { x: function(){ return this.y }, y: 20 };\n" + "eval('g = { x: g.x, y: 30 }');\n" + "return g.x();", + handle(Smi::FromInt(30), isolate)}, + }; + + for (size_t i = 0; i < arraysize(call_lookup); i++) { + std::string source(InterpreterTester::SourceForBody(call_lookup[i].first)); + InterpreterTester tester(handles.main_isolate(), source.c_str()); + auto callable = tester.GetCallable<>(); + + Handle<i::Object> return_value = callable().ToHandleChecked(); + CHECK(return_value->SameValue(*call_lookup[i].second)); + } +} + + +TEST(InterpreterLookupSlotWide) { + HandleAndZoneScope handles; + i::Isolate* isolate = handles.main_isolate(); + i::Factory* factory = isolate->factory(); + + const char* function_prologue = + "var f;" + "var x = 1;" + "function f1() {" + " eval(\"function t() {"; + const char* function_epilogue = + " }; f = t;\");" + "}" + "f1();"; + std::ostringstream str; + str << "var y = 2.3;"; + for (int i = 1; i < 256; i++) { + str << "y = " << 2.3 + i << ";"; + } + std::string init_function_body = str.str(); + + std::pair<std::string, Handle<Object>> lookup_slot[] = { + {init_function_body + "return x;", handle(Smi::FromInt(1), isolate)}, + {init_function_body + "return typeof x;", + factory->NewStringFromStaticChars("number")}, + {init_function_body + "return x = 10;", + handle(Smi::FromInt(10), isolate)}, + {"'use strict';" + init_function_body + "x = 20; return x;", + handle(Smi::FromInt(20), isolate)}, + }; + + for (size_t i = 0; i < arraysize(lookup_slot); i++) { + std::string script = std::string(function_prologue) + lookup_slot[i].first + + std::string(function_epilogue); + + InterpreterTester tester(handles.main_isolate(), script.c_str(), "t"); + auto callable = tester.GetCallable<>(); + + Handle<i::Object> return_value = callable().ToHandleChecked(); + CHECK(return_value->SameValue(*lookup_slot[i].second)); + } +} + + +TEST(InterpreterDeleteLookupSlot) { + HandleAndZoneScope handles; + i::Isolate* isolate = handles.main_isolate(); + i::Factory* factory = isolate->factory(); + + // TODO(mythria): Add more tests when we have support for eval/with. + const char* function_prologue = "var f;" + "var x = 1;" + "y = 10;" + "var obj = {val:10};" + "var z = 30;" + "function f1() {" + " var z = 20;" + " eval(\"function t() {"; + const char* function_epilogue = " }; f = t;\");" + "}" + "f1();"; + + + std::pair<const char*, Handle<Object>> delete_lookup_slot[] = { + {"return delete x;", factory->false_value()}, + {"return delete y;", factory->true_value()}, + {"return delete z;", factory->false_value()}, + {"return delete obj.val;", factory->true_value()}, + {"'use strict'; return delete obj.val;", factory->true_value()}, + }; + + for (size_t i = 0; i < arraysize(delete_lookup_slot); i++) { + std::string script = std::string(function_prologue) + + std::string(delete_lookup_slot[i].first) + + std::string(function_epilogue); + + InterpreterTester tester(handles.main_isolate(), script.c_str(), "t"); + auto callable = tester.GetCallable<>(); + + Handle<i::Object> return_value = callable().ToHandleChecked(); + CHECK(return_value->SameValue(*delete_lookup_slot[i].second)); + } +} + + +TEST(JumpWithConstantsAndWideConstants) { + HandleAndZoneScope handles; + auto isolate = handles.main_isolate(); + auto factory = isolate->factory(); + const int kStep = 13; + for (int constants = 3; constants < 256 + 3 * kStep; constants += kStep) { + std::ostringstream filler_os; + // Generate a string that consumes constant pool entries and + // spread out branch distances in script below. + for (int i = 0; i < constants; i++) { + filler_os << "var x_ = 'x_" << i << "';\n"; + } + std::string filler(filler_os.str()); + std::ostringstream script_os; + script_os << "function " << InterpreterTester::function_name() << "(a) {\n"; + script_os << " " << filler; + script_os << " for (var i = a; i < 2; i++) {\n"; + script_os << " " << filler; + script_os << " if (i == 0) { " << filler << "i = 10; continue; }\n"; + script_os << " else if (i == a) { " << filler << "i = 12; break; }\n"; + script_os << " else { " << filler << " }\n"; + script_os << " }\n"; + script_os << " return i;\n"; + script_os << "}\n"; + std::string script(script_os.str()); + for (int a = 0; a < 3; a++) { + InterpreterTester tester(handles.main_isolate(), script.c_str()); + auto callable = tester.GetCallable<Handle<Object>>(); + Handle<Object> return_val = + callable(factory->NewNumberFromInt(a)).ToHandleChecked(); + static const int results[] = {11, 12, 2}; + CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]); + } + } +} + + +TEST(InterpreterEval) { + HandleAndZoneScope handles; + i::Isolate* isolate = handles.main_isolate(); + i::Factory* factory = isolate->factory(); + + std::pair<const char*, Handle<Object>> eval[] = { + {"return eval('1;');", handle(Smi::FromInt(1), isolate)}, + {"return eval('100 * 20;');", handle(Smi::FromInt(2000), isolate)}, + {"var x = 10; return eval('x + 20;');", + handle(Smi::FromInt(30), isolate)}, + {"var x = 10; eval('x = 33;'); return x;", + handle(Smi::FromInt(33), isolate)}, + {"'use strict'; var x = 20; var z = 0;\n" + "eval('var x = 33; z = x;'); return x + z;", + handle(Smi::FromInt(53), isolate)}, + {"eval('var x = 33;'); eval('var y = x + 20'); return x + y;", + handle(Smi::FromInt(86), isolate)}, + {"var x = 1; eval('for(i = 0; i < 10; i++) x = x + 1;'); return x", + handle(Smi::FromInt(11), isolate)}, + {"var x = 10; eval('var x = 20;'); return x;", + handle(Smi::FromInt(20), isolate)}, + {"var x = 1; eval('\"use strict\"; var x = 2;'); return x;", + handle(Smi::FromInt(1), isolate)}, + {"'use strict'; var x = 1; eval('var x = 2;'); return x;", + handle(Smi::FromInt(1), isolate)}, + {"var x = 10; eval('x + 20;'); return typeof x;", + factory->NewStringFromStaticChars("number")}, + {"eval('var y = 10;'); return typeof unallocated;", + factory->NewStringFromStaticChars("undefined")}, + {"'use strict'; eval('var y = 10;'); return typeof unallocated;", + factory->NewStringFromStaticChars("undefined")}, + {"eval('var x = 10;'); return typeof x;", + factory->NewStringFromStaticChars("number")}, + {"var x = {}; eval('var x = 10;'); return typeof x;", + factory->NewStringFromStaticChars("number")}, + {"'use strict'; var x = {}; eval('var x = 10;'); return typeof x;", + factory->NewStringFromStaticChars("object")}, + }; + + for (size_t i = 0; i < arraysize(eval); i++) { + std::string source(InterpreterTester::SourceForBody(eval[i].first)); + InterpreterTester tester(handles.main_isolate(), source.c_str()); + auto callable = tester.GetCallable<>(); + + Handle<i::Object> return_value = callable().ToHandleChecked(); + CHECK(return_value->SameValue(*eval[i].second)); + } +} + + +TEST(InterpreterEvalParams) { + HandleAndZoneScope handles; + i::Isolate* isolate = handles.main_isolate(); + + std::pair<const char*, Handle<Object>> eval_params[] = { + {"var x = 10; return eval('x + p1;');", + handle(Smi::FromInt(30), isolate)}, + {"var x = 10; eval('p1 = x;'); return p1;", + handle(Smi::FromInt(10), isolate)}, + {"var a = 10;" + "function inner() { return eval('a + p1;');}" + "return inner();", + handle(Smi::FromInt(30), isolate)}, + }; + + for (size_t i = 0; i < arraysize(eval_params); i++) { + std::string source = "function " + InterpreterTester::function_name() + + "(p1) {" + eval_params[i].first + "}"; + InterpreterTester tester(handles.main_isolate(), source.c_str()); + auto callable = tester.GetCallable<Handle<Object>>(); + + Handle<i::Object> return_value = + callable(handle(Smi::FromInt(20), isolate)).ToHandleChecked(); + CHECK(return_value->SameValue(*eval_params[i].second)); + } +} + + +TEST(InterpreterEvalGlobal) { + HandleAndZoneScope handles; + i::Isolate* isolate = handles.main_isolate(); + i::Factory* factory = isolate->factory(); + + std::pair<const char*, Handle<Object>> eval_global[] = { + {"function add_global() { eval('function test() { z = 33; }; test()'); };" + "function f() { add_global(); return z; }; f();", + handle(Smi::FromInt(33), isolate)}, + {"function add_global() {\n" + " eval('\"use strict\"; function test() { y = 33; };" + " try { test() } catch(e) {}');\n" + "}\n" + "function f() { add_global(); return typeof y; } f();", + factory->NewStringFromStaticChars("undefined")}, + }; + + for (size_t i = 0; i < arraysize(eval_global); i++) { + InterpreterTester tester(handles.main_isolate(), eval_global[i].first, + "test"); + auto callable = tester.GetCallable<>(); + + Handle<i::Object> return_value = callable().ToHandleChecked(); + CHECK(return_value->SameValue(*eval_global[i].second)); + } +} + } // namespace interpreter } // namespace internal } // namespace v8 |