diff options
Diffstat (limited to 'deps/v8/test/cctest/interpreter/test-bytecode-generator.cc')
-rw-r--r-- | deps/v8/test/cctest/interpreter/test-bytecode-generator.cc | 4038 |
1 files changed, 2773 insertions, 1265 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 |