1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/v8.h" 6 7 #include "src/compiler.h" 8 #include "src/interpreter/bytecode-array-iterator.h" 9 #include "src/interpreter/bytecode-generator.h" 10 #include "src/interpreter/interpreter.h" 11 #include "test/cctest/cctest.h" 12 #include "test/cctest/test-feedback-vector.h" 13 14 namespace v8 { 15 namespace internal { 16 namespace interpreter { 17 18 class BytecodeGeneratorHelper { 19 public: 20 const char* kFunctionName = "f"; 21 22 static const int kLastParamIndex = 23 -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; 24 25 BytecodeGeneratorHelper() { 26 i::FLAG_ignition = true; 27 i::FLAG_ignition_fake_try_catch = true; 28 i::FLAG_ignition_fallback_on_eval_and_catch = false; 29 i::FLAG_ignition_filter = StrDup(kFunctionName); 30 i::FLAG_always_opt = false; 31 i::FLAG_allow_natives_syntax = true; 32 i::FLAG_legacy_const = true; 33 CcTest::i_isolate()->interpreter()->Initialize(); 34 } 35 36 Isolate* isolate() { return CcTest::i_isolate(); } 37 Factory* factory() { return CcTest::i_isolate()->factory(); } 38 39 Handle<BytecodeArray> MakeTopLevelBytecode(const char* source) { 40 const char* old_ignition_filter = i::FLAG_ignition_filter; 41 i::FLAG_ignition_filter = "*"; 42 Local<v8::Script> script = v8_compile(source); 43 i::FLAG_ignition_filter = old_ignition_filter; 44 i::Handle<i::JSFunction> js_function = v8::Utils::OpenHandle(*script); 45 return handle(js_function->shared()->bytecode_array(), CcTest::i_isolate()); 46 } 47 48 Handle<BytecodeArray> MakeBytecode(const char* script, 49 const char* function_name) { 50 CompileRun(script); 51 v8::Local<v8::Context> context = 52 v8::Isolate::GetCurrent()->GetCurrentContext(); 53 Local<Function> function = Local<Function>::Cast( 54 CcTest::global()->Get(context, v8_str(function_name)).ToLocalChecked()); 55 i::Handle<i::JSFunction> js_function = 56 i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*function)); 57 return handle(js_function->shared()->bytecode_array(), CcTest::i_isolate()); 58 } 59 60 Handle<BytecodeArray> MakeBytecode(const char* script, const char* filter, 61 const char* function_name) { 62 const char* old_ignition_filter = i::FLAG_ignition_filter; 63 i::FLAG_ignition_filter = filter; 64 Handle<BytecodeArray> return_val = MakeBytecode(script, function_name); 65 i::FLAG_ignition_filter = old_ignition_filter; 66 return return_val; 67 } 68 69 Handle<BytecodeArray> MakeBytecodeForFunctionBody(const char* body) { 70 static const char kFormat[] = "function %s() { %s }\n%s();"; 71 static const int kFormatLength = arraysize(kFormat); 72 int length = kFormatLength + 2 * StrLength(kFunctionName) + StrLength(body); 73 ScopedVector<char> program(length); 74 length = SNPrintF(program, kFormat, kFunctionName, body, kFunctionName); 75 CHECK_GT(length, 0); 76 return MakeBytecode(program.start(), kFunctionName); 77 } 78 79 Handle<BytecodeArray> MakeBytecodeForFunction(const char* function) { 80 ScopedVector<char> program(3072); 81 SNPrintF(program, "%s\n%s();", function, kFunctionName); 82 return MakeBytecode(program.start(), kFunctionName); 83 } 84 85 Handle<BytecodeArray> MakeBytecodeForFunctionNoFilter(const char* function) { 86 ScopedVector<char> program(3072); 87 SNPrintF(program, "%s\n%s();", function, kFunctionName); 88 return MakeBytecode(program.start(), "*", kFunctionName); 89 } 90 }; 91 92 93 // Helper macros for handcrafting bytecode sequences. 94 #define B(x) static_cast<uint8_t>(Bytecode::k##x) 95 #define U8(x) static_cast<uint8_t>((x) & 0xff) 96 #define R(x) static_cast<uint8_t>(-(x) & 0xff) 97 #define A(x, n) R(helper.kLastParamIndex - (n) + 1 + (x)) 98 #define THIS(n) A(0, n) 99 #if defined(V8_TARGET_LITTLE_ENDIAN) 100 #define U16(x) static_cast<uint8_t>((x) & 0xff), \ 101 static_cast<uint8_t>(((x) >> kBitsPerByte) & 0xff) 102 #define U16I(x) static_cast<uint8_t>((x) & 0xff), \ 103 static_cast<uint8_t>(((x++) >> kBitsPerByte) & 0xff) 104 #elif defined(V8_TARGET_BIG_ENDIAN) 105 #define U16(x) static_cast<uint8_t>(((x) >> kBitsPerByte) & 0xff), \ 106 static_cast<uint8_t>((x) & 0xff) 107 #define U16I(x) static_cast<uint8_t>(((x) >> kBitsPerByte) & 0xff), \ 108 static_cast<uint8_t>((x++) & 0xff) 109 #else 110 #error Unknown byte ordering 111 #endif 112 113 #define XSTR(A) #A 114 #define STR(A) XSTR(A) 115 116 #define COMMA() , 117 #define SPACE() 118 #define UNIQUE_VAR() "var a" STR(__COUNTER__) " = 0;\n" 119 120 #define REPEAT_2(SEP, ...) \ 121 __VA_ARGS__ SEP() __VA_ARGS__ 122 #define REPEAT_4(SEP, ...) \ 123 REPEAT_2(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) 124 #define REPEAT_8(SEP, ...) \ 125 REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_4(SEP, __VA_ARGS__) 126 #define REPEAT_16(SEP, ...) \ 127 REPEAT_8(SEP, __VA_ARGS__) SEP() REPEAT_8(SEP, __VA_ARGS__) 128 #define REPEAT_32(SEP, ...) \ 129 REPEAT_16(SEP, __VA_ARGS__) SEP() REPEAT_16(SEP, __VA_ARGS__) 130 #define REPEAT_64(SEP, ...) \ 131 REPEAT_32(SEP, __VA_ARGS__) SEP() REPEAT_32(SEP, __VA_ARGS__) 132 #define REPEAT_128(SEP, ...) \ 133 REPEAT_64(SEP, __VA_ARGS__) SEP() REPEAT_64(SEP, __VA_ARGS__) 134 #define REPEAT_256(SEP, ...) \ 135 REPEAT_128(SEP, __VA_ARGS__) SEP() REPEAT_128(SEP, __VA_ARGS__) 136 137 #define REPEAT_127(SEP, ...) \ 138 REPEAT_64(SEP, __VA_ARGS__) SEP() REPEAT_32(SEP, __VA_ARGS__) SEP() \ 139 REPEAT_16(SEP, __VA_ARGS__) SEP() REPEAT_8(SEP, __VA_ARGS__) SEP() \ 140 REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) SEP() \ 141 __VA_ARGS__ 142 143 #define REPEAT_249(SEP, ...) \ 144 REPEAT_127(SEP, __VA_ARGS__) SEP() REPEAT_64(SEP, __VA_ARGS__) SEP() \ 145 REPEAT_32(SEP, __VA_ARGS__) SEP() REPEAT_16(SEP, __VA_ARGS__) SEP() \ 146 REPEAT_8(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) 147 148 #define REPEAT_249_UNIQUE_VARS() \ 149 UNIQUE_VAR() REPEAT_127(UNIQUE_VAR) UNIQUE_VAR() REPEAT_64(UNIQUE_VAR) \ 150 UNIQUE_VAR() REPEAT_32(UNIQUE_VAR) UNIQUE_VAR() REPEAT_16(UNIQUE_VAR) \ 151 UNIQUE_VAR() REPEAT_8(UNIQUE_VAR) UNIQUE_VAR() REPEAT_2(UNIQUE_VAR) 152 153 // Structure for containing expected bytecode snippets. 154 template<typename T, int C = 6> 155 struct ExpectedSnippet { 156 const char* code_snippet; 157 int frame_size; 158 int parameter_count; 159 int bytecode_length; 160 const uint8_t bytecode[2048]; 161 int constant_count; 162 T constants[C]; 163 }; 164 165 166 static void CheckConstant(int expected, Object* actual) { 167 CHECK_EQ(expected, Smi::cast(actual)->value()); 168 } 169 170 171 static void CheckConstant(double expected, Object* actual) { 172 CHECK_EQ(expected, HeapNumber::cast(actual)->value()); 173 } 174 175 176 static void CheckConstant(const char* expected, Object* actual) { 177 Handle<String> expected_string = 178 CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(expected); 179 CHECK(String::cast(actual)->Equals(*expected_string)); 180 } 181 182 183 static void CheckConstant(Handle<Object> expected, Object* actual) { 184 CHECK(actual == *expected || expected->StrictEquals(actual)); 185 } 186 187 188 static void CheckConstant(InstanceType expected, Object* actual) { 189 CHECK_EQ(expected, HeapObject::cast(actual)->map()->instance_type()); 190 } 191 192 193 template <typename T, int C> 194 static void CheckBytecodeArrayEqual(const ExpectedSnippet<T, C>& expected, 195 Handle<BytecodeArray> actual) { 196 CHECK_EQ(expected.frame_size, actual->frame_size()); 197 CHECK_EQ(expected.parameter_count, actual->parameter_count()); 198 CHECK_EQ(expected.bytecode_length, actual->length()); 199 if (expected.constant_count == 0) { 200 CHECK_EQ(CcTest::heap()->empty_fixed_array(), actual->constant_pool()); 201 } else { 202 CHECK_EQ(expected.constant_count, actual->constant_pool()->length()); 203 for (int i = 0; i < expected.constant_count; i++) { 204 CheckConstant(expected.constants[i], actual->constant_pool()->get(i)); 205 } 206 } 207 208 BytecodeArrayIterator iterator(actual); 209 int i = 0; 210 while (!iterator.done()) { 211 int bytecode_index = i++; 212 Bytecode bytecode = iterator.current_bytecode(); 213 if (Bytecodes::ToByte(bytecode) != expected.bytecode[bytecode_index]) { 214 std::ostringstream stream; 215 stream << "Check failed: expected bytecode [" << bytecode_index 216 << "] to be " << Bytecodes::ToString(static_cast<Bytecode>( 217 expected.bytecode[bytecode_index])) 218 << " but got " << Bytecodes::ToString(bytecode); 219 FATAL(stream.str().c_str()); 220 } 221 for (int j = 0; j < Bytecodes::NumberOfOperands(bytecode); ++j) { 222 OperandType operand_type = Bytecodes::GetOperandType(bytecode, j); 223 int operand_index = i; 224 i += static_cast<int>(Bytecodes::SizeOfOperand(operand_type)); 225 uint32_t raw_operand = iterator.GetRawOperand(j, operand_type); 226 uint32_t expected_operand; 227 switch (Bytecodes::SizeOfOperand(operand_type)) { 228 case OperandSize::kNone: 229 UNREACHABLE(); 230 return; 231 case OperandSize::kByte: 232 expected_operand = 233 static_cast<uint32_t>(expected.bytecode[operand_index]); 234 break; 235 case OperandSize::kShort: 236 expected_operand = 237 ReadUnalignedUInt16(&expected.bytecode[operand_index]); 238 break; 239 default: 240 UNREACHABLE(); 241 return; 242 } 243 if (raw_operand != expected_operand) { 244 std::ostringstream stream; 245 stream << "Check failed: expected operand [" << j << "] for bytecode [" 246 << bytecode_index << "] to be " 247 << static_cast<unsigned int>(expected_operand) << " but got " 248 << static_cast<unsigned int>(raw_operand); 249 FATAL(stream.str().c_str()); 250 } 251 } 252 iterator.Advance(); 253 } 254 } 255 256 257 TEST(PrimitiveReturnStatements) { 258 InitializedHandleScope handle_scope; 259 BytecodeGeneratorHelper helper; 260 261 ExpectedSnippet<int> snippets[] = { 262 {"", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0}, 263 {"return;", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0}, 264 {"return null;", 0, 1, 2, {B(LdaNull), B(Return)}, 0}, 265 {"return true;", 0, 1, 2, {B(LdaTrue), B(Return)}, 0}, 266 {"return false;", 0, 1, 2, {B(LdaFalse), B(Return)}, 0}, 267 {"return 0;", 0, 1, 2, {B(LdaZero), B(Return)}, 0}, 268 {"return +1;", 0, 1, 3, {B(LdaSmi8), U8(1), B(Return)}, 0}, 269 {"return -1;", 0, 1, 3, {B(LdaSmi8), U8(-1), B(Return)}, 0}, 270 {"return +127;", 0, 1, 3, {B(LdaSmi8), U8(127), B(Return)}, 0}, 271 {"return -128;", 0, 1, 3, {B(LdaSmi8), U8(-128), B(Return)}, 0}, 272 }; 273 274 for (size_t i = 0; i < arraysize(snippets); i++) { 275 Handle<BytecodeArray> bytecode_array = 276 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 277 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 278 } 279 } 280 281 282 TEST(PrimitiveExpressions) { 283 InitializedHandleScope handle_scope; 284 BytecodeGeneratorHelper helper; 285 286 ExpectedSnippet<int> snippets[] = { 287 {"var x = 0; return x;", 288 kPointerSize, 289 1, 290 4, 291 {B(LdaZero), // 292 B(Star), R(0), // 293 B(Return)}, 294 0}, 295 {"var x = 0; return x + 3;", 296 2 * kPointerSize, 297 1, 298 10, 299 {B(LdaZero), // 300 B(Star), R(0), // 301 B(Star), R(1), // 302 B(LdaSmi8), U8(3), // 303 B(Add), R(1), // 304 B(Return)}, 305 0}, 306 {"var x = 0; return x - 3;", 307 2 * kPointerSize, 308 1, 309 10, 310 {B(LdaZero), // 311 B(Star), R(0), // 312 B(Star), R(1), // 313 B(LdaSmi8), U8(3), // 314 B(Sub), R(1), // 315 B(Return)}, 316 0}, 317 {"var x = 4; return x * 3;", 318 2 * kPointerSize, 319 1, 320 11, 321 {B(LdaSmi8), U8(4), // 322 B(Star), R(0), // 323 B(Star), R(1), // 324 B(LdaSmi8), U8(3), // 325 B(Mul), R(1), // 326 B(Return)}, 327 0}, 328 {"var x = 4; return x / 3;", 329 2 * kPointerSize, 330 1, 331 11, 332 {B(LdaSmi8), U8(4), // 333 B(Star), R(0), // 334 B(Star), R(1), // 335 B(LdaSmi8), U8(3), // 336 B(Div), R(1), // 337 B(Return)}, 338 0}, 339 {"var x = 4; return x % 3;", 340 2 * kPointerSize, 341 1, 342 11, 343 {B(LdaSmi8), U8(4), // 344 B(Star), R(0), // 345 B(Star), R(1), // 346 B(LdaSmi8), U8(3), // 347 B(Mod), R(1), // 348 B(Return)}, 349 0}, 350 {"var x = 1; return x | 2;", 351 2 * kPointerSize, 352 1, 353 11, 354 {B(LdaSmi8), U8(1), // 355 B(Star), R(0), // 356 B(Star), R(1), // 357 B(LdaSmi8), U8(2), // 358 B(BitwiseOr), R(1), // 359 B(Return)}, 360 0}, 361 {"var x = 1; return x ^ 2;", 362 2 * kPointerSize, 363 1, 364 11, 365 {B(LdaSmi8), U8(1), // 366 B(Star), R(0), // 367 B(Star), R(1), // 368 B(LdaSmi8), U8(2), // 369 B(BitwiseXor), R(1), // 370 B(Return)}, 371 0}, 372 {"var x = 1; return x & 2;", 373 2 * kPointerSize, 374 1, 375 11, 376 {B(LdaSmi8), U8(1), // 377 B(Star), R(0), // 378 B(Star), R(1), // 379 B(LdaSmi8), U8(2), // 380 B(BitwiseAnd), R(1), // 381 B(Return)}, 382 0}, 383 {"var x = 10; return x << 3;", 384 2 * kPointerSize, 385 1, 386 11, 387 {B(LdaSmi8), U8(10), // 388 B(Star), R(0), // 389 B(Star), R(1), // 390 B(LdaSmi8), U8(3), // 391 B(ShiftLeft), R(1), // 392 B(Return)}, 393 0}, 394 {"var x = 10; return x >> 3;", 395 2 * kPointerSize, 396 1, 397 11, 398 {B(LdaSmi8), U8(10), // 399 B(Star), R(0), // 400 B(Star), R(1), // 401 B(LdaSmi8), U8(3), // 402 B(ShiftRight), R(1), // 403 B(Return)}, 404 0}, 405 {"var x = 10; return x >>> 3;", 406 2 * kPointerSize, 407 1, 408 11, 409 {B(LdaSmi8), U8(10), // 410 B(Star), R(0), // 411 B(Star), R(1), // 412 B(LdaSmi8), U8(3), // 413 B(ShiftRightLogical), R(1), // 414 B(Return)}, 415 0}, 416 {"var x = 0; return (x, 3);", 417 1 * kPointerSize, 418 1, 419 6, 420 {B(LdaZero), // 421 B(Star), R(0), // 422 B(LdaSmi8), U8(3), // 423 B(Return)}, 424 0}}; 425 426 for (size_t i = 0; i < arraysize(snippets); i++) { 427 Handle<BytecodeArray> bytecode_array = 428 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 429 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 430 } 431 } 432 433 434 TEST(LogicalExpressions) { 435 InitializedHandleScope handle_scope; 436 BytecodeGeneratorHelper helper; 437 438 ExpectedSnippet<int> snippets[] = { 439 {"var x = 0; return x || 3;", 440 1 * kPointerSize, 441 1, 442 8, 443 {B(LdaZero), // 444 B(Star), R(0), // 445 B(JumpIfToBooleanTrue), U8(4), // 446 B(LdaSmi8), U8(3), // 447 B(Return)}, 448 0}, 449 {"var x = 0; return (x == 1) || 3;", 450 2 * kPointerSize, 451 1, 452 14, 453 {B(LdaZero), // 454 B(Star), R(0), // 455 B(Star), R(1), // 456 B(LdaSmi8), U8(1), // 457 B(TestEqual), R(1), // 458 B(JumpIfTrue), U8(4), // 459 B(LdaSmi8), U8(3), // 460 B(Return)}, 461 0}, 462 {"var x = 0; return x && 3;", 463 1 * kPointerSize, 464 1, 465 8, 466 {B(LdaZero), // 467 B(Star), R(0), // 468 B(JumpIfToBooleanFalse), U8(4), // 469 B(LdaSmi8), U8(3), // 470 B(Return)}, 471 0}, 472 {"var x = 0; return (x == 0) && 3;", 473 2 * kPointerSize, 474 1, 475 13, 476 {B(LdaZero), // 477 B(Star), R(0), // 478 B(Star), R(1), // 479 B(LdaZero), // 480 B(TestEqual), R(1), // 481 B(JumpIfFalse), U8(4), // 482 B(LdaSmi8), U8(3), // 483 B(Return)}, 484 0}, 485 {"var x = 0; return x || (1, 2, 3);", 486 1 * kPointerSize, 487 1, 488 8, 489 {B(LdaZero), // 490 B(Star), R(0), // 491 B(JumpIfToBooleanTrue), U8(4), // 492 B(LdaSmi8), U8(3), // 493 B(Return)}, 494 0}, 495 {"var a = 2, b = 3, c = 4; return a || (a, b, a, b, c = 5, 3);", 496 3 * kPointerSize, 497 1, 498 31, 499 {B(LdaSmi8), U8(2), // 500 B(Star), R(0), // 501 B(LdaSmi8), U8(3), // 502 B(Star), R(1), // 503 B(LdaSmi8), U8(4), // 504 B(Star), R(2), // 505 B(Ldar), R(0), // 506 B(JumpIfToBooleanTrue), U8(16), // 507 B(Ldar), R(0), // 508 B(Ldar), R(1), // 509 B(Ldar), R(0), // 510 B(Ldar), R(1), // 511 B(LdaSmi8), U8(5), // 512 B(Star), R(2), // 513 B(LdaSmi8), U8(3), // 514 B(Return)}, 515 0}, 516 {"var x = 1; var a = 2, b = 3; return x || (" 517 REPEAT_32(SPACE, "a = 1, b = 2, ") 518 "3);", 519 3 * kPointerSize, 520 1, 521 275, 522 {B(LdaSmi8), U8(1), // 523 B(Star), R(0), // 524 B(LdaSmi8), U8(2), // 525 B(Star), R(1), // 526 B(LdaSmi8), U8(3), // 527 B(Star), R(2), // 528 B(Ldar), R(0), // 529 B(JumpIfToBooleanTrueConstant), U8(0), // 530 REPEAT_32(COMMA, // 531 B(LdaSmi8), U8(1), // 532 B(Star), R(1), // 533 B(LdaSmi8), U8(2), // 534 B(Star), R(2)), // 535 B(LdaSmi8), U8(3), // 536 B(Return)}, 537 1, 538 {260, 0, 0, 0}}, 539 {"var x = 0; var a = 2, b = 3; return x && (" 540 REPEAT_32(SPACE, "a = 1, b = 2, ") 541 "3);", 542 3 * kPointerSize, 543 1, 544 274, 545 {B(LdaZero), // 546 B(Star), R(0), // 547 B(LdaSmi8), U8(2), // 548 B(Star), R(1), // 549 B(LdaSmi8), U8(3), // 550 B(Star), R(2), // 551 B(Ldar), R(0), // 552 B(JumpIfToBooleanFalseConstant), U8(0), // 553 REPEAT_32(COMMA, // 554 B(LdaSmi8), U8(1), // 555 B(Star), R(1), // 556 B(LdaSmi8), U8(2), // 557 B(Star), R(2)), // 558 B(LdaSmi8), U8(3), // 559 B(Return)}, // 560 1, 561 {260, 0, 0, 0}}, 562 {"var x = 1; var a = 2, b = 3; return (x > 3) || (" 563 REPEAT_32(SPACE, "a = 1, b = 2, ") 564 "3);", 565 4 * kPointerSize, 566 1, 567 281, 568 {B(LdaSmi8), U8(1), // 569 B(Star), R(0), // 570 B(LdaSmi8), U8(2), // 571 B(Star), R(1), // 572 B(LdaSmi8), U8(3), // 573 B(Star), R(2), // 574 B(Ldar), R(0), // 575 B(Star), R(3), // 576 B(LdaSmi8), U8(3), // 577 B(TestGreaterThan), R(3), // 578 B(JumpIfTrueConstant), U8(0), // 579 REPEAT_32(COMMA, // 580 B(LdaSmi8), U8(1), // 581 B(Star), R(1), // 582 B(LdaSmi8), U8(2), // 583 B(Star), R(2)), // 584 B(LdaSmi8), U8(3), // 585 B(Return)}, 586 1, 587 {260, 0, 0, 0}}, 588 {"var x = 0; var a = 2, b = 3; return (x < 5) && (" 589 REPEAT_32(SPACE, "a = 1, b = 2, ") 590 "3);", 591 4 * kPointerSize, 592 1, 593 280, 594 {B(LdaZero), // 595 B(Star), R(0), // 596 B(LdaSmi8), U8(2), // 597 B(Star), R(1), // 598 B(LdaSmi8), U8(3), // 599 B(Star), R(2), // 600 B(Ldar), R(0), // 601 B(Star), R(3), // 602 B(LdaSmi8), U8(5), // 603 B(TestLessThan), R(3), // 604 B(JumpIfFalseConstant), U8(0), // 605 REPEAT_32(COMMA, // 606 B(LdaSmi8), U8(1), // 607 B(Star), R(1), // 608 B(LdaSmi8), U8(2), // 609 B(Star), R(2)), // 610 B(LdaSmi8), U8(3), // 611 B(Return)}, 612 1, 613 {260, 0, 0, 0}}, 614 {"return 0 && 3;", 615 0 * kPointerSize, 616 1, 617 2, 618 {B(LdaZero), // 619 B(Return)}, 620 0}, 621 {"return 1 || 3;", 622 0 * kPointerSize, 623 1, 624 3, 625 {B(LdaSmi8), U8(1), // 626 B(Return)}, 627 0}, 628 {"var x = 1; return x && 3 || 0, 1;", 629 1 * kPointerSize, 630 1, 631 14, 632 {B(LdaSmi8), U8(1), // 633 B(Star), R(0), // 634 B(JumpIfToBooleanFalse), U8(4), // 635 B(LdaSmi8), U8(3), // 636 B(JumpIfToBooleanTrue), U8(3), // 637 B(LdaZero), // 638 B(LdaSmi8), U8(1), // 639 B(Return)}, 640 0}}; 641 642 for (size_t i = 0; i < arraysize(snippets); i++) { 643 Handle<BytecodeArray> bytecode_array = 644 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 645 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 646 } 647 } 648 649 650 TEST(Parameters) { 651 InitializedHandleScope handle_scope; 652 BytecodeGeneratorHelper helper; 653 654 ExpectedSnippet<int> snippets[] = { 655 {"function f() { return this; }", 656 0, 657 1, 658 3, 659 {B(Ldar), THIS(1), B(Return)}, 660 0}, 661 {"function f(arg1) { return arg1; }", 662 0, 663 2, 664 3, 665 {B(Ldar), A(1, 2), B(Return)}, 666 0}, 667 {"function f(arg1) { return this; }", 668 0, 669 2, 670 3, 671 {B(Ldar), THIS(2), B(Return)}, 672 0}, 673 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return arg4; }", 674 0, 675 8, 676 3, 677 {B(Ldar), A(4, 8), B(Return)}, 678 0}, 679 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return this; }", 680 0, 681 8, 682 3, 683 {B(Ldar), THIS(8), B(Return)}, 684 0}, 685 {"function f(arg1) { arg1 = 1; }", 686 0, 687 2, 688 6, 689 {B(LdaSmi8), U8(1), // 690 B(Star), A(1, 2), // 691 B(LdaUndefined), // 692 B(Return)}, 693 0}, 694 {"function f(arg1, arg2, arg3, arg4) { arg2 = 1; }", 695 0, 696 5, 697 6, 698 {B(LdaSmi8), U8(1), // 699 B(Star), A(2, 5), // 700 B(LdaUndefined), // 701 B(Return)}, 702 0}, 703 }; 704 705 for (size_t i = 0; i < arraysize(snippets); i++) { 706 Handle<BytecodeArray> bytecode_array = 707 helper.MakeBytecodeForFunction(snippets[i].code_snippet); 708 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 709 } 710 } 711 712 713 TEST(IntegerConstants) { 714 InitializedHandleScope handle_scope; 715 BytecodeGeneratorHelper helper; 716 717 ExpectedSnippet<int> snippets[] = { 718 {"return 12345678;", 719 0, 720 1, 721 3, 722 { 723 B(LdaConstant), U8(0), // 724 B(Return) // 725 }, 726 1, 727 {12345678}}, 728 {"var a = 1234; return 5678;", 729 1 * kPointerSize, 730 1, 731 7, 732 { 733 B(LdaConstant), U8(0), // 734 B(Star), R(0), // 735 B(LdaConstant), U8(1), // 736 B(Return) // 737 }, 738 2, 739 {1234, 5678}}, 740 {"var a = 1234; return 1234;", 741 1 * kPointerSize, 742 1, 743 7, 744 { 745 B(LdaConstant), U8(0), // 746 B(Star), R(0), // 747 B(LdaConstant), U8(0), // 748 B(Return) // 749 }, 750 1, 751 {1234}}}; 752 753 for (size_t i = 0; i < arraysize(snippets); i++) { 754 Handle<BytecodeArray> bytecode_array = 755 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 756 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 757 } 758 } 759 760 761 TEST(HeapNumberConstants) { 762 InitializedHandleScope handle_scope; 763 BytecodeGeneratorHelper helper; 764 765 int wide_idx = 0; 766 767 ExpectedSnippet<double, 257> snippets[] = { 768 {"return 1.2;", 769 0, 770 1, 771 3, 772 { 773 B(LdaConstant), U8(0), // 774 B(Return) // 775 }, 776 1, 777 {1.2}}, 778 {"var a = 1.2; return 2.6;", 779 1 * kPointerSize, 780 1, 781 7, 782 { 783 B(LdaConstant), U8(0), // 784 B(Star), R(0), // 785 B(LdaConstant), U8(1), // 786 B(Return) // 787 }, 788 2, 789 {1.2, 2.6}}, 790 {"var a = 3.14; return 3.14;", 791 1 * kPointerSize, 792 1, 793 7, 794 { 795 B(LdaConstant), U8(0), // 796 B(Star), R(0), // 797 B(LdaConstant), U8(1), // 798 B(Return) // 799 }, 800 2, 801 {3.14, 3.14}}, 802 {"var a;" 803 REPEAT_256(SPACE, " a = 1.414;") 804 " a = 3.14;", 805 1 * kPointerSize, 806 1, 807 1031, 808 { 809 REPEAT_256(COMMA, // 810 B(LdaConstant), U8(wide_idx++), // 811 B(Star), R(0)), // 812 B(LdaConstantWide), U16(wide_idx), // 813 B(Star), R(0), // 814 B(LdaUndefined), // 815 B(Return), // 816 }, 817 257, 818 {REPEAT_256(COMMA, 1.414), 819 3.14}} 820 }; 821 for (size_t i = 0; i < arraysize(snippets); i++) { 822 Handle<BytecodeArray> bytecode_array = 823 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 824 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 825 } 826 } 827 828 829 TEST(StringConstants) { 830 InitializedHandleScope handle_scope; 831 BytecodeGeneratorHelper helper; 832 833 ExpectedSnippet<const char*> snippets[] = { 834 {"return \"This is a string\";", 835 0, 836 1, 837 3, 838 { 839 B(LdaConstant), U8(0), // 840 B(Return) // 841 }, 842 1, 843 {"This is a string"}}, 844 {"var a = \"First string\"; return \"Second string\";", 845 1 * kPointerSize, 846 1, 847 7, 848 { 849 B(LdaConstant), U8(0), // 850 B(Star), R(0), // 851 B(LdaConstant), U8(1), // 852 B(Return) // 853 }, 854 2, 855 {"First string", "Second string"}}, 856 {"var a = \"Same string\"; return \"Same string\";", 857 1 * kPointerSize, 858 1, 859 7, 860 { 861 B(LdaConstant), U8(0), // 862 B(Star), R(0), // 863 B(LdaConstant), U8(0), // 864 B(Return) // 865 }, 866 1, 867 {"Same string"}}}; 868 869 for (size_t i = 0; i < arraysize(snippets); i++) { 870 Handle<BytecodeArray> bytecode_array = 871 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 872 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 873 } 874 } 875 876 877 TEST(PropertyLoads) { 878 InitializedHandleScope handle_scope; 879 BytecodeGeneratorHelper helper; 880 Zone zone; 881 882 FeedbackVectorSpec feedback_spec(&zone); 883 FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot(); 884 FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot(); 885 886 Handle<i::TypeFeedbackVector> vector = 887 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 888 889 // These are a hack used by the LoadICXXXWide tests below. 890 int wide_idx_1 = vector->GetIndex(slot1) - 2; 891 int wide_idx_2 = vector->GetIndex(slot1) - 2; 892 int wide_idx_3 = vector->GetIndex(slot1) - 2; 893 int wide_idx_4 = vector->GetIndex(slot1) - 2; 894 895 ExpectedSnippet<const char*> snippets[] = { 896 {"function f(a) { return a.name; }\nf({name : \"test\"})", 897 1 * kPointerSize, 898 2, 899 9, 900 { 901 B(Ldar), A(1, 2), // 902 B(Star), R(0), // 903 B(LoadICSloppy), R(0), U8(0), U8(vector->GetIndex(slot1)), // 904 B(Return), // 905 }, 906 1, 907 {"name"}}, 908 {"function f(a) { return a[\"key\"]; }\nf({key : \"test\"})", 909 1 * kPointerSize, 910 2, 911 9, 912 { 913 B(Ldar), A(1, 2), // 914 B(Star), R(0), // 915 B(LoadICSloppy), R(0), U8(0), U8(vector->GetIndex(slot1)), // 916 B(Return) // 917 }, 918 1, 919 {"key"}}, 920 {"function f(a) { return a[100]; }\nf({100 : \"test\"})", 921 1 * kPointerSize, 922 2, 923 10, 924 { 925 B(Ldar), A(1, 2), // 926 B(Star), R(0), // 927 B(LdaSmi8), U8(100), // 928 B(KeyedLoadICSloppy), R(0), U8(vector->GetIndex(slot1)), // 929 B(Return) // 930 }, 931 0}, 932 {"function f(a, b) { return a[b]; }\nf({arg : \"test\"}, \"arg\")", 933 1 * kPointerSize, 934 3, 935 10, 936 { 937 B(Ldar), A(1, 3), // 938 B(Star), R(0), // 939 B(Ldar), A(1, 2), // 940 B(KeyedLoadICSloppy), R(0), U8(vector->GetIndex(slot1)), // 941 B(Return) // 942 }, 943 0}, 944 {"function f(a) { var b = a.name; return a[-124]; }\n" 945 "f({\"-124\" : \"test\", name : 123 })", 946 2 * kPointerSize, 947 2, 948 20, 949 { 950 B(Ldar), A(1, 2), // 951 B(Star), R(1), // 952 B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot1)), // 953 B(Star), R(0), // 954 B(Ldar), A(1, 2), // 955 B(Star), R(1), // 956 B(LdaSmi8), U8(-124), // 957 B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot2)), // 958 B(Return), // 959 }, 960 1, 961 {"name"}}, 962 {"function f(a) { \"use strict\"; return a.name; }\nf({name : \"test\"})", 963 1 * kPointerSize, 964 2, 965 9, 966 { 967 B(Ldar), A(1, 2), // 968 B(Star), R(0), // 969 B(LoadICStrict), R(0), U8(0), U8(vector->GetIndex(slot1)), // 970 B(Return), // 971 }, 972 1, 973 {"name"}}, 974 {"function f(a, b) { \"use strict\"; return a[b]; }\n" 975 "f({arg : \"test\"}, \"arg\")", 976 1 * kPointerSize, 977 3, 978 10, 979 { 980 B(Ldar), A(1, 3), // 981 B(Star), R(0), // 982 B(Ldar), A(2, 3), // 983 B(KeyedLoadICStrict), R(0), U8(vector->GetIndex(slot1)), // 984 B(Return), // 985 }, 986 0}, 987 {"function f(a) {\n" 988 " var b;\n" 989 "b = a.name;" 990 REPEAT_127(SPACE, " b = a.name; ") 991 " return a.name; }\n" 992 "f({name : \"test\"})\n", 993 2 * kPointerSize, 994 2, 995 1291, 996 { 997 B(Ldar), A(1, 2), // 998 B(Star), R(1), // 999 B(LoadICSloppy), R(1), U8(0), U8(wide_idx_1 += 2), // 1000 B(Star), R(0), // 1001 REPEAT_127(COMMA, // 1002 B(Ldar), A(1, 2), // 1003 B(Star), R(1), // 1004 B(LoadICSloppy), R(1), U8(0), // 1005 U8((wide_idx_1 += 2)), // 1006 B(Star), R(0)), // 1007 B(Ldar), A(1, 2), // 1008 B(Star), R(1), // 1009 B(LoadICSloppyWide), R(1), U16(0), U16(wide_idx_1 + 2), // 1010 B(Return), // 1011 }, 1012 1, 1013 {"name"}}, 1014 {"function f(a) {\n" 1015 " 'use strict'; var b;\n" 1016 " b = a.name;\n" 1017 REPEAT_127(SPACE, " b = a.name; ") 1018 " return a.name; }\n" 1019 "f({name : \"test\"})\n", 1020 2 * kPointerSize, 1021 2, 1022 1291, 1023 { 1024 B(Ldar), A(1, 2), // 1025 B(Star), R(1), // 1026 B(LoadICStrict), R(1), U8(0), U8((wide_idx_2 += 2)), // 1027 B(Star), R(0), // 1028 REPEAT_127(COMMA, // 1029 B(Ldar), A(1, 2), // 1030 B(Star), R(1), // 1031 B(LoadICStrict), R(1), U8(0), // 1032 U8((wide_idx_2 += 2)), // 1033 B(Star), R(0)), // 1034 B(Ldar), A(1, 2), // 1035 B(Star), R(1), // 1036 B(LoadICStrictWide), R(1), U16(0), U16(wide_idx_2 + 2), // 1037 B(Return), // 1038 }, 1039 1, 1040 {"name"}}, 1041 {"function f(a, b) {\n" 1042 " var c;\n" 1043 " c = a[b];" 1044 REPEAT_127(SPACE, " c = a[b]; ") 1045 " return a[b]; }\n" 1046 "f({name : \"test\"}, \"name\")\n", 1047 2 * kPointerSize, 1048 3, 1049 1419, 1050 { 1051 B(Ldar), A(1, 3), // 1052 B(Star), R(1), // 1053 B(Ldar), A(2, 3), // 1054 B(KeyedLoadICSloppy), R(1), U8((wide_idx_3 += 2)), // 1055 B(Star), R(0), // 1056 REPEAT_127(COMMA, // 1057 B(Ldar), A(1, 3), // 1058 B(Star), R(1), // 1059 B(Ldar), A(2, 3), // 1060 B(KeyedLoadICSloppy), R(1), U8((wide_idx_3 += 2)), // 1061 B(Star), R(0)), // 1062 B(Ldar), A(1, 3), // 1063 B(Star), R(1), // 1064 B(Ldar), A(2, 3), // 1065 B(KeyedLoadICSloppyWide), R(1), U16(wide_idx_3 + 2), // 1066 B(Return), // 1067 }}, 1068 {"function f(a, b) {\n" 1069 " 'use strict'; var c;\n" 1070 " c = a[b];" 1071 REPEAT_127(SPACE, " c = a[b]; ") 1072 " return a[b]; }\n" 1073 "f({name : \"test\"}, \"name\")\n", 1074 2 * kPointerSize, 1075 3, 1076 1419, 1077 { 1078 B(Ldar), A(1, 3), // 1079 B(Star), R(1), // 1080 B(Ldar), A(2, 3), // 1081 B(KeyedLoadICStrict), R(1), U8((wide_idx_4 += 2)), // 1082 B(Star), R(0), // 1083 REPEAT_127(COMMA, // 1084 B(Ldar), A(1, 3), // 1085 B(Star), R(1), // 1086 B(Ldar), A(2, 3), // 1087 B(KeyedLoadICStrict), R(1), U8((wide_idx_4 += 2)), // 1088 B(Star), R(0)), // 1089 B(Ldar), A(1, 3), // 1090 B(Star), R(1), // 1091 B(Ldar), A(2, 3), // 1092 B(KeyedLoadICStrictWide), R(1), U16(wide_idx_4 + 2), // 1093 B(Return), // 1094 }}, 1095 }; 1096 for (size_t i = 0; i < arraysize(snippets); i++) { 1097 Handle<BytecodeArray> bytecode_array = 1098 helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName); 1099 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 1100 } 1101 } 1102 1103 1104 TEST(PropertyStores) { 1105 InitializedHandleScope handle_scope; 1106 BytecodeGeneratorHelper helper; 1107 Zone zone; 1108 1109 FeedbackVectorSpec feedback_spec(&zone); 1110 FeedbackVectorSlot slot1 = feedback_spec.AddStoreICSlot(); 1111 FeedbackVectorSlot slot2 = feedback_spec.AddStoreICSlot(); 1112 1113 Handle<i::TypeFeedbackVector> vector = 1114 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 1115 1116 // These are a hack used by the StoreICXXXWide tests below. 1117 int wide_idx_1 = vector->GetIndex(slot1) - 2; 1118 int wide_idx_2 = vector->GetIndex(slot1) - 2; 1119 int wide_idx_3 = vector->GetIndex(slot1) - 2; 1120 int wide_idx_4 = vector->GetIndex(slot1) - 2; 1121 1122 ExpectedSnippet<const char*> snippets[] = { 1123 {"function f(a) { a.name = \"val\"; }\nf({name : \"test\"})", 1124 kPointerSize, 1125 2, 1126 12, 1127 { 1128 B(Ldar), A(1, 2), // 1129 B(Star), R(0), // 1130 B(LdaConstant), U8(0), // 1131 B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), // 1132 B(LdaUndefined), // 1133 B(Return), // 1134 }, 1135 2, 1136 {"val", "name"}}, 1137 {"function f(a) { a[\"key\"] = \"val\"; }\nf({key : \"test\"})", 1138 kPointerSize, 1139 2, 1140 12, 1141 { 1142 B(Ldar), A(1, 2), // 1143 B(Star), R(0), // 1144 B(LdaConstant), U8(0), // 1145 B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), // 1146 B(LdaUndefined), // 1147 B(Return), // 1148 }, 1149 2, 1150 {"val", "key"}}, 1151 {"function f(a) { a[100] = \"val\"; }\nf({100 : \"test\"})", 1152 2 * kPointerSize, 1153 2, 1154 16, 1155 { 1156 B(Ldar), A(1, 2), // 1157 B(Star), R(0), // 1158 B(LdaSmi8), U8(100), // 1159 B(Star), R(1), // 1160 B(LdaConstant), U8(0), // 1161 B(KeyedStoreICSloppy), R(0), R(1), // 1162 U8(vector->GetIndex(slot1)), // 1163 B(LdaUndefined), // 1164 B(Return), // 1165 }, 1166 1, 1167 {"val"}}, 1168 {"function f(a, b) { a[b] = \"val\"; }\nf({arg : \"test\"}, \"arg\")", 1169 2 * kPointerSize, 1170 3, 1171 16, 1172 { 1173 B(Ldar), A(1, 3), // 1174 B(Star), R(0), // 1175 B(Ldar), A(2, 3), // 1176 B(Star), R(1), // 1177 B(LdaConstant), U8(0), // 1178 B(KeyedStoreICSloppy), R(0), R(1), // 1179 U8(vector->GetIndex(slot1)), // 1180 B(LdaUndefined), // 1181 B(Return), // 1182 }, 1183 1, 1184 {"val"}}, 1185 {"function f(a) { a.name = a[-124]; }\n" 1186 "f({\"-124\" : \"test\", name : 123 })", 1187 2 * kPointerSize, 1188 2, 1189 19, 1190 { 1191 B(Ldar), A(1, 2), // 1192 B(Star), R(0), // 1193 B(Ldar), A(1, 2), // 1194 B(Star), R(1), // 1195 B(LdaSmi8), U8(-124), // 1196 B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot1)), // 1197 B(StoreICSloppy), R(0), U8(0), U8(vector->GetIndex(slot2)), // 1198 B(LdaUndefined), // 1199 B(Return), // 1200 }, 1201 1, 1202 {"name"}}, 1203 {"function f(a) { \"use strict\"; a.name = \"val\"; }\n" 1204 "f({name : \"test\"})", 1205 kPointerSize, 1206 2, 1207 12, 1208 { 1209 B(Ldar), A(1, 2), // 1210 B(Star), R(0), // 1211 B(LdaConstant), U8(0), // 1212 B(StoreICStrict), R(0), U8(1), U8(vector->GetIndex(slot1)), // 1213 B(LdaUndefined), // 1214 B(Return), // 1215 }, 1216 2, 1217 {"val", "name"}}, 1218 {"function f(a, b) { \"use strict\"; a[b] = \"val\"; }\n" 1219 "f({arg : \"test\"}, \"arg\")", 1220 2 * kPointerSize, 1221 3, 1222 16, 1223 { 1224 B(Ldar), A(1, 3), // 1225 B(Star), R(0), // 1226 B(Ldar), A(2, 3), // 1227 B(Star), R(1), // 1228 B(LdaConstant), U8(0), // 1229 B(KeyedStoreICStrict), R(0), R(1), U8(vector->GetIndex(slot1)), // 1230 B(LdaUndefined), // 1231 B(Return), // 1232 }, 1233 1, 1234 {"val"}}, 1235 {"function f(a) {\n" 1236 "a.name = 1;" 1237 REPEAT_127(SPACE, " a.name = 1; ") 1238 " a.name = 2; }\n" 1239 "f({name : \"test\"})\n", 1240 kPointerSize, 1241 2, 1242 1294, 1243 { 1244 B(Ldar), A(1, 2), // 1245 B(Star), R(0), // 1246 B(LdaSmi8), U8(1), // 1247 B(StoreICSloppy), R(0), U8(0), U8((wide_idx_1 += 2)), // 1248 REPEAT_127(COMMA, // 1249 B(Ldar), A(1, 2), // 1250 B(Star), R(0), // 1251 B(LdaSmi8), U8(1), // 1252 B(StoreICSloppy), R(0), U8(0), // 1253 U8((wide_idx_1 += 2))), // 1254 B(Ldar), A(1, 2), // 1255 B(Star), R(0), // 1256 B(LdaSmi8), U8(2), // 1257 B(StoreICSloppyWide), R(0), U16(0), U16(wide_idx_1 + 2), // 1258 B(LdaUndefined), // 1259 B(Return), // 1260 }, 1261 1, 1262 {"name"}}, 1263 {"function f(a) {\n" 1264 " 'use strict';\n" 1265 " a.name = 1;" 1266 REPEAT_127(SPACE, " a.name = 1; ") 1267 " a.name = 2; }\n" 1268 "f({name : \"test\"})\n", 1269 kPointerSize, 1270 2, 1271 1294, 1272 { 1273 B(Ldar), A(1, 2), // 1274 B(Star), R(0), // 1275 B(LdaSmi8), U8(1), // 1276 B(StoreICStrict), R(0), U8(0), U8(wide_idx_2 += 2), // 1277 REPEAT_127(COMMA, // 1278 B(Ldar), A(1, 2), // 1279 B(Star), R(0), // 1280 B(LdaSmi8), U8(1), // 1281 B(StoreICStrict), R(0), U8(0), // 1282 U8((wide_idx_2 += 2))), // 1283 B(Ldar), A(1, 2), // 1284 B(Star), R(0), // 1285 B(LdaSmi8), U8(2), // 1286 B(StoreICStrictWide), R(0), U16(0), U16(wide_idx_2 + 2), // 1287 B(LdaUndefined), // 1288 B(Return), // 1289 }, 1290 1, 1291 {"name"}}, 1292 {"function f(a, b) {\n" 1293 " a[b] = 1;" 1294 REPEAT_127(SPACE, " a[b] = 1; ") 1295 " a[b] = 2; }\n" 1296 "f({name : \"test\"})\n", 1297 2 * kPointerSize, 1298 3, 1299 1809, 1300 { 1301 B(Ldar), A(1, 3), // 1302 B(Star), R(0), // 1303 B(Ldar), A(2, 3), // 1304 B(Star), R(1), // 1305 B(LdaSmi8), U8(1), // 1306 B(KeyedStoreICSloppy), R(0), R(1), U8(wide_idx_3 += 2), // 1307 REPEAT_127(COMMA, // 1308 B(Ldar), A(1, 3), // 1309 B(Star), R(0), // 1310 B(Ldar), A(2, 3), // 1311 B(Star), R(1), // 1312 B(LdaSmi8), U8(1), // 1313 B(KeyedStoreICSloppy), R(0), R(1), // 1314 U8((wide_idx_3 += 2))), // 1315 B(Ldar), A(1, 3), // 1316 B(Star), R(0), // 1317 B(Ldar), A(2, 3), // 1318 B(Star), R(1), // 1319 B(LdaSmi8), U8(2), // 1320 B(KeyedStoreICSloppyWide), R(0), R(1), U16(wide_idx_3 + 2), // 1321 B(LdaUndefined), // 1322 B(Return), // 1323 }}, 1324 {"function f(a, b) {\n" 1325 " 'use strict';\n" 1326 " a[b] = 1;" 1327 REPEAT_127(SPACE, " a[b] = 1; ") 1328 " a[b] = 2; }\n" 1329 "f({name : \"test\"})\n", 1330 2 * kPointerSize, 1331 3, 1332 1809, 1333 { 1334 B(Ldar), A(1, 3), // 1335 B(Star), R(0), // 1336 B(Ldar), A(2, 3), // 1337 B(Star), R(1), // 1338 B(LdaSmi8), U8(1), // 1339 B(KeyedStoreICStrict), R(0), R(1), U8(wide_idx_4 += 2), // 1340 REPEAT_127(COMMA, // 1341 B(Ldar), A(1, 3), // 1342 B(Star), R(0), // 1343 B(Ldar), A(2, 3), // 1344 B(Star), R(1), // 1345 B(LdaSmi8), U8(1), // 1346 B(KeyedStoreICStrict), R(0), R(1), // 1347 U8((wide_idx_4 += 2))), // 1348 B(Ldar), A(1, 3), // 1349 B(Star), R(0), // 1350 B(Ldar), A(2, 3), // 1351 B(Star), R(1), // 1352 B(LdaSmi8), U8(2), // 1353 B(KeyedStoreICStrictWide), R(0), R(1), U16(wide_idx_4 + 2), // 1354 B(LdaUndefined), // 1355 B(Return), // 1356 }}}; 1357 for (size_t i = 0; i < arraysize(snippets); i++) { 1358 Handle<BytecodeArray> bytecode_array = 1359 helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName); 1360 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 1361 } 1362 } 1363 1364 1365 #define FUNC_ARG "new (function Obj() { this.func = function() { return; }})()" 1366 1367 1368 TEST(PropertyCall) { 1369 InitializedHandleScope handle_scope; 1370 BytecodeGeneratorHelper helper; 1371 Zone zone; 1372 1373 FeedbackVectorSpec feedback_spec(&zone); 1374 FeedbackVectorSlot slot1 = feedback_spec.AddCallICSlot(); 1375 FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot(); 1376 1377 Handle<i::TypeFeedbackVector> vector = 1378 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 1379 1380 // These are a hack used by the CallWide test below. 1381 int wide_idx = vector->GetIndex(slot1) - 2; 1382 1383 ExpectedSnippet<const char*> snippets[] = { 1384 {"function f(a) { return a.func(); }\nf(" FUNC_ARG ")", 1385 2 * kPointerSize, 1386 2, 1387 16, 1388 { 1389 B(Ldar), A(1, 2), // 1390 B(Star), R(1), // 1391 B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)), // 1392 B(Star), R(0), // 1393 B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot1)), // 1394 B(Return), // 1395 }, 1396 1, 1397 {"func"}}, 1398 {"function f(a, b, c) { return a.func(b, c); }\nf(" FUNC_ARG ", 1, 2)", 1399 4 * kPointerSize, 1400 4, 1401 24, 1402 { 1403 B(Ldar), A(1, 4), // 1404 B(Star), R(1), // 1405 B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)), // 1406 B(Star), R(0), // 1407 B(Ldar), A(2, 4), // 1408 B(Star), R(2), // 1409 B(Ldar), A(3, 4), // 1410 B(Star), R(3), // 1411 B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot1)), // 1412 B(Return) // 1413 }, 1414 1, 1415 {"func"}}, 1416 {"function f(a, b) { return a.func(b + b, b); }\nf(" FUNC_ARG ", 1)", 1417 4 * kPointerSize, 1418 3, 1419 30, 1420 { 1421 B(Ldar), A(1, 3), // 1422 B(Star), R(1), // 1423 B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)), // 1424 B(Star), R(0), // 1425 B(Ldar), A(2, 3), // 1426 B(Star), R(3), // 1427 B(Ldar), A(2, 3), // 1428 B(Add), R(3), // 1429 B(Star), R(2), // 1430 B(Ldar), A(2, 3), // 1431 B(Star), R(3), // 1432 B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot1)), // 1433 B(Return), // 1434 }, 1435 1, 1436 {"func"}}, 1437 {"function f(a) {\n" 1438 " a.func;\n" 1439 REPEAT_127(SPACE, " a.func;\n") 1440 " return a.func(); }\nf(" FUNC_ARG ")", 1441 2 * kPointerSize, 1442 2, 1443 1044, 1444 { 1445 B(Ldar), A(1, 2), // 1446 B(Star), R(0), // 1447 B(LoadICSloppy), R(0), U8(0), U8(wide_idx += 2), // 1448 REPEAT_127(COMMA, // 1449 B(Ldar), A(1, 2), // 1450 B(Star), R(0), // 1451 B(LoadICSloppy), R(0), U8(0), U8((wide_idx += 2))), // 1452 B(Ldar), A(1, 2), // 1453 B(Star), R(1), // 1454 B(LoadICSloppyWide), R(1), U16(0), U16(wide_idx + 4), // 1455 B(Star), R(0), // 1456 B(CallWide), R(0), R(1), U16(0), U16(wide_idx + 2), // 1457 B(Return), // 1458 }, 1459 1, 1460 {"func"}}, 1461 }; 1462 for (size_t i = 0; i < arraysize(snippets); i++) { 1463 Handle<BytecodeArray> bytecode_array = 1464 helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName); 1465 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 1466 } 1467 } 1468 1469 1470 TEST(LoadGlobal) { 1471 InitializedHandleScope handle_scope; 1472 BytecodeGeneratorHelper helper; 1473 Zone zone; 1474 1475 FeedbackVectorSpec feedback_spec(&zone); 1476 FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot(); 1477 1478 Handle<i::TypeFeedbackVector> vector = 1479 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 1480 1481 // These are a hack used by the LdaGlobalXXXWide tests below. 1482 int wide_idx_1 = vector->GetIndex(slot) - 2; 1483 int wide_idx_2 = vector->GetIndex(slot) - 2; 1484 1485 ExpectedSnippet<const char*> snippets[] = { 1486 {"var a = 1;\nfunction f() { return a; }\nf()", 1487 0, 1488 1, 1489 4, 1490 { 1491 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), // 1492 B(Return) // 1493 }, 1494 1, 1495 {"a"}}, 1496 {"function t() { }\nfunction f() { return t; }\nf()", 1497 0, 1498 1, 1499 4, 1500 { 1501 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), // 1502 B(Return) // 1503 }, 1504 1, 1505 {"t"}}, 1506 {"'use strict'; var a = 1;\nfunction f() { return a; }\nf()", 1507 0, 1508 1, 1509 4, 1510 { 1511 B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot)), // 1512 B(Return) // 1513 }, 1514 1, 1515 {"a"}}, 1516 {"a = 1;\nfunction f() { return a; }\nf()", 1517 0, 1518 1, 1519 4, 1520 { 1521 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), // 1522 B(Return) // 1523 }, 1524 1, 1525 {"a"}}, 1526 {"a = 1;" 1527 "function f(b) {\n" 1528 " b.name;\n" 1529 REPEAT_127(SPACE, "b.name; ") 1530 " return a;" 1531 "}\nf({name: 1});", 1532 kPointerSize, 1533 2, 1534 1030, 1535 { 1536 B(Ldar), A(1, 2), // 1537 B(Star), R(0), // 1538 B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2), // 1539 REPEAT_127(COMMA, // 1540 B(Ldar), A(1, 2), // 1541 B(Star), R(0), // 1542 B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2)), // 1543 B(LdaGlobalSloppyWide), U16(1), U16(wide_idx_1 + 2), // 1544 B(Return), // 1545 }, 1546 2, 1547 {"name", "a"}}, 1548 {"a = 1;" 1549 "function f(b) {\n" 1550 " 'use strict';\n" 1551 " b.name\n" 1552 REPEAT_127(SPACE, "b.name; ") 1553 " return a;" 1554 "}\nf({name: 1});", 1555 kPointerSize, 1556 2, 1557 1030, 1558 { 1559 B(Ldar), A(1, 2), // 1560 B(Star), R(0), // 1561 B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2), // 1562 REPEAT_127(COMMA, // 1563 B(Ldar), A(1, 2), // 1564 B(Star), R(0), // 1565 B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2)), // 1566 B(LdaGlobalStrictWide), U16(1), U16(wide_idx_2 + 2), // 1567 B(Return), // 1568 }, 1569 2, 1570 {"name", "a"}}, 1571 }; 1572 1573 for (size_t i = 0; i < arraysize(snippets); i++) { 1574 Handle<BytecodeArray> bytecode_array = 1575 helper.MakeBytecode(snippets[i].code_snippet, "f"); 1576 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 1577 } 1578 } 1579 1580 1581 TEST(StoreGlobal) { 1582 InitializedHandleScope handle_scope; 1583 BytecodeGeneratorHelper helper; 1584 Zone zone; 1585 1586 FeedbackVectorSpec feedback_spec(&zone); 1587 FeedbackVectorSlot slot = feedback_spec.AddStoreICSlot(); 1588 1589 Handle<i::TypeFeedbackVector> vector = 1590 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 1591 1592 // These are a hack used by the StaGlobalXXXWide tests below. 1593 int wide_idx_1 = vector->GetIndex(slot) - 2; 1594 int wide_idx_2 = vector->GetIndex(slot) - 2; 1595 1596 ExpectedSnippet<const char*> snippets[] = { 1597 {"var a = 1;\nfunction f() { a = 2; }\nf()", 1598 0, 1599 1, 1600 7, 1601 { 1602 B(LdaSmi8), U8(2), // 1603 B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), // 1604 B(LdaUndefined), // 1605 B(Return) // 1606 }, 1607 1, 1608 {"a"}}, 1609 {"var a = \"test\"; function f(b) { a = b; }\nf(\"global\")", 1610 0, 1611 2, 1612 7, 1613 { 1614 B(Ldar), R(helper.kLastParamIndex), // 1615 B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), // 1616 B(LdaUndefined), // 1617 B(Return) // 1618 }, 1619 1, 1620 {"a"}}, 1621 {"'use strict'; var a = 1;\nfunction f() { a = 2; }\nf()", 1622 0, 1623 1, 1624 7, 1625 { 1626 B(LdaSmi8), U8(2), // 1627 B(StaGlobalStrict), U8(0), U8(vector->GetIndex(slot)), // 1628 B(LdaUndefined), // 1629 B(Return) // 1630 }, 1631 1, 1632 {"a"}}, 1633 {"a = 1;\nfunction f() { a = 2; }\nf()", 1634 0, 1635 1, 1636 7, 1637 { 1638 B(LdaSmi8), U8(2), // 1639 B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), // 1640 B(LdaUndefined), // 1641 B(Return) // 1642 }, 1643 1, 1644 {"a"}}, 1645 {"a = 1;" 1646 "function f(b) {" 1647 " b.name;\n" 1648 REPEAT_127(SPACE, "b.name; ") 1649 " a = 2; }\n" 1650 "f({name: 1});", 1651 kPointerSize, 1652 2, 1653 1033, 1654 { 1655 B(Ldar), A(1, 2), // 1656 B(Star), R(0), // 1657 B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2), // 1658 REPEAT_127(COMMA, // 1659 B(Ldar), A(1, 2), // 1660 B(Star), R(0), // 1661 B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2)), // 1662 B(LdaSmi8), U8(2), // 1663 B(StaGlobalSloppyWide), U16(1), U16(wide_idx_1 + 2), // 1664 B(LdaUndefined), // 1665 B(Return), // 1666 }, 1667 2, 1668 {"name", "a"}}, 1669 {"a = 1;" 1670 "function f(b) {\n" 1671 " 'use strict';\n" 1672 " b.name;\n" 1673 REPEAT_127(SPACE, "b.name; ") 1674 " a = 2; }\n" 1675 "f({name: 1});", 1676 kPointerSize, 1677 2, 1678 1033, 1679 { 1680 B(Ldar), A(1, 2), // 1681 B(Star), R(0), // 1682 B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2), // 1683 REPEAT_127(COMMA, // 1684 B(Ldar), A(1, 2), // 1685 B(Star), R(0), // 1686 B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2)), // 1687 B(LdaSmi8), U8(2), // 1688 B(StaGlobalStrictWide), U16(1), U16(wide_idx_2 + 2), // 1689 B(LdaUndefined), // 1690 B(Return), // 1691 }, 1692 2, 1693 {"name", "a"}}, 1694 }; 1695 1696 for (size_t i = 0; i < arraysize(snippets); i++) { 1697 Handle<BytecodeArray> bytecode_array = 1698 helper.MakeBytecode(snippets[i].code_snippet, "f"); 1699 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 1700 } 1701 } 1702 1703 1704 TEST(CallGlobal) { 1705 InitializedHandleScope handle_scope; 1706 BytecodeGeneratorHelper helper; 1707 Zone zone; 1708 1709 FeedbackVectorSpec feedback_spec(&zone); 1710 FeedbackVectorSlot slot1 = feedback_spec.AddCallICSlot(); 1711 FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot(); 1712 1713 Handle<i::TypeFeedbackVector> vector = 1714 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 1715 1716 ExpectedSnippet<const char*> snippets[] = { 1717 {"function t() { }\nfunction f() { return t(); }\nf()", 1718 2 * kPointerSize, 1719 1, 1720 14, 1721 { 1722 B(LdaUndefined), // 1723 B(Star), R(1), // 1724 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), // 1725 B(Star), R(0), // 1726 B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot1)), // 1727 B(Return) // 1728 }, 1729 1, 1730 {"t"}}, 1731 {"function t(a, b, c) { }\nfunction f() { return t(1, 2, 3); }\nf()", 1732 5 * kPointerSize, 1733 1, 1734 26, 1735 { 1736 B(LdaUndefined), // 1737 B(Star), R(1), // 1738 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), // 1739 B(Star), R(0), // 1740 B(LdaSmi8), U8(1), // 1741 B(Star), R(2), // 1742 B(LdaSmi8), U8(2), // 1743 B(Star), R(3), // 1744 B(LdaSmi8), U8(3), // 1745 B(Star), R(4), // 1746 B(Call), R(0), R(1), U8(3), U8(vector->GetIndex(slot1)), // 1747 B(Return) // 1748 }, 1749 1, 1750 {"t"}}, 1751 }; 1752 1753 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); 1754 for (size_t i = 0; i < num_snippets; i++) { 1755 Handle<BytecodeArray> bytecode_array = 1756 helper.MakeBytecode(snippets[i].code_snippet, "f"); 1757 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 1758 } 1759 } 1760 1761 1762 TEST(CallRuntime) { 1763 InitializedHandleScope handle_scope; 1764 BytecodeGeneratorHelper helper; 1765 1766 ExpectedSnippet<InstanceType> snippets[] = { 1767 { 1768 "function f() { %TheHole() }\nf()", 1769 0, 1770 1, 1771 7, 1772 { 1773 B(CallRuntime), U16(Runtime::kTheHole), R(0), U8(0), // 1774 B(LdaUndefined), // 1775 B(Return) // 1776 }, 1777 }, 1778 { 1779 "function f(a) { return %IsArray(a) }\nf(undefined)", 1780 1 * kPointerSize, 1781 2, 1782 10, 1783 { 1784 B(Ldar), A(1, 2), // 1785 B(Star), R(0), // 1786 B(CallRuntime), U16(Runtime::kIsArray), R(0), U8(1), // 1787 B(Return) // 1788 }, 1789 }, 1790 { 1791 "function f() { return %Add(1, 2) }\nf()", 1792 2 * kPointerSize, 1793 1, 1794 14, 1795 { 1796 B(LdaSmi8), U8(1), // 1797 B(Star), R(0), // 1798 B(LdaSmi8), U8(2), // 1799 B(Star), R(1), // 1800 B(CallRuntime), U16(Runtime::kAdd), R(0), U8(2), // 1801 B(Return) // 1802 }, 1803 }, 1804 { 1805 "function f() { return %spread_iterable([1]) }\nf()", 1806 2 * kPointerSize, 1807 1, 1808 15, 1809 { 1810 B(LdaUndefined), // 1811 B(Star), R(0), // 1812 B(CreateArrayLiteral), U8(0), U8(0), U8(3), // 1813 B(Star), R(1), // 1814 B(CallJSRuntime), U16(Context::SPREAD_ITERABLE_INDEX), R(0), // 1815 U8(1), // 1816 B(Return), // 1817 }, 1818 1, 1819 {InstanceType::FIXED_ARRAY_TYPE}, 1820 }, 1821 }; 1822 1823 for (size_t i = 0; i < arraysize(snippets); i++) { 1824 Handle<BytecodeArray> bytecode_array = 1825 helper.MakeBytecode(snippets[i].code_snippet, "f"); 1826 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 1827 } 1828 } 1829 1830 1831 TEST(IfConditions) { 1832 InitializedHandleScope handle_scope; 1833 BytecodeGeneratorHelper helper; 1834 1835 Handle<Object> unused = helper.factory()->undefined_value(); 1836 1837 ExpectedSnippet<Handle<Object>> snippets[] = { 1838 {"function f() { if (0) { return 1; } else { return -1; } } f()", 1839 0, 1840 1, 1841 3, 1842 { 1843 B(LdaSmi8), U8(-1), // 1844 B(Return), // 1845 }, 1846 0, 1847 {unused, unused, unused, unused, unused, unused}}, 1848 {"function f() { if ('lucky') { return 1; } else { return -1; } } f();", 1849 0, 1850 1, 1851 3, 1852 { 1853 B(LdaSmi8), U8(1), // 1854 B(Return), // 1855 }, 1856 0, 1857 {unused, unused, unused, unused, unused, unused}}, 1858 {"function f() { if (false) { return 1; } else { return -1; } } f();", 1859 0, 1860 1, 1861 3, 1862 { 1863 B(LdaSmi8), U8(-1), // 1864 B(Return), // 1865 }, 1866 0, 1867 {unused, unused, unused, unused, unused, unused}}, 1868 {"function f() { if (false) { return 1; } } f();", 1869 0, 1870 1, 1871 2, 1872 { 1873 B(LdaUndefined), // 1874 B(Return), // 1875 }, 1876 0, 1877 {unused, unused, unused, unused, unused, unused}}, 1878 {"function f() { var a = 1; if (a) { a += 1; } else { return 2; } } f();", 1879 2 * kPointerSize, 1880 1, 1881 23, 1882 { 1883 B(LdaSmi8), U8(1), // 1884 B(Star), R(0), // 1885 B(JumpIfToBooleanFalse), U8(14), // 1886 B(Ldar), R(0), // 1887 B(Star), R(1), // 1888 B(LdaSmi8), U8(1), // 1889 B(Add), R(1), // 1890 B(Star), R(0), // 1891 B(Jump), U8(5), // 1892 B(LdaSmi8), U8(2), // 1893 B(Return), // 1894 B(LdaUndefined), // 1895 B(Return), // 1896 }, 1897 0, 1898 {unused, unused, unused, unused, unused, unused}}, 1899 {"function f(a) { if (a <= 0) { return 200; } else { return -200; } }" 1900 "f(99);", 1901 kPointerSize, 1902 2, 1903 17, 1904 { 1905 B(Ldar), A(1, 2), // 1906 B(Star), R(0), // 1907 B(LdaZero), // 1908 B(TestLessThanOrEqual), R(0), // 1909 B(JumpIfFalse), U8(5), // 1910 B(LdaConstant), U8(0), // 1911 B(Return), // 1912 B(LdaConstant), U8(1), // 1913 B(Return), // 1914 B(LdaUndefined), // 1915 B(Return), // 1916 }, 1917 2, 1918 {helper.factory()->NewNumberFromInt(200), 1919 helper.factory()->NewNumberFromInt(-200), unused, unused, unused, 1920 unused}}, 1921 {"function f(a, b) { if (a in b) { return 200; } }" 1922 "f('prop', { prop: 'yes'});", 1923 kPointerSize, 1924 3, 1925 15, 1926 { 1927 B(Ldar), A(1, 3), // 1928 B(Star), R(0), // 1929 B(Ldar), A(2, 3), // 1930 B(TestIn), R(0), // 1931 B(JumpIfFalse), U8(5), // 1932 B(LdaConstant), U8(0), // 1933 B(Return), // 1934 B(LdaUndefined), // 1935 B(Return), // 1936 }, 1937 1, 1938 {helper.factory()->NewNumberFromInt(200), unused, unused, unused, unused, 1939 unused}}, 1940 {"function f(z) { var a = 0; var b = 0; if (a === 0.01) { " 1941 REPEAT_64(SPACE, "b = a; a = b; ") 1942 " return 200; } else { return -200; } } f(0.001)", 1943 3 * kPointerSize, 1944 2, 1945 282, 1946 { 1947 B(LdaZero), // 1948 B(Star), R(0), // 1949 B(LdaZero), // 1950 B(Star), R(1), // 1951 B(Ldar), R(0), // 1952 B(Star), R(2), // 1953 B(LdaConstant), U8(0), // 1954 B(TestEqualStrict), R(2), // 1955 B(JumpIfFalseConstant), U8(2), // 1956 B(Ldar), R(0), // 1957 REPEAT_64(COMMA, // 1958 B(Star), R(1), // 1959 B(Star), R(0)), // 1960 B(LdaConstant), U8(1), // 1961 B(Return), // 1962 B(LdaConstant), U8(3), // 1963 B(Return), // 1964 B(LdaUndefined), // 1965 B(Return)}, // 1966 4, 1967 {helper.factory()->NewHeapNumber(0.01), 1968 helper.factory()->NewNumberFromInt(200), 1969 helper.factory()->NewNumberFromInt(263), 1970 helper.factory()->NewNumberFromInt(-200), unused, unused}}, 1971 {"function f() { var a = 0; var b = 0; if (a) { " 1972 REPEAT_64(SPACE, "b = a; a = b; ") 1973 " return 200; } else { return -200; } } f()", 1974 2 * kPointerSize, 1975 1, 1976 276, 1977 { 1978 B(LdaZero), // 1979 B(Star), R(0), // 1980 B(LdaZero), // 1981 B(Star), R(1), // 1982 B(Ldar), R(0), // 1983 B(JumpIfToBooleanFalseConstant), U8(1), // 1984 B(Ldar), R(0), // 1985 REPEAT_64(COMMA, // 1986 B(Star), R(1), // 1987 B(Star), R(0)), // 1988 B(LdaConstant), U8(0), // 1989 B(Return), // 1990 B(LdaConstant), U8(2), // 1991 B(Return), // 1992 B(LdaUndefined), // 1993 B(Return)}, // 1994 3, 1995 {helper.factory()->NewNumberFromInt(200), 1996 helper.factory()->NewNumberFromInt(263), 1997 helper.factory()->NewNumberFromInt(-200), unused, unused, unused}}, 1998 1999 {"function f(a, b) {\n" 2000 " if (a == b) { return 1; }\n" 2001 " if (a === b) { return 1; }\n" 2002 " if (a < b) { return 1; }\n" 2003 " if (a > b) { return 1; }\n" 2004 " if (a <= b) { return 1; }\n" 2005 " if (a >= b) { return 1; }\n" 2006 " if (a in b) { return 1; }\n" 2007 " if (a instanceof b) { return 1; }\n" 2008 " return 0;\n" 2009 "} f(1, 1);", 2010 kPointerSize, 2011 3, 2012 106, 2013 { 2014 #define IF_CONDITION_RETURN(condition) \ 2015 B(Ldar), A(1, 3), \ 2016 B(Star), R(0), \ 2017 B(Ldar), A(2, 3), \ 2018 B(condition), R(0), \ 2019 B(JumpIfFalse), U8(5), \ 2020 B(LdaSmi8), U8(1), \ 2021 B(Return), 2022 IF_CONDITION_RETURN(TestEqual) // 2023 IF_CONDITION_RETURN(TestEqualStrict) // 2024 IF_CONDITION_RETURN(TestLessThan) // 2025 IF_CONDITION_RETURN(TestGreaterThan) // 2026 IF_CONDITION_RETURN(TestLessThanOrEqual) // 2027 IF_CONDITION_RETURN(TestGreaterThanOrEqual) // 2028 IF_CONDITION_RETURN(TestIn) // 2029 IF_CONDITION_RETURN(TestInstanceOf) // 2030 B(LdaZero), // 2031 B(Return)}, // 2032 #undef IF_CONDITION_RETURN 2033 0, 2034 {unused, unused, unused, unused, unused, unused}}, 2035 {"function f() {" 2036 " var a = 0;" 2037 " if (a) {" 2038 " return 20;" 2039 "} else {" 2040 " return -20;}" 2041 "};" 2042 "f();", 2043 1 * kPointerSize, 2044 1, 2045 13, 2046 { 2047 B(LdaZero), // 2048 B(Star), R(0), // 2049 B(JumpIfToBooleanFalse), U8(5), // 2050 B(LdaSmi8), U8(20), // 2051 B(Return), // 2052 B(LdaSmi8), U8(-20), // 2053 B(Return), // 2054 B(LdaUndefined), // 2055 B(Return) 2056 }, 2057 0, 2058 {unused, unused, unused, unused, unused, unused}}}; 2059 2060 for (size_t i = 0; i < arraysize(snippets); i++) { 2061 Handle<BytecodeArray> bytecode_array = 2062 helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName); 2063 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 2064 } 2065 } 2066 2067 2068 TEST(DeclareGlobals) { 2069 InitializedHandleScope handle_scope; 2070 BytecodeGeneratorHelper helper; 2071 Zone zone; 2072 2073 // Create different feedback vector specs to be precise on slot numbering. 2074 FeedbackVectorSpec feedback_spec_stores(&zone); 2075 FeedbackVectorSlot store_slot_1 = feedback_spec_stores.AddStoreICSlot(); 2076 FeedbackVectorSlot store_slot_2 = feedback_spec_stores.AddStoreICSlot(); 2077 USE(store_slot_1); 2078 2079 Handle<i::TypeFeedbackVector> store_vector = 2080 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec_stores); 2081 2082 FeedbackVectorSpec feedback_spec_loads(&zone); 2083 FeedbackVectorSlot load_slot_1 = feedback_spec_loads.AddLoadICSlot(); 2084 FeedbackVectorSlot call_slot_1 = feedback_spec_loads.AddCallICSlot(); 2085 2086 Handle<i::TypeFeedbackVector> load_vector = 2087 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec_loads); 2088 2089 ExpectedSnippet<InstanceType> snippets[] = { 2090 {"var a = 1;", 2091 4 * kPointerSize, 2092 1, 2093 30, 2094 { 2095 B(LdaConstant), U8(0), // 2096 B(Star), R(1), // 2097 B(LdaZero), // 2098 B(Star), R(2), // 2099 B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), // 2100 B(LdaConstant), U8(1), // 2101 B(Star), R(1), // 2102 B(LdaZero), // 2103 B(Star), R(2), // 2104 B(LdaSmi8), U8(1), // 2105 B(Star), R(3), // 2106 B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3), // 2107 B(LdaUndefined), // 2108 B(Return) // 2109 }, 2110 2, 2111 {InstanceType::FIXED_ARRAY_TYPE, 2112 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 2113 {"function f() {}", 2114 2 * kPointerSize, 2115 1, 2116 14, 2117 { 2118 B(LdaConstant), U8(0), // 2119 B(Star), R(0), // 2120 B(LdaZero), // 2121 B(Star), R(1), // 2122 B(CallRuntime), U16(Runtime::kDeclareGlobals), R(0), U8(2), // 2123 B(LdaUndefined), // 2124 B(Return) // 2125 }, 2126 1, 2127 {InstanceType::FIXED_ARRAY_TYPE}}, 2128 {"var a = 1;\na=2;", 2129 4 * kPointerSize, 2130 1, 2131 36, 2132 { 2133 B(LdaConstant), U8(0), // 2134 B(Star), R(1), // 2135 B(LdaZero), // 2136 B(Star), R(2), // 2137 B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), // 2138 B(LdaConstant), U8(1), // 2139 B(Star), R(1), // 2140 B(LdaZero), // 2141 B(Star), R(2), // 2142 B(LdaSmi8), U8(1), // 2143 B(Star), R(3), // 2144 B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3), // 2145 B(LdaSmi8), U8(2), // 2146 B(StaGlobalSloppy), U8(1), // 2147 U8(store_vector->GetIndex(store_slot_2)), // 2148 B(Star), R(0), // 2149 B(Return) // 2150 }, 2151 2, 2152 {InstanceType::FIXED_ARRAY_TYPE, 2153 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 2154 {"function f() {}\nf();", 2155 3 * kPointerSize, 2156 1, 2157 28, 2158 { 2159 B(LdaConstant), U8(0), // 2160 B(Star), R(1), // 2161 B(LdaZero), // 2162 B(Star), R(2), // 2163 B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), // 2164 B(LdaUndefined), // 2165 B(Star), R(2), // 2166 B(LdaGlobalSloppy), U8(1), // 2167 U8(load_vector->GetIndex(load_slot_1)), // 2168 B(Star), R(1), // 2169 B(Call), R(1), R(2), U8(0), // 2170 U8(load_vector->GetIndex(call_slot_1)), // 2171 B(Star), R(0), // 2172 B(Return) // 2173 }, 2174 2, 2175 {InstanceType::FIXED_ARRAY_TYPE, 2176 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 2177 }; 2178 2179 for (size_t i = 0; i < arraysize(snippets); i++) { 2180 Handle<BytecodeArray> bytecode_array = 2181 helper.MakeTopLevelBytecode(snippets[i].code_snippet); 2182 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 2183 } 2184 } 2185 2186 2187 TEST(BreakableBlocks) { 2188 InitializedHandleScope handle_scope; 2189 BytecodeGeneratorHelper helper; 2190 2191 ExpectedSnippet<int> snippets[] = { 2192 {"var x = 0;\n" 2193 "label: {\n" 2194 " x = x + 1;\n" 2195 " break label;\n" 2196 " x = x + 1;\n" 2197 "}\n" 2198 "return x;", 2199 2 * kPointerSize, 2200 1, 2201 16, 2202 { 2203 B(LdaZero), // 2204 B(Star), R(0), // 2205 B(Star), R(1), // 2206 B(LdaSmi8), U8(1), // 2207 B(Add), R(1), // 2208 B(Star), R(0), // 2209 B(Jump), U8(2), // 2210 B(Ldar), R(0), // 2211 B(Return) // 2212 }}, 2213 {"var sum = 0;\n" 2214 "outer: {\n" 2215 " for (var x = 0; x < 10; ++x) {\n" 2216 " for (var y = 0; y < 3; ++y) {\n" 2217 " ++sum;\n" 2218 " if (x + y == 12) { break outer; }\n" 2219 " }\n" 2220 " }\n" 2221 "}\n" 2222 "return sum;", 2223 5 * kPointerSize, 2224 1, 2225 72, 2226 { 2227 B(LdaZero), // 2228 B(Star), R(0), // 2229 B(LdaZero), // 2230 B(Star), R(1), // 2231 B(Ldar), R(1), // 2232 B(Star), R(3), // 2233 B(LdaSmi8), U8(10), // 2234 B(TestLessThan), R(3), // 2235 B(JumpIfFalse), U8(55), // 2236 B(LdaZero), // 2237 B(Star), R(2), // 2238 B(Ldar), R(2), // 2239 B(Star), R(3), // 2240 B(LdaSmi8), U8(3), // 2241 B(TestLessThan), R(3), // 2242 B(JumpIfFalse), U8(34), // 2243 B(Ldar), R(0), // 2244 B(ToNumber), // 2245 B(Inc), // 2246 B(Star), R(0), // 2247 B(Ldar), R(1), // 2248 B(Star), R(3), // 2249 B(Ldar), R(2), // 2250 B(Add), R(3), // 2251 B(Star), R(4), // 2252 B(LdaSmi8), U8(12), // 2253 B(TestEqual), R(4), // 2254 B(JumpIfFalse), U8(4), // 2255 B(Jump), U8(18), // 2256 B(Ldar), R(2), // 2257 B(ToNumber), // 2258 B(Inc), // 2259 B(Star), R(2), // 2260 B(Jump), U8(-40), // 2261 B(Ldar), R(1), // 2262 B(ToNumber), // 2263 B(Inc), // 2264 B(Star), R(1), // 2265 B(Jump), U8(-61), // 2266 B(Ldar), R(0), // 2267 B(Return), // 2268 }}, 2269 }; 2270 2271 for (size_t i = 0; i < arraysize(snippets); i++) { 2272 Handle<BytecodeArray> bytecode_array = 2273 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 2274 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 2275 } 2276 } 2277 2278 2279 TEST(BasicLoops) { 2280 InitializedHandleScope handle_scope; 2281 BytecodeGeneratorHelper helper; 2282 2283 ExpectedSnippet<int> snippets[] = { 2284 {"var x = 0;\n" 2285 "while (false) { x = 99; break; continue; }\n" 2286 "return x;", 2287 1 * kPointerSize, 2288 1, 2289 4, 2290 { 2291 B(LdaZero), // 2292 B(Star), R(0), // 2293 B(Return) // 2294 }}, 2295 {"var x = 0;" 2296 "while (false) {" 2297 " x = x + 1;" 2298 "};" 2299 "return x;", 2300 1 * kPointerSize, 2301 1, 2302 4, 2303 { 2304 B(LdaZero), // 2305 B(Star), R(0), // 2306 B(Return), // 2307 }, 2308 0}, 2309 {"var x = 0;" 2310 "var y = 1;" 2311 "while (x < 10) {" 2312 " y = y * 12;" 2313 " x = x + 1;" 2314 " if (x == 3) continue;" 2315 " if (x == 4) break;" 2316 "}" 2317 "return y;", 2318 3 * kPointerSize, 2319 1, 2320 64, 2321 { 2322 B(LdaZero), // 2323 B(Star), R(0), // 2324 B(LdaSmi8), U8(1), // 2325 B(Star), R(1), // 2326 B(Ldar), R(0), // 2327 B(Star), R(2), // 2328 B(LdaSmi8), U8(10), // 2329 B(TestLessThan), R(2), // 2330 B(JumpIfFalse), U8(46), // 2331 B(Ldar), R(1), // 2332 B(Star), R(2), // 2333 B(LdaSmi8), U8(12), // 2334 B(Mul), R(2), // 2335 B(Star), R(1), // 2336 B(Ldar), R(0), // 2337 B(Star), R(2), // 2338 B(LdaSmi8), U8(1), // 2339 B(Add), R(2), // 2340 B(Star), R(0), // 2341 B(Star), R(2), // 2342 B(LdaSmi8), U8(3), // 2343 B(TestEqual), R(2), // 2344 B(JumpIfFalse), U8(4), // 2345 B(Jump), U8(-38), // 2346 B(Ldar), R(0), // 2347 B(Star), R(2), // 2348 B(LdaSmi8), U8(4), // 2349 B(TestEqual), R(2), // 2350 B(JumpIfFalse), U8(4), // 2351 B(Jump), U8(4), // 2352 B(Jump), U8(-52), // 2353 B(Ldar), R(1), // 2354 B(Return), // 2355 }, 2356 0}, 2357 {"var i = 0;" 2358 "while (true) {" 2359 " if (i < 0) continue;" 2360 " if (i == 3) break;" 2361 " if (i == 4) break;" 2362 " if (i == 10) continue;" 2363 " if (i == 5) break;" 2364 " i = i + 1;" 2365 "}" 2366 "return i;", 2367 2 * kPointerSize, 2368 1, 2369 77, 2370 { 2371 B(LdaZero), // 2372 B(Star), R(0), // 2373 B(Ldar), R(0), // 2374 B(Star), R(1), // 2375 B(LdaZero), // 2376 B(TestLessThan), R(1), // 2377 B(JumpIfFalse), U8(4), // 2378 B(Jump), U8(-9), // 2379 B(Ldar), R(0), // 2380 B(Star), R(1), // 2381 B(LdaSmi8), U8(3), // 2382 B(TestEqual), R(1), // 2383 B(JumpIfFalse), U8(4), // 2384 B(Jump), U8(50), // 2385 B(Ldar), R(0), // 2386 B(Star), R(1), // 2387 B(LdaSmi8), U8(4), // 2388 B(TestEqual), R(1), // 2389 B(JumpIfFalse), U8(4), // 2390 B(Jump), U8(38), // 2391 B(Ldar), R(0), // 2392 B(Star), R(1), // 2393 B(LdaSmi8), U8(10), // 2394 B(TestEqual), R(1), // 2395 B(JumpIfFalse), U8(4), // 2396 B(Jump), U8(-45), // 2397 B(Ldar), R(0), // 2398 B(Star), R(1), // 2399 B(LdaSmi8), U8(5), // 2400 B(TestEqual), R(1), // 2401 B(JumpIfFalse), U8(4), // 2402 B(Jump), U8(14), // 2403 B(Ldar), R(0), // 2404 B(Star), R(1), // 2405 B(LdaSmi8), U8(1), // 2406 B(Add), R(1), // 2407 B(Star), R(0), // 2408 B(Jump), U8(-69), // 2409 B(Ldar), R(0), // 2410 B(Return), // 2411 }, 2412 0}, 2413 {"var i = 0;" 2414 "while (true) {" 2415 " while (i < 3) {" 2416 " if (i == 2) break;" 2417 " i = i + 1;" 2418 " }" 2419 " i = i + 1;" 2420 " break;" 2421 "}" 2422 "return i;", 2423 2 * kPointerSize, 2424 1, 2425 54, 2426 { 2427 B(LdaZero), // 2428 B(Star), R(0), // 2429 B(Ldar), R(0), // 2430 B(Star), R(1), // 2431 B(LdaSmi8), U8(3), // 2432 B(TestLessThan), R(1), // 2433 B(JumpIfFalse), U8(26), // 2434 B(Ldar), R(0), // 2435 B(Star), R(1), // 2436 B(LdaSmi8), U8(2), // 2437 B(TestEqual), R(1), // 2438 B(JumpIfFalse), U8(4), // 2439 B(Jump), U8(14), // 2440 B(Ldar), R(0), // 2441 B(Star), R(1), // 2442 B(LdaSmi8), U8(1), // 2443 B(Add), R(1), // 2444 B(Star), R(0), // 2445 B(Jump), U8(-32), // 2446 B(Ldar), R(0), // 2447 B(Star), R(1), // 2448 B(LdaSmi8), U8(1), // 2449 B(Add), R(1), // 2450 B(Star), R(0), // 2451 B(Jump), U8(4), // 2452 B(Jump), U8(-46), // 2453 B(Ldar), R(0), // 2454 B(Return), // 2455 }, 2456 0}, 2457 {"var x = 10;" 2458 "var y = 1;" 2459 "while (x) {" 2460 " y = y * 12;" 2461 " x = x - 1;" 2462 "}" 2463 "return y;", 2464 3 * kPointerSize, 2465 1, 2466 37, 2467 { 2468 B(LdaSmi8), U8(10), // 2469 B(Star), R(0), // 2470 B(LdaSmi8), U8(1), // 2471 B(Star), R(1), // 2472 B(Ldar), R(0), // 2473 B(JumpIfToBooleanFalse), U8(24), // 2474 B(Ldar), R(1), // 2475 B(Star), R(2), // 2476 B(LdaSmi8), U8(12), // 2477 B(Mul), R(2), // 2478 B(Star), R(1), // 2479 B(Ldar), R(0), // 2480 B(Star), R(2), // 2481 B(LdaSmi8), U8(1), // 2482 B(Sub), R(2), // 2483 B(Star), R(0), // 2484 B(Jump), U8(-24), // 2485 B(Ldar), R(1), // 2486 B(Return), // 2487 }, 2488 0}, 2489 {"var x = 0; var y = 1;" 2490 "do {" 2491 " y = y * 10;" 2492 " if (x == 5) break;" 2493 " if (x == 6) continue;" 2494 " x = x + 1;" 2495 "} while (x < 10);" 2496 "return y;", 2497 3 * kPointerSize, 2498 1, 2499 64, 2500 { 2501 B(LdaZero), // 2502 B(Star), R(0), // 2503 B(LdaSmi8), U8(1), // 2504 B(Star), R(1), // 2505 B(Ldar), R(1), // 2506 B(Star), R(2), // 2507 B(LdaSmi8), U8(10), // 2508 B(Mul), R(2), // 2509 B(Star), R(1), // 2510 B(Ldar), R(0), // 2511 B(Star), R(2), // 2512 B(LdaSmi8), U8(5), // 2513 B(TestEqual), R(2), // 2514 B(JumpIfFalse), U8(4), // 2515 B(Jump), U8(34), // 2516 B(Ldar), R(0), // 2517 B(Star), R(2), // 2518 B(LdaSmi8), U8(6), // 2519 B(TestEqual), R(2), // 2520 B(JumpIfFalse), U8(4), // 2521 B(Jump), U8(12), // 2522 B(Ldar), R(0), // 2523 B(Star), R(2), // 2524 B(LdaSmi8), U8(1), // 2525 B(Add), R(2), // 2526 B(Star), R(0), // 2527 B(Ldar), R(0), // 2528 B(Star), R(2), // 2529 B(LdaSmi8), U8(10), // 2530 B(TestLessThan), R(2), // 2531 B(JumpIfTrue), U8(-52), // 2532 B(Ldar), R(1), // 2533 B(Return), // 2534 }, 2535 0}, 2536 {"var x = 10;" 2537 "var y = 1;" 2538 "do {" 2539 " y = y * 12;" 2540 " x = x - 1;" 2541 "} while (x);" 2542 "return y;", 2543 3 * kPointerSize, 2544 1, 2545 35, 2546 { 2547 B(LdaSmi8), U8(10), // 2548 B(Star), R(0), // 2549 B(LdaSmi8), U8(1), // 2550 B(Star), R(1), // 2551 B(Ldar), R(1), // 2552 B(Star), R(2), // 2553 B(LdaSmi8), U8(12), // 2554 B(Mul), R(2), // 2555 B(Star), R(1), // 2556 B(Ldar), R(0), // 2557 B(Star), R(2), // 2558 B(LdaSmi8), U8(1), // 2559 B(Sub), R(2), // 2560 B(Star), R(0), // 2561 B(Ldar), R(0), // 2562 B(JumpIfToBooleanTrue), U8(-22), // 2563 B(Ldar), R(1), // 2564 B(Return), // 2565 }, 2566 0}, 2567 {"var x = 0; var y = 1;" 2568 "do {" 2569 " y = y * 10;" 2570 " if (x == 5) break;" 2571 " x = x + 1;" 2572 " if (x == 6) continue;" 2573 "} while (false);" 2574 "return y;", 2575 3 * kPointerSize, 2576 1, 2577 52, 2578 { 2579 B(LdaZero), // 2580 B(Star), R(0), // 2581 B(LdaSmi8), U8(1), // 2582 B(Star), R(1), // 2583 B(Ldar), R(1), // 2584 B(Star), R(2), // 2585 B(LdaSmi8), U8(10), // 2586 B(Mul), R(2), // 2587 B(Star), R(1), // 2588 B(Ldar), R(0), // 2589 B(Star), R(2), // 2590 B(LdaSmi8), U8(5), // 2591 B(TestEqual), R(2), // 2592 B(JumpIfFalse), U8(4), // 2593 B(Jump), U8(22), // 2594 B(Ldar), R(0), // 2595 B(Star), R(2), // 2596 B(LdaSmi8), U8(1), // 2597 B(Add), R(2), // 2598 B(Star), R(0), // 2599 B(Star), R(2), // 2600 B(LdaSmi8), U8(6), // 2601 B(TestEqual), R(2), // 2602 B(JumpIfFalse), U8(4), // 2603 B(Jump), U8(2), // 2604 B(Ldar), R(1), // 2605 B(Return), // 2606 }, 2607 0}, 2608 {"var x = 0; var y = 1;" 2609 "do {" 2610 " y = y * 10;" 2611 " if (x == 5) break;" 2612 " x = x + 1;" 2613 " if (x == 6) continue;" 2614 "} while (true);" 2615 "return y;", 2616 3 * kPointerSize, 2617 1, 2618 54, 2619 { 2620 B(LdaZero), // 2621 B(Star), R(0), // 2622 B(LdaSmi8), U8(1), // 2623 B(Star), R(1), // 2624 B(Ldar), R(1), // 2625 B(Star), R(2), // 2626 B(LdaSmi8), U8(10), // 2627 B(Mul), R(2), // 2628 B(Star), R(1), // 2629 B(Ldar), R(0), // 2630 B(Star), R(2), // 2631 B(LdaSmi8), U8(5), // 2632 B(TestEqual), R(2), // 2633 B(JumpIfFalse), U8(4), // 2634 B(Jump), U8(24), // 2635 B(Ldar), R(0), // 2636 B(Star), R(2), // 2637 B(LdaSmi8), U8(1), // 2638 B(Add), R(2), // 2639 B(Star), R(0), // 2640 B(Star), R(2), // 2641 B(LdaSmi8), U8(6), // 2642 B(TestEqual), R(2), // 2643 B(JumpIfFalse), U8(4), // 2644 B(Jump), U8(-40), // 2645 B(Jump), U8(-42), // 2646 B(Ldar), R(1), // 2647 B(Return), // 2648 }, 2649 0}, 2650 {"var x = 0; " 2651 "for (;;) {" 2652 " if (x == 1) break;" 2653 " if (x == 2) continue;" 2654 " x = x + 1;" 2655 "}", 2656 2 * kPointerSize, 2657 1, 2658 41, 2659 { 2660 B(LdaZero), // 2661 B(Star), R(0), // 2662 B(Ldar), R(0), // 2663 B(Star), R(1), // 2664 B(LdaSmi8), U8(1), // 2665 B(TestEqual), R(1), // 2666 B(JumpIfFalse), U8(4), // 2667 B(Jump), U8(26), // 2668 B(Ldar), R(0), // 2669 B(Star), R(1), // 2670 B(LdaSmi8), U8(2), // 2671 B(TestEqual), R(1), // 2672 B(JumpIfFalse), U8(4), // 2673 B(Jump), U8(-22), // 2674 B(Ldar), R(0), // 2675 B(Star), R(1), // 2676 B(LdaSmi8), U8(1), // 2677 B(Add), R(1), // 2678 B(Star), R(0), // 2679 B(Jump), U8(-34), // 2680 B(LdaUndefined), // 2681 B(Return), // 2682 }, 2683 0}, 2684 {"for (var x = 0;;) {" 2685 " if (x == 1) break;" 2686 " if (x == 2) continue;" 2687 " x = x + 1;" 2688 "}", 2689 2 * kPointerSize, 2690 1, 2691 41, 2692 { 2693 B(LdaZero), // 2694 B(Star), R(0), // 2695 B(Ldar), R(0), // 2696 B(Star), R(1), // 2697 B(LdaSmi8), U8(1), // 2698 B(TestEqual), R(1), // 2699 B(JumpIfFalse), U8(4), // 2700 B(Jump), U8(26), // 2701 B(Ldar), R(0), // 2702 B(Star), R(1), // 2703 B(LdaSmi8), U8(2), // 2704 B(TestEqual), R(1), // 2705 B(JumpIfFalse), U8(4), // 2706 B(Jump), U8(-22), // 2707 B(Ldar), R(0), // 2708 B(Star), R(1), // 2709 B(LdaSmi8), U8(1), // 2710 B(Add), R(1), // 2711 B(Star), R(0), // 2712 B(Jump), U8(-34), // 2713 B(LdaUndefined), // 2714 B(Return), // 2715 }, 2716 0}, 2717 {"var x = 0; " 2718 "for (;; x = x + 1) {" 2719 " if (x == 1) break;" 2720 " if (x == 2) continue;" 2721 "}", 2722 2 * kPointerSize, 2723 1, 2724 41, 2725 { 2726 B(LdaZero), // 2727 B(Star), R(0), // 2728 B(Ldar), R(0), // 2729 B(Star), R(1), // 2730 B(LdaSmi8), U8(1), // 2731 B(TestEqual), R(1), // 2732 B(JumpIfFalse), U8(4), // 2733 B(Jump), U8(26), // 2734 B(Ldar), R(0), // 2735 B(Star), R(1), // 2736 B(LdaSmi8), U8(2), // 2737 B(TestEqual), R(1), // 2738 B(JumpIfFalse), U8(4), // 2739 B(Jump), U8(2), // 2740 B(Ldar), R(0), // 2741 B(Star), R(1), // 2742 B(LdaSmi8), U8(1), // 2743 B(Add), R(1), // 2744 B(Star), R(0), // 2745 B(Jump), U8(-34), // 2746 B(LdaUndefined), // 2747 B(Return), // 2748 }, 2749 0}, 2750 {"for (var x = 0;; x = x + 1) {" 2751 " if (x == 1) break;" 2752 " if (x == 2) continue;" 2753 "}", 2754 2 * kPointerSize, 2755 1, 2756 41, 2757 { 2758 B(LdaZero), // 2759 B(Star), R(0), // 2760 B(Ldar), R(0), // 2761 B(Star), R(1), // 2762 B(LdaSmi8), U8(1), // 2763 B(TestEqual), R(1), // 2764 B(JumpIfFalse), U8(4), // 2765 B(Jump), U8(26), // 2766 B(Ldar), R(0), // 2767 B(Star), R(1), // 2768 B(LdaSmi8), U8(2), // 2769 B(TestEqual), R(1), // 2770 B(JumpIfFalse), U8(4), // 2771 B(Jump), U8(2), // 2772 B(Ldar), R(0), // 2773 B(Star), R(1), // 2774 B(LdaSmi8), U8(1), // 2775 B(Add), R(1), // 2776 B(Star), R(0), // 2777 B(Jump), U8(-34), // 2778 B(LdaUndefined), // 2779 B(Return), // 2780 }, 2781 0}, 2782 {"var u = 0;" 2783 "for (var i = 0; i < 100; i = i + 1) {" 2784 " u = u + 1;" 2785 " continue;" 2786 "}", 2787 3 * kPointerSize, 2788 1, 2789 42, 2790 { 2791 B(LdaZero), // 2792 B(Star), R(0), // 2793 B(LdaZero), // 2794 B(Star), R(1), // 2795 B(Ldar), R(1), // 2796 B(Star), R(2), // 2797 B(LdaSmi8), U8(100), // 2798 B(TestLessThan), R(2), // 2799 B(JumpIfFalse), U8(26), // 2800 B(Ldar), R(0), // 2801 B(Star), R(2), // 2802 B(LdaSmi8), U8(1), // 2803 B(Add), R(2), // 2804 B(Star), R(0), // 2805 B(Jump), U8(2), // 2806 B(Ldar), R(1), // 2807 B(Star), R(2), // 2808 B(LdaSmi8), U8(1), // 2809 B(Add), R(2), // 2810 B(Star), R(1), // 2811 B(Jump), U8(-32), // 2812 B(LdaUndefined), // 2813 B(Return), // 2814 }, 2815 0}, 2816 {"var y = 1;" 2817 "for (var x = 10; x; --x) {" 2818 " y = y * 12;" 2819 "}" 2820 "return y;", 2821 3 * kPointerSize, 2822 1, 2823 33, 2824 { 2825 B(LdaSmi8), U8(1), // 2826 B(Star), R(0), // 2827 B(LdaSmi8), U8(10), // 2828 B(Star), R(1), // 2829 B(Ldar), R(1), // 2830 B(JumpIfToBooleanFalse), U8(20), // 2831 B(Ldar), R(0), // 2832 B(Star), R(2), // 2833 B(LdaSmi8), U8(12), // 2834 B(Mul), R(2), // 2835 B(Star), R(0), // 2836 B(Ldar), R(1), // 2837 B(ToNumber), // 2838 B(Dec), // 2839 B(Star), R(1), // 2840 B(Jump), U8(-20), // 2841 B(Ldar), R(0), // 2842 B(Return), // 2843 }, 2844 0}, 2845 {"var x = 0;" 2846 "for (var i = 0; false; i++) {" 2847 " x = x + 1;" 2848 "};" 2849 "return x;", 2850 2 * kPointerSize, 2851 1, 2852 9, 2853 { 2854 B(LdaZero), // 2855 B(Star), R(0), // 2856 B(LdaZero), // 2857 B(Star), R(1), // 2858 B(Ldar), R(0), // 2859 B(Return), // 2860 }, 2861 0}, 2862 {"var x = 0;" 2863 "for (var i = 0; true; ++i) {" 2864 " x = x + 1;" 2865 " if (x == 20) break;" 2866 "};" 2867 "return x;", 2868 3 * kPointerSize, 2869 1, 2870 37, 2871 { 2872 B(LdaZero), // 2873 B(Star), R(0), // 2874 B(LdaZero), // 2875 B(Star), R(1), // 2876 B(Ldar), R(0), // 2877 B(Star), R(2), // 2878 B(LdaSmi8), U8(1), // 2879 B(Add), R(2), // 2880 B(Star), R(0), // 2881 B(Star), R(2), // 2882 B(LdaSmi8), U8(20), // 2883 B(TestEqual), R(2), // 2884 B(JumpIfFalse), U8(4), // 2885 B(Jump), U8(10), // 2886 B(Ldar), R(1), // 2887 B(ToNumber), // 2888 B(Inc), // 2889 B(Star), R(1), // 2890 B(Jump), U8(-26), // 2891 B(Ldar), R(0), // 2892 B(Return), // 2893 }, 2894 0}, 2895 }; 2896 2897 for (size_t i = 0; i < arraysize(snippets); i++) { 2898 Handle<BytecodeArray> bytecode_array = 2899 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 2900 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 2901 } 2902 } 2903 2904 2905 TEST(JumpsRequiringConstantWideOperands) { 2906 InitializedHandleScope handle_scope; 2907 BytecodeGeneratorHelper helper; 2908 2909 int constant_count = 0; 2910 ExpectedSnippet<Handle<Object>, 316> snippets[] = { 2911 { 2912 REPEAT_256(SPACE, "var x = 0.1;") 2913 REPEAT_32(SPACE, "var x = 0.2;") 2914 REPEAT_16(SPACE, "var x = 0.3;") 2915 REPEAT_8(SPACE, "var x = 0.4;") 2916 "for (var i = 0; i < 3; i++) {\n" 2917 " if (i == 1) continue;\n" 2918 " if (i == 2) break;\n" 2919 "}\n" 2920 "return 3;", 2921 kPointerSize * 3, 2922 1, 2923 1359, 2924 { 2925 #define L(c) B(LdaConstant), U8(c), B(Star), R(0) 2926 REPEAT_256(COMMA, L(constant_count++)), 2927 #undef L 2928 #define LW(c) B(LdaConstantWide), U16I(c), B(Star), R(0) 2929 REPEAT_32(COMMA, LW(constant_count)), 2930 REPEAT_16(COMMA, LW(constant_count)), 2931 REPEAT_8(COMMA, LW(constant_count)), 2932 #undef LW 2933 B(LdaZero), // 2934 B(Star), R(1), // 2935 B(Ldar), R(1), // 2936 B(Star), R(2), // 2937 B(LdaSmi8), U8(3), // 2938 B(TestLessThan), R(2), // 2939 B(JumpIfFalseConstantWide), U16(313), // 2940 B(Ldar), R(1), // 2941 B(Star), R(2), // 2942 B(LdaSmi8), U8(1), // 2943 B(TestEqual), R(2), // 2944 B(JumpIfFalseConstantWide), U16(312), // 2945 B(JumpConstantWide), U16(315), // 2946 B(Ldar), R(1), // 2947 B(Star), R(2), // 2948 B(LdaSmi8), U8(2), // 2949 B(TestEqual), R(2), // 2950 B(JumpIfFalseConstantWide), U16(312), // 2951 B(JumpConstantWide), U16(314), // 2952 B(Ldar), R(1), // 2953 B(ToNumber), // 2954 B(Star), R(2), // 2955 B(Inc), // 2956 B(Star), R(1), // 2957 B(Jump), U8(-47), // 2958 B(LdaSmi8), U8(3), // 2959 B(Return) // 2960 }, 2961 316, 2962 { 2963 #define S(x) CcTest::i_isolate()->factory()->NewNumber(x) 2964 REPEAT_256(COMMA, S(0.1)), 2965 REPEAT_32(COMMA, S(0.2)), 2966 REPEAT_16(COMMA, S(0.3)), 2967 REPEAT_8(COMMA, S(0.4)), 2968 #undef S 2969 #define N(x) CcTest::i_isolate()->factory()->NewNumberFromInt(x) 2970 N(6), N(41), N(13), N(17) 2971 #undef N 2972 }}}; 2973 2974 for (size_t i = 0; i < arraysize(snippets); i++) { 2975 Handle<BytecodeArray> bytecode_array = 2976 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 2977 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 2978 } 2979 } 2980 2981 2982 TEST(UnaryOperators) { 2983 InitializedHandleScope handle_scope; 2984 BytecodeGeneratorHelper helper; 2985 2986 ExpectedSnippet<int> snippets[] = { 2987 {"var x = 0;" 2988 "while (x != 10) {" 2989 " x = x + 10;" 2990 "}" 2991 "return x;", 2992 2 * kPointerSize, 2993 1, 2994 29, 2995 { 2996 B(LdaZero), // 2997 B(Star), R(0), // 2998 B(Ldar), R(0), // 2999 B(Star), R(1), // 3000 B(LdaSmi8), U8(10), // 3001 B(TestEqual), R(1), // 3002 B(LogicalNot), // 3003 B(JumpIfFalse), U8(14), // 3004 B(Ldar), R(0), // 3005 B(Star), R(1), // 3006 B(LdaSmi8), U8(10), // 3007 B(Add), R(1), // 3008 B(Star), R(0), // 3009 B(Jump), U8(-21), // 3010 B(Ldar), R(0), // 3011 B(Return), // 3012 }, 3013 0}, 3014 {"var x = false;" 3015 "do {" 3016 " x = !x;" 3017 "} while(x == false);" 3018 "return x;", 3019 2 * kPointerSize, 3020 1, 3021 20, 3022 { 3023 B(LdaFalse), // 3024 B(Star), R(0), // 3025 B(Ldar), R(0), // 3026 B(LogicalNot), // 3027 B(Star), R(0), // 3028 B(Ldar), R(0), // 3029 B(Star), R(1), // 3030 B(LdaFalse), // 3031 B(TestEqual), R(1), // 3032 B(JumpIfTrue), U8(-12), // 3033 B(Ldar), R(0), // 3034 B(Return), // 3035 }, 3036 0}, 3037 {"var x = 101;" 3038 "return void(x * 3);", 3039 2 * kPointerSize, 3040 1, 3041 12, 3042 { 3043 B(LdaSmi8), U8(101), // 3044 B(Star), R(0), // 3045 B(Star), R(1), // 3046 B(LdaSmi8), U8(3), // 3047 B(Mul), R(1), // 3048 B(LdaUndefined), // 3049 B(Return), // 3050 }, 3051 0}, 3052 {"var x = 1234;" 3053 "var y = void (x * x - 1);" 3054 "return y;", 3055 4 * kPointerSize, 3056 1, 3057 20, 3058 { 3059 B(LdaConstant), U8(0), // 3060 B(Star), R(0), // 3061 B(Star), R(2), // 3062 B(Ldar), R(0), // 3063 B(Mul), R(2), // 3064 B(Star), R(3), // 3065 B(LdaSmi8), U8(1), // 3066 B(Sub), R(3), // 3067 B(LdaUndefined), // 3068 B(Star), R(1), // 3069 B(Return), // 3070 }, 3071 1, 3072 {1234}}, 3073 {"var x = 13;" 3074 "return ~x;", 3075 2 * kPointerSize, 3076 1, 3077 11, 3078 { 3079 B(LdaSmi8), U8(13), // 3080 B(Star), R(0), // 3081 B(Star), R(1), // 3082 B(LdaSmi8), U8(-1), // 3083 B(BitwiseXor), R(1), // 3084 B(Return), // 3085 }, 3086 0}, 3087 {"var x = 13;" 3088 "return +x;", 3089 2 * kPointerSize, 3090 1, 3091 11, 3092 { 3093 B(LdaSmi8), U8(13), // 3094 B(Star), R(0), // 3095 B(Star), R(1), // 3096 B(LdaSmi8), U8(1), // 3097 B(Mul), R(1), // 3098 B(Return), // 3099 }, 3100 0}, 3101 {"var x = 13;" 3102 "return -x;", 3103 2 * kPointerSize, 3104 1, 3105 11, 3106 { 3107 B(LdaSmi8), U8(13), // 3108 B(Star), R(0), // 3109 B(Star), R(1), // 3110 B(LdaSmi8), U8(-1), // 3111 B(Mul), R(1), // 3112 B(Return), // 3113 }, 3114 0}}; 3115 3116 for (size_t i = 0; i < arraysize(snippets); i++) { 3117 Handle<BytecodeArray> bytecode_array = 3118 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 3119 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 3120 } 3121 } 3122 3123 3124 TEST(Typeof) { 3125 InitializedHandleScope handle_scope; 3126 BytecodeGeneratorHelper helper; 3127 Zone zone; 3128 3129 FeedbackVectorSpec feedback_spec(&zone); 3130 FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot(); 3131 3132 Handle<i::TypeFeedbackVector> vector = 3133 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 3134 3135 ExpectedSnippet<const char*> snippets[] = { 3136 {"function f() {\n" 3137 " var x = 13;\n" 3138 " return typeof(x);\n" 3139 "}; f();", 3140 kPointerSize, 3141 1, 3142 6, 3143 { 3144 B(LdaSmi8), U8(13), // 3145 B(Star), R(0), // 3146 B(TypeOf), // 3147 B(Return), // 3148 }}, 3149 {"var x = 13;\n" 3150 "function f() {\n" 3151 " return typeof(x);\n" 3152 "}; f();", 3153 0, 3154 1, 3155 5, 3156 { 3157 B(LdaGlobalInsideTypeofSloppy), U8(0), // 3158 U8(vector->GetIndex(slot)), // 3159 B(TypeOf), // 3160 B(Return), // 3161 }, 3162 1, 3163 {"x"}}, 3164 {"var x = 13;\n" 3165 "function f() {\n" 3166 " 'use strict';\n" 3167 " return typeof(x);\n" 3168 "}; f();", 3169 0, 3170 1, 3171 5, 3172 { 3173 B(LdaGlobalInsideTypeofStrict), U8(0), // 3174 U8(vector->GetIndex(slot)), // 3175 B(TypeOf), // 3176 B(Return), // 3177 }, 3178 1, 3179 {"x"}}, 3180 }; 3181 3182 for (size_t i = 0; i < arraysize(snippets); i++) { 3183 Handle<BytecodeArray> bytecode_array = 3184 helper.MakeBytecodeForFunction(snippets[i].code_snippet); 3185 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 3186 } 3187 } 3188 3189 3190 TEST(Delete) { 3191 InitializedHandleScope handle_scope; 3192 BytecodeGeneratorHelper helper; 3193 3194 int deep_elements_flags = 3195 ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos; 3196 int closure = Register::function_closure().index(); 3197 int first_context_slot = Context::MIN_CONTEXT_SLOTS; 3198 3199 ExpectedSnippet<InstanceType> snippets[] = { 3200 {"var a = {x:13, y:14}; return delete a.x;", 3201 2 * kPointerSize, 3202 1, 3203 13, 3204 { 3205 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // 3206 B(Star), R(0), // 3207 B(Star), R(1), // 3208 B(LdaConstant), U8(1), // 3209 B(DeletePropertySloppy), R(1), // 3210 B(Return) 3211 }, 3212 2, 3213 {InstanceType::FIXED_ARRAY_TYPE, 3214 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 3215 {"'use strict'; var a = {x:13, y:14}; return delete a.x;", 3216 2 * kPointerSize, 3217 1, 3218 13, 3219 { 3220 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // 3221 B(Star), R(0), // 3222 B(Star), R(1), // 3223 B(LdaConstant), U8(1), // 3224 B(DeletePropertyStrict), R(1), // 3225 B(Return) 3226 }, 3227 2, 3228 {InstanceType::FIXED_ARRAY_TYPE, 3229 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 3230 {"var a = {1:13, 2:14}; return delete a[2];", 3231 2 * kPointerSize, 3232 1, 3233 13, 3234 { 3235 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // 3236 B(Star), R(0), // 3237 B(Star), R(1), // 3238 B(LdaSmi8), U8(2), // 3239 B(DeletePropertySloppy), R(1), // 3240 B(Return) 3241 }, 3242 1, 3243 {InstanceType::FIXED_ARRAY_TYPE}}, 3244 {"var a = 10; return delete a;", 3245 1 * kPointerSize, 3246 1, 3247 6, 3248 { 3249 B(LdaSmi8), U8(10), // 3250 B(Star), R(0), // 3251 B(LdaFalse), // 3252 B(Return) 3253 }, 3254 0}, 3255 {"'use strict';" 3256 "var a = {1:10};" 3257 "(function f1() {return a;});" 3258 "return delete a[1];", 3259 2 * kPointerSize, 3260 1, 3261 27, 3262 { 3263 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3264 R(closure), U8(1), // 3265 B(PushContext), R(0), // 3266 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // 3267 B(StaContextSlot), R(0), U8(first_context_slot), // 3268 B(CreateClosure), U8(1), U8(0), // 3269 B(LdaContextSlot), R(0), U8(first_context_slot), // 3270 B(Star), R(1), // 3271 B(LdaSmi8), U8(1), // 3272 B(DeletePropertyStrict), R(1), // 3273 B(Return) 3274 }, 3275 2, 3276 {InstanceType::FIXED_ARRAY_TYPE, 3277 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3278 {"return delete 'test';", 3279 0 * kPointerSize, 3280 1, 3281 2, 3282 { 3283 B(LdaTrue), // 3284 B(Return) 3285 }, 3286 0}, 3287 }; 3288 3289 for (size_t i = 0; i < arraysize(snippets); i++) { 3290 Handle<BytecodeArray> bytecode_array = 3291 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 3292 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 3293 } 3294 } 3295 3296 3297 TEST(GlobalDelete) { 3298 InitializedHandleScope handle_scope; 3299 BytecodeGeneratorHelper helper; 3300 Zone zone; 3301 3302 int context = Register::function_context().index(); 3303 int native_context_index = Context::NATIVE_CONTEXT_INDEX; 3304 int global_context_index = Context::EXTENSION_INDEX; 3305 FeedbackVectorSpec feedback_spec(&zone); 3306 FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot(); 3307 3308 Handle<i::TypeFeedbackVector> vector = 3309 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 3310 3311 ExpectedSnippet<InstanceType> snippets[] = { 3312 {"var a = {x:13, y:14};\n function f() { return delete a.x; };\n f();", 3313 1 * kPointerSize, 3314 1, 3315 10, 3316 {B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), // 3317 B(Star), R(0), // 3318 B(LdaConstant), U8(1), // 3319 B(DeletePropertySloppy), R(0), // 3320 B(Return)}, 3321 2, 3322 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3323 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 3324 {"a = {1:13, 2:14};\n" 3325 "function f() {'use strict'; return delete a[1];};\n f();", 3326 1 * kPointerSize, 3327 1, 3328 10, 3329 {B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot)), // 3330 B(Star), R(0), // 3331 B(LdaSmi8), U8(1), // 3332 B(DeletePropertyStrict), R(0), // 3333 B(Return)}, 3334 1, 3335 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 3336 {"var a = {x:13, y:14};\n function f() { return delete a; };\n f();", 3337 2 * kPointerSize, 3338 1, 3339 15, 3340 {B(LdaContextSlot), R(context), U8(native_context_index), // 3341 B(Star), R(0), // 3342 B(LdaContextSlot), R(0), U8(global_context_index), // 3343 B(Star), R(1), // 3344 B(LdaConstant), U8(0), // 3345 B(DeletePropertySloppy), R(1), // 3346 B(Return)}, 3347 1, 3348 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 3349 {"b = 30;\n function f() { return delete b; };\n f();", 3350 2 * kPointerSize, 3351 1, 3352 15, 3353 {B(LdaContextSlot), R(context), U8(native_context_index), // 3354 B(Star), R(0), // 3355 B(LdaContextSlot), R(0), U8(global_context_index), // 3356 B(Star), R(1), // 3357 B(LdaConstant), U8(0), // 3358 B(DeletePropertySloppy), R(1), // 3359 B(Return)}, 3360 1, 3361 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}}; 3362 3363 for (size_t i = 0; i < arraysize(snippets); i++) { 3364 Handle<BytecodeArray> bytecode_array = 3365 helper.MakeBytecode(snippets[i].code_snippet, "f"); 3366 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 3367 } 3368 } 3369 3370 3371 TEST(FunctionLiterals) { 3372 InitializedHandleScope handle_scope; 3373 BytecodeGeneratorHelper helper; 3374 Zone zone; 3375 3376 FeedbackVectorSpec feedback_spec(&zone); 3377 FeedbackVectorSlot slot = feedback_spec.AddCallICSlot(); 3378 3379 Handle<i::TypeFeedbackVector> vector = 3380 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 3381 3382 ExpectedSnippet<InstanceType> snippets[] = { 3383 {"return function(){ }", 3384 0, 3385 1, 3386 4, 3387 { 3388 B(CreateClosure), U8(0), U8(0), // 3389 B(Return) // 3390 }, 3391 1, 3392 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3393 {"return (function(){ })()", 3394 2 * kPointerSize, 3395 1, 3396 14, 3397 { 3398 B(LdaUndefined), // 3399 B(Star), R(1), // 3400 B(CreateClosure), U8(0), U8(0), // 3401 B(Star), R(0), // 3402 B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot)), // 3403 B(Return) // 3404 }, 3405 1, 3406 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3407 {"return (function(x){ return x; })(1)", 3408 3 * kPointerSize, 3409 1, 3410 18, 3411 { 3412 B(LdaUndefined), // 3413 B(Star), R(1), // 3414 B(CreateClosure), U8(0), U8(0), // 3415 B(Star), R(0), // 3416 B(LdaSmi8), U8(1), // 3417 B(Star), R(2), // 3418 B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot)), // 3419 B(Return) // 3420 }, 3421 1, 3422 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3423 }; 3424 3425 for (size_t i = 0; i < arraysize(snippets); i++) { 3426 Handle<BytecodeArray> bytecode_array = 3427 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 3428 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 3429 } 3430 } 3431 3432 3433 TEST(RegExpLiterals) { 3434 InitializedHandleScope handle_scope; 3435 BytecodeGeneratorHelper helper; 3436 Zone zone; 3437 3438 FeedbackVectorSpec feedback_spec(&zone); 3439 FeedbackVectorSlot slot1 = feedback_spec.AddCallICSlot(); 3440 FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot(); 3441 uint8_t i_flags = JSRegExp::kIgnoreCase; 3442 3443 Handle<i::TypeFeedbackVector> vector = 3444 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 3445 3446 ExpectedSnippet<const char*> snippets[] = { 3447 {"return /ab+d/;", 3448 0 * kPointerSize, 3449 1, 3450 5, 3451 { 3452 B(CreateRegExpLiteral), U8(0), U8(0), U8(0), // 3453 B(Return), // 3454 }, 3455 1, 3456 {"ab+d"}}, 3457 {"return /(\\w+)\\s(\\w+)/i;", 3458 0 * kPointerSize, 3459 1, 3460 5, 3461 { 3462 B(CreateRegExpLiteral), U8(0), U8(0), U8(i_flags), // 3463 B(Return), // 3464 }, 3465 1, 3466 {"(\\w+)\\s(\\w+)"}}, 3467 {"return /ab+d/.exec('abdd');", 3468 3 * kPointerSize, 3469 1, 3470 22, 3471 { 3472 B(CreateRegExpLiteral), U8(0), U8(0), U8(0), // 3473 B(Star), R(1), // 3474 B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)), // 3475 B(Star), R(0), // 3476 B(LdaConstant), U8(2), // 3477 B(Star), R(2), // 3478 B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot1)), // 3479 B(Return), // 3480 }, 3481 3, 3482 {"ab+d", "exec", "abdd"}}, 3483 }; 3484 3485 for (size_t i = 0; i < arraysize(snippets); i++) { 3486 Handle<BytecodeArray> bytecode_array = 3487 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 3488 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 3489 } 3490 } 3491 3492 3493 TEST(RegExpLiteralsWide) { 3494 InitializedHandleScope handle_scope; 3495 BytecodeGeneratorHelper helper; 3496 Zone zone; 3497 3498 int wide_idx = 0; 3499 3500 ExpectedSnippet<InstanceType, 257> snippets[] = { 3501 {"var a;" REPEAT_256(SPACE, "a = 1.23;") "return /ab+d/;", 3502 1 * kPointerSize, 3503 1, 3504 1031, 3505 { 3506 REPEAT_256(COMMA, // 3507 B(LdaConstant), U8(wide_idx++), // 3508 B(Star), R(0)), // 3509 B(CreateRegExpLiteralWide), U16(256), U16(0), U8(0), // 3510 B(Return) // 3511 }, 3512 257, 3513 {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE), 3514 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 3515 }; 3516 3517 for (size_t i = 0; i < arraysize(snippets); i++) { 3518 Handle<BytecodeArray> bytecode_array = 3519 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 3520 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 3521 } 3522 } 3523 3524 3525 TEST(ArrayLiterals) { 3526 InitializedHandleScope handle_scope; 3527 BytecodeGeneratorHelper helper; 3528 Zone zone; 3529 3530 FeedbackVectorSpec feedback_spec(&zone); 3531 FeedbackVectorSlot slot1 = feedback_spec.AddKeyedStoreICSlot(); 3532 FeedbackVectorSlot slot2 = feedback_spec.AddKeyedStoreICSlot(); 3533 FeedbackVectorSlot slot3 = feedback_spec.AddKeyedStoreICSlot(); 3534 3535 Handle<i::TypeFeedbackVector> vector = 3536 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 3537 3538 int simple_flags = 3539 ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements; 3540 int deep_elements_flags = ArrayLiteral::kDisableMementos; 3541 ExpectedSnippet<InstanceType> snippets[] = { 3542 {"return [ 1, 2 ];", 3543 0, 3544 1, 3545 5, 3546 { 3547 B(CreateArrayLiteral), U8(0), U8(0), U8(simple_flags), // 3548 B(Return) // 3549 }, 3550 1, 3551 {InstanceType::FIXED_ARRAY_TYPE}}, 3552 {"var a = 1; return [ a, a + 1 ];", 3553 4 * kPointerSize, 3554 1, 3555 38, 3556 { 3557 B(LdaSmi8), U8(1), // 3558 B(Star), R(0), // 3559 B(CreateArrayLiteral), U8(0), U8(0), U8(3), // 3560 B(Star), R(2), // 3561 B(LdaZero), // 3562 B(Star), R(1), // 3563 B(Ldar), R(0), // 3564 B(KeyedStoreICSloppy), R(2), R(1), U8(vector->GetIndex(slot1)), // 3565 B(LdaSmi8), U8(1), // 3566 B(Star), R(1), // 3567 B(Ldar), R(0), // 3568 B(Star), R(3), // 3569 B(LdaSmi8), U8(1), // 3570 B(Add), R(3), // 3571 B(KeyedStoreICSloppy), R(2), R(1), U8(vector->GetIndex(slot1)), // 3572 B(Ldar), R(2), // 3573 B(Return), // 3574 }, 3575 1, 3576 {InstanceType::FIXED_ARRAY_TYPE}}, 3577 {"return [ [ 1, 2 ], [ 3 ] ];", 3578 0, 3579 1, 3580 5, 3581 { 3582 B(CreateArrayLiteral), U8(0), U8(2), U8(deep_elements_flags), // 3583 B(Return) // 3584 }, 3585 1, 3586 {InstanceType::FIXED_ARRAY_TYPE}}, 3587 {"var a = 1; return [ [ a, 2 ], [ a + 2 ] ];", 3588 6 * kPointerSize, 3589 1, 3590 68, 3591 { 3592 B(LdaSmi8), U8(1), // 3593 B(Star), R(0), // 3594 B(CreateArrayLiteral), U8(0), U8(2), U8(deep_elements_flags), // 3595 B(Star), R(2), // 3596 B(LdaZero), // 3597 B(Star), R(1), // 3598 B(CreateArrayLiteral), U8(1), U8(0), U8(simple_flags), // 3599 B(Star), R(4), // 3600 B(LdaZero), // 3601 B(Star), R(3), // 3602 B(Ldar), R(0), // 3603 B(KeyedStoreICSloppy), R(4), R(3), U8(vector->GetIndex(slot1)), // 3604 B(Ldar), R(4), // 3605 B(KeyedStoreICSloppy), R(2), R(1), U8(vector->GetIndex(slot3)), // 3606 B(LdaSmi8), U8(1), // 3607 B(Star), R(1), // 3608 B(CreateArrayLiteral), U8(2), U8(1), U8(simple_flags), // 3609 B(Star), R(4), // 3610 B(LdaZero), // 3611 B(Star), R(3), // 3612 B(Ldar), R(0), // 3613 B(Star), R(5), // 3614 B(LdaSmi8), U8(2), // 3615 B(Add), R(5), // 3616 B(KeyedStoreICSloppy), R(4), R(3), U8(vector->GetIndex(slot2)), // 3617 B(Ldar), R(4), // 3618 B(KeyedStoreICSloppy), R(2), R(1), U8(vector->GetIndex(slot3)), // 3619 B(Ldar), R(2), // 3620 B(Return), // 3621 }, 3622 3, 3623 {InstanceType::FIXED_ARRAY_TYPE, InstanceType::FIXED_ARRAY_TYPE, 3624 InstanceType::FIXED_ARRAY_TYPE}}, 3625 }; 3626 3627 for (size_t i = 0; i < arraysize(snippets); i++) { 3628 Handle<BytecodeArray> bytecode_array = 3629 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 3630 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 3631 } 3632 } 3633 3634 3635 TEST(ArrayLiteralsWide) { 3636 InitializedHandleScope handle_scope; 3637 BytecodeGeneratorHelper helper; 3638 Zone zone; 3639 3640 int wide_idx = 0; 3641 int simple_flags = 3642 ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements; 3643 3644 ExpectedSnippet<InstanceType, 257> snippets[] = { 3645 {"var a;" REPEAT_256(SPACE, "a = 1.23;") "return [ 1 , 2 ];", 3646 1 * kPointerSize, 3647 1, 3648 1031, 3649 { 3650 REPEAT_256(COMMA, // 3651 B(LdaConstant), U8(wide_idx++), // 3652 B(Star), R(0)), // 3653 B(CreateArrayLiteralWide), U16(256), U16(0), U8(simple_flags), // 3654 B(Return) // 3655 }, 3656 257, 3657 {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE), 3658 InstanceType::FIXED_ARRAY_TYPE}}, 3659 }; 3660 3661 for (size_t i = 0; i < arraysize(snippets); i++) { 3662 Handle<BytecodeArray> bytecode_array = 3663 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 3664 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 3665 } 3666 } 3667 3668 3669 TEST(ObjectLiterals) { 3670 InitializedHandleScope handle_scope; 3671 BytecodeGeneratorHelper helper; 3672 Zone zone; 3673 3674 FeedbackVectorSpec feedback_spec(&zone); 3675 FeedbackVectorSlot slot1 = feedback_spec.AddStoreICSlot(); 3676 3677 Handle<i::TypeFeedbackVector> vector = 3678 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 3679 3680 int simple_flags = ObjectLiteral::kFastElements | 3681 ObjectLiteral::kShallowProperties | 3682 ObjectLiteral::kDisableMementos; 3683 int deep_elements_flags = 3684 ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos; 3685 ExpectedSnippet<InstanceType> snippets[] = { 3686 {"return { };", 3687 0, 3688 1, 3689 5, 3690 { 3691 B(CreateObjectLiteral), U8(0), U8(0), U8(simple_flags), // 3692 B(Return) // 3693 }, 3694 1, 3695 {InstanceType::FIXED_ARRAY_TYPE}}, 3696 {"return { name: 'string', val: 9.2 };", 3697 0, 3698 1, 3699 5, 3700 { 3701 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // 3702 B(Return) // 3703 }, 3704 1, 3705 {InstanceType::FIXED_ARRAY_TYPE}}, 3706 {"var a = 1; return { name: 'string', val: a };", 3707 2 * kPointerSize, 3708 1, 3709 19, 3710 { 3711 B(LdaSmi8), U8(1), // 3712 B(Star), R(0), // 3713 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // 3714 B(Star), R(1), // 3715 B(Ldar), R(0), // 3716 B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), // 3717 B(Ldar), R(1), // 3718 B(Return), // 3719 }, 3720 2, 3721 {InstanceType::FIXED_ARRAY_TYPE, 3722 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 3723 {"var a = 1; return { val: a, val: a + 1 };", 3724 3 * kPointerSize, 3725 1, 3726 25, 3727 { 3728 B(LdaSmi8), U8(1), // 3729 B(Star), R(0), // 3730 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // 3731 B(Star), R(1), // 3732 B(Ldar), R(0), // 3733 B(Star), R(2), // 3734 B(LdaSmi8), U8(1), // 3735 B(Add), R(2), // 3736 B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), // 3737 B(Ldar), R(1), // 3738 B(Return), // 3739 }, 3740 2, 3741 {InstanceType::FIXED_ARRAY_TYPE, 3742 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 3743 {"return { func: function() { } };", 3744 1 * kPointerSize, 3745 1, 3746 16, 3747 { 3748 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // 3749 B(Star), R(0), // 3750 B(CreateClosure), U8(1), U8(0), // 3751 B(StoreICSloppy), R(0), U8(2), U8(vector->GetIndex(slot1)), // 3752 B(Ldar), R(0), // 3753 B(Return), // 3754 }, 3755 3, 3756 {InstanceType::FIXED_ARRAY_TYPE, 3757 InstanceType::SHARED_FUNCTION_INFO_TYPE, 3758 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 3759 {"return { func(a) { return a; } };", 3760 1 * kPointerSize, 3761 1, 3762 16, 3763 { 3764 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // 3765 B(Star), R(0), // 3766 B(CreateClosure), U8(1), U8(0), // 3767 B(StoreICSloppy), R(0), U8(2), U8(vector->GetIndex(slot1)), // 3768 B(Ldar), R(0), // 3769 B(Return), // 3770 }, 3771 3, 3772 {InstanceType::FIXED_ARRAY_TYPE, 3773 InstanceType::SHARED_FUNCTION_INFO_TYPE, 3774 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 3775 {"return { get a() { return 2; } };", 3776 5 * kPointerSize, 3777 1, 3778 29, 3779 { 3780 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // 3781 B(Star), R(0), // 3782 B(LdaConstant), U8(1), // 3783 B(Star), R(1), // 3784 B(CreateClosure), U8(2), U8(0), // 3785 B(Star), R(2), // 3786 B(LdaNull), // 3787 B(Star), R(3), // 3788 B(LdaZero), // 3789 B(Star), R(4), // 3790 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), // 3791 R(0), U8(5), // 3792 B(Ldar), R(0), // 3793 B(Return), // 3794 }, 3795 3, 3796 {InstanceType::FIXED_ARRAY_TYPE, 3797 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3798 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3799 {"return { get a() { return this.x; }, set a(val) { this.x = val } };", 3800 5 * kPointerSize, 3801 1, 3802 31, 3803 { 3804 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // 3805 B(Star), R(0), // 3806 B(LdaConstant), U8(1), // 3807 B(Star), R(1), // 3808 B(CreateClosure), U8(2), U8(0), // 3809 B(Star), R(2), // 3810 B(CreateClosure), U8(3), U8(0), // 3811 B(Star), R(3), // 3812 B(LdaZero), // 3813 B(Star), R(4), // 3814 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), // 3815 R(0), U8(5), // 3816 B(Ldar), R(0), // 3817 B(Return), // 3818 }, 3819 4, 3820 {InstanceType::FIXED_ARRAY_TYPE, 3821 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3822 InstanceType::SHARED_FUNCTION_INFO_TYPE, 3823 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3824 {"return { set b(val) { this.y = val } };", 3825 5 * kPointerSize, 3826 1, 3827 29, 3828 { 3829 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // 3830 B(Star), R(0), // 3831 B(LdaConstant), U8(1), // 3832 B(Star), R(1), // 3833 B(LdaNull), // 3834 B(Star), R(2), // 3835 B(CreateClosure), U8(2), U8(0), // 3836 B(Star), R(3), // 3837 B(LdaZero), // 3838 B(Star), R(4), // 3839 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), // 3840 R(0), U8(5), // 3841 B(Ldar), R(0), // 3842 B(Return), // 3843 }, 3844 3, 3845 {InstanceType::FIXED_ARRAY_TYPE, 3846 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3847 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3848 {"var a = 1; return { 1: a };", 3849 5 * kPointerSize, 3850 1, 3851 29, 3852 { 3853 B(LdaSmi8), U8(1), // 3854 B(Star), R(0), // 3855 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // 3856 B(Star), R(1), // 3857 B(LdaSmi8), U8(1), // 3858 B(Star), R(2), // 3859 B(Ldar), R(0), // 3860 B(Star), R(3), // 3861 B(LdaZero), // 3862 B(Star), R(4), // 3863 B(CallRuntime), U16(Runtime::kSetProperty), R(1), U8(4), // 3864 B(Ldar), R(1), // 3865 B(Return), // 3866 }, 3867 1, 3868 {InstanceType::FIXED_ARRAY_TYPE}}, 3869 {"return { __proto__: null }", 3870 2 * kPointerSize, 3871 1, 3872 17, 3873 { 3874 B(CreateObjectLiteral), U8(0), U8(0), U8(simple_flags), // 3875 B(Star), R(0), // 3876 B(LdaNull), B(Star), R(1), // 3877 B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(0), U8(2), // 3878 B(Ldar), R(0), // 3879 B(Return), // 3880 }, 3881 1, 3882 {InstanceType::FIXED_ARRAY_TYPE}}, 3883 {"var a = 'test'; return { [a]: 1 }", 3884 5 * kPointerSize, 3885 1, 3886 30, 3887 { 3888 B(LdaConstant), U8(0), // 3889 B(Star), R(0), // 3890 B(CreateObjectLiteral), U8(1), U8(0), U8(simple_flags), // 3891 B(Star), R(1), // 3892 B(Ldar), R(0), // 3893 B(ToName), // 3894 B(Star), R(2), // 3895 B(LdaSmi8), U8(1), // 3896 B(Star), R(3), // 3897 B(LdaZero), // 3898 B(Star), R(4), // 3899 B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), // 3900 U8(4), // 3901 B(Ldar), R(1), // 3902 B(Return), // 3903 }, 3904 2, 3905 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3906 InstanceType::FIXED_ARRAY_TYPE}}, 3907 {"var a = 'test'; return { val: a, [a]: 1 }", 3908 5 * kPointerSize, 3909 1, 3910 36, 3911 { 3912 B(LdaConstant), U8(0), // 3913 B(Star), R(0), // 3914 B(CreateObjectLiteral), U8(1), U8(0), U8(deep_elements_flags), // 3915 B(Star), R(1), // 3916 B(Ldar), R(0), // 3917 B(StoreICSloppy), R(1), U8(2), U8(vector->GetIndex(slot1)), // 3918 B(Ldar), R(0), // 3919 B(ToName), // 3920 B(Star), R(2), // 3921 B(LdaSmi8), U8(1), // 3922 B(Star), R(3), // 3923 B(LdaZero), // 3924 B(Star), R(4), // 3925 B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), // 3926 U8(4), // 3927 B(Ldar), R(1), // 3928 B(Return), // 3929 }, 3930 3, 3931 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3932 InstanceType::FIXED_ARRAY_TYPE, 3933 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 3934 {"var a = 'test'; return { [a]: 1, __proto__: {} }", 3935 5 * kPointerSize, 3936 1, 3937 41, 3938 { 3939 B(LdaConstant), U8(0), // 3940 B(Star), R(0), // 3941 B(CreateObjectLiteral), U8(1), U8(1), U8(simple_flags), // 3942 B(Star), R(1), // 3943 B(Ldar), R(0), // 3944 B(ToName), // 3945 B(Star), R(2), // 3946 B(LdaSmi8), U8(1), // 3947 B(Star), R(3), // 3948 B(LdaZero), // 3949 B(Star), R(4), // 3950 B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), // 3951 U8(4), // 3952 B(CreateObjectLiteral), U8(1), U8(0), U8(13), // 3953 B(Star), R(2), // 3954 B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(1), U8(2), // 3955 B(Ldar), R(1), // 3956 B(Return), // 3957 }, 3958 2, 3959 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3960 InstanceType::FIXED_ARRAY_TYPE}}, 3961 {"var n = 'name'; return { [n]: 'val', get a() { }, set a(b) {} };", 3962 5 * kPointerSize, 3963 1, 3964 64, 3965 { 3966 B(LdaConstant), U8(0), // 3967 B(Star), R(0), // 3968 B(CreateObjectLiteral), U8(1), U8(0), U8(simple_flags), // 3969 B(Star), R(1), // 3970 B(Ldar), R(0), // 3971 B(ToName), // 3972 B(Star), R(2), // 3973 B(LdaConstant), U8(2), // 3974 B(Star), R(3), // 3975 B(LdaZero), // 3976 B(Star), R(4), // 3977 B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), // 3978 U8(4), // 3979 B(LdaConstant), U8(3), // 3980 B(Star), R(2), // 3981 B(CreateClosure), U8(4), U8(0), // 3982 B(Star), R(3), // 3983 B(LdaZero), // 3984 B(Star), R(4), // 3985 B(CallRuntime), U16(Runtime::kDefineGetterPropertyUnchecked), // 3986 R(1), U8(4), // 3987 B(LdaConstant), U8(3), // 3988 B(Star), R(2), // 3989 B(CreateClosure), U8(5), U8(0), // 3990 B(Star), R(3), // 3991 B(LdaZero), // 3992 B(Star), R(4), // 3993 B(CallRuntime), U16(Runtime::kDefineSetterPropertyUnchecked), // 3994 R(1), U8(4), // 3995 B(Ldar), R(1), // 3996 B(Return), // 3997 }, 3998 6, 3999 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 4000 InstanceType::FIXED_ARRAY_TYPE, 4001 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 4002 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 4003 InstanceType::SHARED_FUNCTION_INFO_TYPE, 4004 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 4005 }; 4006 4007 for (size_t i = 0; i < arraysize(snippets); i++) { 4008 Handle<BytecodeArray> bytecode_array = 4009 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 4010 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 4011 } 4012 } 4013 4014 4015 TEST(ObjectLiteralsWide) { 4016 InitializedHandleScope handle_scope; 4017 BytecodeGeneratorHelper helper; 4018 Zone zone; 4019 4020 int deep_elements_flags = 4021 ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos; 4022 int wide_idx = 0; 4023 4024 ExpectedSnippet<InstanceType, 257> snippets[] = { 4025 {"var a;" REPEAT_256(SPACE, 4026 "a = 1.23;") "return { name: 'string', val: 9.2 };", 4027 1 * kPointerSize, 4028 1, 4029 1031, 4030 { 4031 REPEAT_256(COMMA, // 4032 B(LdaConstant), U8(wide_idx++), // 4033 B(Star), R(0)), // 4034 B(CreateObjectLiteralWide), U16(256), U16(0), // 4035 U8(deep_elements_flags), // 4036 B(Return) // 4037 }, 4038 257, 4039 {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE), 4040 InstanceType::FIXED_ARRAY_TYPE}}, 4041 }; 4042 4043 for (size_t i = 0; i < arraysize(snippets); i++) { 4044 Handle<BytecodeArray> bytecode_array = 4045 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 4046 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 4047 } 4048 } 4049 4050 4051 TEST(TopLevelObjectLiterals) { 4052 InitializedHandleScope handle_scope; 4053 BytecodeGeneratorHelper helper; 4054 4055 int has_function_flags = ObjectLiteral::kFastElements | 4056 ObjectLiteral::kHasFunction | 4057 ObjectLiteral::kDisableMementos; 4058 ExpectedSnippet<InstanceType> snippets[] = { 4059 {"var a = { func: function() { } };", 4060 5 * kPointerSize, 4061 1, 4062 48, 4063 { 4064 B(LdaConstant), U8(0), // 4065 B(Star), R(1), // 4066 B(LdaZero), // 4067 B(Star), R(2), // 4068 B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), // 4069 B(LdaConstant), U8(1), // 4070 B(Star), R(1), // 4071 B(LdaZero), // 4072 B(Star), R(2), // 4073 B(CreateObjectLiteral), U8(2), U8(0), U8(has_function_flags), // 4074 B(Star), R(4), // 4075 B(CreateClosure), U8(3), U8(1), // 4076 B(StoreICSloppy), R(4), U8(4), U8(3), // 4077 B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1), // 4078 B(Ldar), R(4), // 4079 B(Star), R(3), // 4080 B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3), // 4081 B(LdaUndefined), // 4082 B(Return), // 4083 }, 4084 5, 4085 {InstanceType::FIXED_ARRAY_TYPE, 4086 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 4087 InstanceType::FIXED_ARRAY_TYPE, 4088 InstanceType::SHARED_FUNCTION_INFO_TYPE, 4089 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 4090 }; 4091 4092 for (size_t i = 0; i < arraysize(snippets); i++) { 4093 Handle<BytecodeArray> bytecode_array = 4094 helper.MakeTopLevelBytecode(snippets[i].code_snippet); 4095 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 4096 } 4097 } 4098 4099 4100 TEST(TryCatch) { 4101 InitializedHandleScope handle_scope; 4102 BytecodeGeneratorHelper helper; 4103 4104 // TODO(rmcilroy): modify tests when we have real try catch support. 4105 ExpectedSnippet<int> snippets[] = { 4106 {"try { return 1; } catch(e) { return 2; }", 4107 kPointerSize, 4108 1, 4109 3, 4110 { 4111 B(LdaSmi8), U8(1), // 4112 B(Return), // 4113 }, 4114 0}, 4115 }; 4116 4117 for (size_t i = 0; i < arraysize(snippets); i++) { 4118 Handle<BytecodeArray> bytecode_array = 4119 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 4120 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 4121 } 4122 } 4123 4124 4125 TEST(TryFinally) { 4126 InitializedHandleScope handle_scope; 4127 BytecodeGeneratorHelper helper; 4128 4129 // TODO(rmcilroy): modify tests when we have real try finally support. 4130 ExpectedSnippet<int> snippets[] = { 4131 {"var a = 1; try { a = 2; } finally { a = 3; }", 4132 kPointerSize, 4133 1, 4134 14, 4135 { 4136 B(LdaSmi8), U8(1), // 4137 B(Star), R(0), // 4138 B(LdaSmi8), U8(2), // 4139 B(Star), R(0), // 4140 B(LdaSmi8), U8(3), // 4141 B(Star), R(0), // 4142 B(LdaUndefined), // 4143 B(Return), // 4144 }, 4145 0}, 4146 {"var a = 1; try { a = 2; } catch(e) { a = 20 } finally { a = 3; }", 4147 2 * kPointerSize, 4148 1, 4149 14, 4150 { 4151 B(LdaSmi8), U8(1), // 4152 B(Star), R(0), // 4153 B(LdaSmi8), U8(2), // 4154 B(Star), R(0), // 4155 B(LdaSmi8), U8(3), // 4156 B(Star), R(0), // 4157 B(LdaUndefined), // 4158 B(Return), // 4159 }, 4160 0}, 4161 }; 4162 4163 for (size_t i = 0; i < arraysize(snippets); i++) { 4164 Handle<BytecodeArray> bytecode_array = 4165 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 4166 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 4167 } 4168 } 4169 4170 4171 TEST(Throw) { 4172 InitializedHandleScope handle_scope; 4173 BytecodeGeneratorHelper helper; 4174 4175 // TODO(rmcilroy): modify tests when we have real try catch support. 4176 ExpectedSnippet<const char*> snippets[] = { 4177 {"throw 1;", 4178 0, 4179 1, 4180 3, 4181 { 4182 B(LdaSmi8), U8(1), // 4183 B(Throw), // 4184 }, 4185 0}, 4186 {"throw 'Error';", 4187 0, 4188 1, 4189 3, 4190 { 4191 B(LdaConstant), U8(0), // 4192 B(Throw), // 4193 }, 4194 1, 4195 {"Error"}}, 4196 {"var a = 1; if (a) { throw 'Error'; };", 4197 1 * kPointerSize, 4198 1, 4199 11, 4200 { 4201 B(LdaSmi8), U8(1), // 4202 B(Star), R(0), // 4203 B(JumpIfToBooleanFalse), U8(5), // 4204 B(LdaConstant), U8(0), // 4205 B(Throw), // 4206 B(LdaUndefined), // 4207 B(Return), // 4208 }, 4209 1, 4210 {"Error"}}, 4211 }; 4212 4213 for (size_t i = 0; i < arraysize(snippets); i++) { 4214 Handle<BytecodeArray> bytecode_array = 4215 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 4216 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 4217 } 4218 } 4219 4220 4221 TEST(CallNew) { 4222 InitializedHandleScope handle_scope; 4223 BytecodeGeneratorHelper helper; 4224 Zone zone; 4225 4226 FeedbackVectorSpec feedback_spec(&zone); 4227 FeedbackVectorSlot slot1 = feedback_spec.AddGeneralSlot(); 4228 FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot(); 4229 USE(slot1); 4230 4231 Handle<i::TypeFeedbackVector> vector = 4232 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 4233 4234 ExpectedSnippet<InstanceType> snippets[] = { 4235 {"function bar() { this.value = 0; }\n" 4236 "function f() { return new bar(); }\n" 4237 "f()", 4238 1 * kPointerSize, 4239 1, 4240 10, 4241 { 4242 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), // 4243 B(Star), R(0), // 4244 B(New), R(0), R(0), U8(0), // 4245 B(Return), // 4246 }, 4247 1, 4248 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 4249 {"function bar(x) { this.value = 18; this.x = x;}\n" 4250 "function f() { return new bar(3); }\n" 4251 "f()", 4252 2 * kPointerSize, 4253 1, 4254 14, 4255 { 4256 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), // 4257 B(Star), R(0), // 4258 B(LdaSmi8), U8(3), // 4259 B(Star), R(1), // 4260 B(New), R(0), R(1), U8(1), // 4261 B(Return), // 4262 }, 4263 1, 4264 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 4265 {"function bar(w, x, y, z) {\n" 4266 " this.value = 18;\n" 4267 " this.x = x;\n" 4268 " this.y = y;\n" 4269 " this.z = z;\n" 4270 "}\n" 4271 "function f() { return new bar(3, 4, 5); }\n" 4272 "f()", 4273 4 * kPointerSize, 4274 1, 4275 22, 4276 { 4277 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), // 4278 B(Star), R(0), // 4279 B(LdaSmi8), U8(3), // 4280 B(Star), R(1), // 4281 B(LdaSmi8), U8(4), // 4282 B(Star), R(2), // 4283 B(LdaSmi8), U8(5), // 4284 B(Star), R(3), // 4285 B(New), R(0), R(1), U8(3), // 4286 B(Return), // 4287 }, 4288 1, 4289 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 4290 }; 4291 4292 for (size_t i = 0; i < arraysize(snippets); i++) { 4293 Handle<BytecodeArray> bytecode_array = 4294 helper.MakeBytecode(snippets[i].code_snippet, "f"); 4295 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 4296 } 4297 } 4298 4299 4300 TEST(ContextVariables) { 4301 InitializedHandleScope handle_scope; 4302 BytecodeGeneratorHelper helper; 4303 Zone zone; 4304 4305 FeedbackVectorSpec feedback_spec(&zone); 4306 FeedbackVectorSlot slot = feedback_spec.AddCallICSlot(); 4307 4308 Handle<i::TypeFeedbackVector> vector = 4309 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 4310 4311 int closure = Register::function_closure().index(); 4312 int new_target = Register::new_target().index(); 4313 int first_context_slot = Context::MIN_CONTEXT_SLOTS; 4314 4315 // The wide check below relies on MIN_CONTEXT_SLOTS + 3 + 249 == 256, if this 4316 // ever changes, the REPEAT_XXX should be changed to output the correct number 4317 // of unique variables to trigger the wide slot load / store. 4318 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS + 3 + 249 == 256); 4319 int wide_slot = first_context_slot + 3; 4320 4321 ExpectedSnippet<InstanceType> snippets[] = { 4322 {"var a; return function() { a = 1; };", 4323 1 * kPointerSize, 4324 1, 4325 11, 4326 { 4327 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 4328 R(closure), U8(1), // 4329 B(PushContext), R(0), // 4330 B(CreateClosure), U8(0), U8(0), // 4331 B(Return), // 4332 }, 4333 1, 4334 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 4335 {"var a = 1; return function() { a = 2; };", 4336 1 * kPointerSize, 4337 1, 4338 16, 4339 { 4340 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 4341 R(closure), U8(1), // 4342 B(PushContext), R(0), // 4343 B(LdaSmi8), U8(1), // 4344 B(StaContextSlot), R(0), U8(first_context_slot), // 4345 B(CreateClosure), U8(0), U8(0), // 4346 B(Return), // 4347 }, 4348 1, 4349 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 4350 {"var a = 1; var b = 2; return function() { a = 2; b = 3 };", 4351 1 * kPointerSize, 4352 1, 4353 21, 4354 { 4355 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 4356 R(closure), U8(1), // 4357 B(PushContext), R(0), // 4358 B(LdaSmi8), U8(1), // 4359 B(StaContextSlot), R(0), U8(first_context_slot), // 4360 B(LdaSmi8), U8(2), // 4361 B(StaContextSlot), R(0), U8(first_context_slot + 1), // 4362 B(CreateClosure), U8(0), U8(0), // 4363 B(Return), // 4364 }, 4365 1, 4366 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 4367 {"var a; (function() { a = 2; })(); return a;", 4368 3 * kPointerSize, 4369 1, 4370 24, 4371 { 4372 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 4373 R(closure), U8(1), // 4374 B(PushContext), R(0), // 4375 B(LdaUndefined), // 4376 B(Star), R(2), // 4377 B(CreateClosure), U8(0), U8(0), // 4378 B(Star), R(1), // 4379 B(Call), R(1), R(2), U8(0), U8(vector->GetIndex(slot)), // 4380 B(LdaContextSlot), R(0), U8(first_context_slot), // 4381 B(Return), // 4382 }, 4383 1, 4384 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 4385 {"'use strict'; let a = 1; { let b = 2; return function() { a + b; }; }", 4386 4 * kPointerSize, 4387 1, 4388 44, 4389 { 4390 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 4391 R(closure), U8(1), // 4392 B(PushContext), R(0), // 4393 B(LdaTheHole), // 4394 B(StaContextSlot), R(0), U8(first_context_slot), // 4395 B(LdaSmi8), U8(1), // 4396 B(StaContextSlot), R(0), U8(first_context_slot), // 4397 B(LdaConstant), U8(0), // 4398 B(Star), R(2), // 4399 B(Ldar), R(closure), // 4400 B(Star), R(3), // 4401 B(CallRuntime), U16(Runtime::kPushBlockContext), R(2), U8(2), // 4402 B(PushContext), R(1), // 4403 B(LdaTheHole), // 4404 B(StaContextSlot), R(1), U8(first_context_slot), // 4405 B(LdaSmi8), U8(2), // 4406 B(StaContextSlot), R(1), U8(first_context_slot), // 4407 B(CreateClosure), U8(1), U8(0), // 4408 B(Return), // 4409 }, 4410 2, 4411 {InstanceType::FIXED_ARRAY_TYPE, 4412 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 4413 {"'use strict';\n" 4414 REPEAT_249_UNIQUE_VARS() 4415 "eval();" 4416 "var b = 100;" 4417 "return b", 4418 3 * kPointerSize, 4419 1, 4420 1041, 4421 { 4422 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // 4423 U8(1), // 4424 B(PushContext), R(0), // 4425 B(Ldar), THIS(1), // 4426 B(StaContextSlot), R(0), U8(first_context_slot), // 4427 B(CreateUnmappedArguments), // 4428 B(StaContextSlot), R(0), U8(first_context_slot + 1), // 4429 B(Ldar), R(new_target), // 4430 B(StaContextSlot), R(0), U8(first_context_slot + 2), // 4431 REPEAT_249(COMMA, // 4432 B(LdaZero), // 4433 B(StaContextSlot), R(0), U8(wide_slot++)), // 4434 B(LdaUndefined), // 4435 B(Star), R(2), // 4436 B(LdaGlobalStrict), U8(0), U8(1), // 4437 B(Star), R(1), // 4438 B(Call), R(1), R(2), U8(0), U8(0), // 4439 B(LdaSmi8), U8(100), // 4440 B(StaContextSlotWide), R(0), U16(256), // 4441 B(LdaContextSlotWide), R(0), U16(256), // 4442 B(Return), // 4443 }, 4444 1, 4445 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 4446 }; 4447 4448 for (size_t i = 0; i < arraysize(snippets); i++) { 4449 Handle<BytecodeArray> bytecode_array = 4450 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 4451 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 4452 } 4453 } 4454 4455 4456 TEST(ContextParameters) { 4457 InitializedHandleScope handle_scope; 4458 BytecodeGeneratorHelper helper; 4459 4460 int closure = Register::function_closure().index(); 4461 int first_context_slot = Context::MIN_CONTEXT_SLOTS; 4462 4463 ExpectedSnippet<InstanceType> snippets[] = { 4464 {"function f(arg1) { return function() { arg1 = 2; }; }", 4465 1 * kPointerSize, 4466 2, 4467 16, 4468 { 4469 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 4470 R(closure), U8(1), // 4471 B(PushContext), R(0), // 4472 B(Ldar), R(helper.kLastParamIndex), // 4473 B(StaContextSlot), R(0), U8(first_context_slot), // 4474 B(CreateClosure), U8(0), U8(0), // 4475 B(Return), // 4476 }, 4477 1, 4478 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 4479 {"function f(arg1) { var a = function() { arg1 = 2; }; return arg1; }", 4480 2 * kPointerSize, 4481 2, 4482 21, 4483 { 4484 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 4485 R(closure), U8(1), // 4486 B(PushContext), R(1), // 4487 B(Ldar), R(helper.kLastParamIndex), // 4488 B(StaContextSlot), R(1), U8(first_context_slot), // 4489 B(CreateClosure), U8(0), U8(0), // 4490 B(Star), R(0), // 4491 B(LdaContextSlot), R(1), U8(first_context_slot), // 4492 B(Return), // 4493 }, 4494 1, 4495 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 4496 {"function f(a1, a2, a3, a4) { return function() { a1 = a3; }; }", 4497 1 * kPointerSize, 4498 5, 4499 21, 4500 { 4501 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 4502 R(closure), U8(1), // 4503 B(PushContext), R(0), // 4504 B(Ldar), R(helper.kLastParamIndex - 3), // 4505 B(StaContextSlot), R(0), U8(first_context_slot + 1), // 4506 B(Ldar), R(helper.kLastParamIndex -1), // 4507 B(StaContextSlot), R(0), U8(first_context_slot), // 4508 B(CreateClosure), U8(0), U8(0), // 4509 B(Return), // 4510 }, 4511 1, 4512 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 4513 {"function f() { var self = this; return function() { self = 2; }; }", 4514 1 * kPointerSize, 4515 1, 4516 16, 4517 { 4518 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 4519 R(closure), U8(1), // 4520 B(PushContext), R(0), // 4521 B(Ldar), R(helper.kLastParamIndex), // 4522 B(StaContextSlot), R(0), U8(first_context_slot), // 4523 B(CreateClosure), U8(0), U8(0), // 4524 B(Return), // 4525 }, 4526 1, 4527 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 4528 }; 4529 4530 for (size_t i = 0; i < arraysize(snippets); i++) { 4531 Handle<BytecodeArray> bytecode_array = 4532 helper.MakeBytecodeForFunction(snippets[i].code_snippet); 4533 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 4534 } 4535 } 4536 4537 4538 TEST(OuterContextVariables) { 4539 InitializedHandleScope handle_scope; 4540 BytecodeGeneratorHelper helper; 4541 4542 int context = Register::function_context().index(); 4543 int first_context_slot = Context::MIN_CONTEXT_SLOTS; 4544 4545 ExpectedSnippet<InstanceType> snippets[] = { 4546 {"function Outer() {" 4547 " var outerVar = 1;" 4548 " function Inner(innerArg) {" 4549 " this.innerFunc = function() { return outerVar * innerArg; }" 4550 " }" 4551 " this.getInnerFunc = function() { return new Inner(1).innerFunc; }" 4552 "}" 4553 "var f = new Outer().getInnerFunc();", 4554 2 * kPointerSize, 4555 1, 4556 20, 4557 { 4558 B(Ldar), R(context), // 4559 B(Star), R(0), // 4560 B(LdaContextSlot), R(0), U8(Context::PREVIOUS_INDEX), // 4561 B(Star), R(0), // 4562 B(LdaContextSlot), R(0), U8(first_context_slot), // 4563 B(Star), R(1), // 4564 B(LdaContextSlot), R(context), U8(first_context_slot), // 4565 B(Mul), R(1), // 4566 B(Return), // 4567 }}, 4568 {"function Outer() {" 4569 " var outerVar = 1;" 4570 " function Inner(innerArg) {" 4571 " this.innerFunc = function() { outerVar = innerArg; }" 4572 " }" 4573 " this.getInnerFunc = function() { return new Inner(1).innerFunc; }" 4574 "}" 4575 "var f = new Outer().getInnerFunc();", 4576 2 * kPointerSize, 4577 1, 4578 21, 4579 { 4580 B(LdaContextSlot), R(context), U8(first_context_slot), // 4581 B(Star), R(0), // 4582 B(Ldar), R(context), // 4583 B(Star), R(1), // 4584 B(LdaContextSlot), R(1), U8(Context::PREVIOUS_INDEX), // 4585 B(Star), R(1), // 4586 B(Ldar), R(0), // 4587 B(StaContextSlot), R(1), U8(first_context_slot), // 4588 B(LdaUndefined), // 4589 B(Return), // 4590 }}, 4591 }; 4592 4593 for (size_t i = 0; i < arraysize(snippets); i++) { 4594 Handle<BytecodeArray> bytecode_array = 4595 helper.MakeBytecodeForFunctionNoFilter(snippets[i].code_snippet); 4596 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 4597 } 4598 } 4599 4600 4601 TEST(CountOperators) { 4602 InitializedHandleScope handle_scope; 4603 BytecodeGeneratorHelper helper; 4604 Zone zone; 4605 4606 FeedbackVectorSpec feedback_spec(&zone); 4607 FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot(); 4608 FeedbackVectorSlot slot2 = feedback_spec.AddStoreICSlot(); 4609 Handle<i::TypeFeedbackVector> vector = 4610 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 4611 4612 FeedbackVectorSpec store_feedback_spec(&zone); 4613 FeedbackVectorSlot store_slot = store_feedback_spec.AddStoreICSlot(); 4614 Handle<i::TypeFeedbackVector> store_vector = 4615 i::NewTypeFeedbackVector(helper.isolate(), &store_feedback_spec); 4616 4617 int closure = Register::function_closure().index(); 4618 int first_context_slot = Context::MIN_CONTEXT_SLOTS; 4619 4620 int object_literal_flags = 4621 ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos; 4622 int array_literal_flags = 4623 ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements; 4624 4625 ExpectedSnippet<InstanceType> snippets[] = { 4626 {"var a = 1; return ++a;", 4627 1 * kPointerSize, 4628 1, 4629 9, 4630 { 4631 B(LdaSmi8), U8(1), // 4632 B(Star), R(0), // 4633 B(ToNumber), // 4634 B(Inc), // 4635 B(Star), R(0), // 4636 B(Return), // 4637 }}, 4638 {"var a = 1; return a++;", 4639 2 * kPointerSize, 4640 1, 4641 13, 4642 { 4643 B(LdaSmi8), U8(1), // 4644 B(Star), R(0), // 4645 B(ToNumber), // 4646 B(Star), R(1), // 4647 B(Inc), // 4648 B(Star), R(0), // 4649 B(Ldar), R(1), // 4650 B(Return), // 4651 }}, 4652 {"var a = 1; return --a;", 4653 1 * kPointerSize, 4654 1, 4655 9, 4656 { 4657 B(LdaSmi8), U8(1), // 4658 B(Star), R(0), // 4659 B(ToNumber), // 4660 B(Dec), // 4661 B(Star), R(0), // 4662 B(Return), // 4663 }}, 4664 {"var a = 1; return a--;", 4665 2 * kPointerSize, 4666 1, 4667 13, 4668 { 4669 B(LdaSmi8), U8(1), // 4670 B(Star), R(0), // 4671 B(ToNumber), // 4672 B(Star), R(1), // 4673 B(Dec), // 4674 B(Star), R(0), // 4675 B(Ldar), R(1), // 4676 B(Return), // 4677 }}, 4678 {"var a = { val: 1 }; return a.val++;", 4679 3 * kPointerSize, 4680 1, 4681 23, 4682 { 4683 B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), // 4684 B(Star), R(0), // 4685 B(Star), R(1), // 4686 B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), // 4687 B(ToNumber), // 4688 B(Star), R(2), // 4689 B(Inc), // 4690 B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)), // 4691 B(Ldar), R(2), // 4692 B(Return), // 4693 }, 4694 2, 4695 {InstanceType::FIXED_ARRAY_TYPE, 4696 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 4697 {"var a = { val: 1 }; return --a.val;", 4698 2 * kPointerSize, 4699 1, 4700 19, 4701 { 4702 B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), // 4703 B(Star), R(0), // 4704 B(Star), R(1), // 4705 B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), // 4706 B(ToNumber), // 4707 B(Dec), // 4708 B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)), // 4709 B(Return), // 4710 }, 4711 2, 4712 {InstanceType::FIXED_ARRAY_TYPE, 4713 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 4714 {"var name = 'var'; var a = { val: 1 }; return a[name]--;", 4715 5 * kPointerSize, 4716 1, 4717 30, 4718 { 4719 B(LdaConstant), U8(0), // 4720 B(Star), R(0), // 4721 B(CreateObjectLiteral), U8(1), U8(0), U8(object_literal_flags), // 4722 B(Star), R(1), // 4723 B(Star), R(2), // 4724 B(Ldar), R(0), // 4725 B(Star), R(3), // 4726 B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot1)), // 4727 B(ToNumber), // 4728 B(Star), R(4), // 4729 B(Dec), // 4730 B(KeyedStoreICSloppy), R(2), R(3), U8(vector->GetIndex(slot2)), // 4731 B(Ldar), R(4), // 4732 B(Return), // 4733 }, 4734 2, 4735 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 4736 InstanceType::FIXED_ARRAY_TYPE}}, 4737 {"var name = 'var'; var a = { val: 1 }; return ++a[name];", 4738 4 * kPointerSize, 4739 1, 4740 26, 4741 { 4742 B(LdaConstant), U8(0), // 4743 B(Star), R(0), // 4744 B(CreateObjectLiteral), U8(1), U8(0), U8(object_literal_flags), // 4745 B(Star), R(1), // 4746 B(Star), R(2), // 4747 B(Ldar), R(0), // 4748 B(Star), R(3), // 4749 B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot1)), // 4750 B(ToNumber), // 4751 B(Inc), // 4752 B(KeyedStoreICSloppy), R(2), R(3), U8(vector->GetIndex(slot2)), // 4753 B(Return), // 4754 }, 4755 2, 4756 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 4757 InstanceType::FIXED_ARRAY_TYPE}}, 4758 {"var a = 1; var b = function() { return a }; return ++a;", 4759 2 * kPointerSize, 4760 1, 4761 26, 4762 { 4763 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // 4764 U8(1), // 4765 B(PushContext), R(1), // 4766 B(LdaSmi8), U8(1), // 4767 B(StaContextSlot), R(1), U8(first_context_slot), // 4768 B(CreateClosure), U8(0), U8(0), // 4769 B(Star), R(0), // 4770 B(LdaContextSlot), R(1), U8(first_context_slot), // 4771 B(ToNumber), // 4772 B(Inc), // 4773 B(StaContextSlot), R(1), U8(first_context_slot), // 4774 B(Return), // 4775 }, 4776 1, 4777 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 4778 {"var a = 1; var b = function() { return a }; return a--;", 4779 3 * kPointerSize, 4780 1, 4781 30, 4782 { 4783 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // 4784 U8(1), // 4785 B(PushContext), R(1), // 4786 B(LdaSmi8), U8(1), // 4787 B(StaContextSlot), R(1), U8(first_context_slot), // 4788 B(CreateClosure), U8(0), U8(0), // 4789 B(Star), R(0), // 4790 B(LdaContextSlot), R(1), U8(first_context_slot), // 4791 B(ToNumber), // 4792 B(Star), R(2), // 4793 B(Dec), // 4794 B(StaContextSlot), R(1), U8(first_context_slot), // 4795 B(Ldar), R(2), // 4796 B(Return), // 4797 }, 4798 1, 4799 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 4800 {"var idx = 1; var a = [1, 2]; return a[idx++] = 2;", 4801 4 * kPointerSize, 4802 1, 4803 27, 4804 { 4805 B(LdaSmi8), U8(1), // 4806 B(Star), R(0), // 4807 B(CreateArrayLiteral), U8(0), U8(0), U8(array_literal_flags), // 4808 B(Star), R(1), // 4809 B(Star), R(2), // 4810 B(Ldar), R(0), // 4811 B(ToNumber), // 4812 B(Star), R(3), // 4813 B(Inc), // 4814 B(Star), R(0), // 4815 B(LdaSmi8), U8(2), // 4816 B(KeyedStoreICSloppy), R(2), R(3), // 4817 U8(store_vector->GetIndex(store_slot)), // 4818 B(Return), // 4819 }, 4820 1, 4821 {InstanceType::FIXED_ARRAY_TYPE}}, 4822 }; 4823 4824 for (size_t i = 0; i < arraysize(snippets); i++) { 4825 Handle<BytecodeArray> bytecode_array = 4826 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 4827 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 4828 } 4829 } 4830 4831 4832 TEST(GlobalCountOperators) { 4833 InitializedHandleScope handle_scope; 4834 BytecodeGeneratorHelper helper; 4835 Zone zone; 4836 4837 FeedbackVectorSpec feedback_spec(&zone); 4838 FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot(); 4839 FeedbackVectorSlot slot2 = feedback_spec.AddStoreICSlot(); 4840 4841 Handle<i::TypeFeedbackVector> vector = 4842 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 4843 4844 ExpectedSnippet<const char*> snippets[] = { 4845 {"var global = 1;\nfunction f() { return ++global; }\nf()", 4846 0, 4847 1, 4848 9, 4849 { 4850 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), // 4851 B(ToNumber), // 4852 B(Inc), // 4853 B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), // 4854 B(Return), // 4855 }, 4856 1, 4857 {"global"}}, 4858 {"var global = 1;\nfunction f() { return global--; }\nf()", 4859 1 * kPointerSize, 4860 1, 4861 13, 4862 { 4863 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), // 4864 B(ToNumber), // 4865 B(Star), R(0), // 4866 B(Dec), // 4867 B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), // 4868 B(Ldar), R(0), // 4869 B(Return), 4870 }, 4871 1, 4872 {"global"}}, 4873 {"unallocated = 1;\nfunction f() { 'use strict'; return --unallocated; }" 4874 "f()", 4875 0, 4876 1, 4877 9, 4878 { 4879 B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot1)), // 4880 B(ToNumber), // 4881 B(Dec), // 4882 B(StaGlobalStrict), U8(0), U8(vector->GetIndex(slot2)), // 4883 B(Return), // 4884 }, 4885 1, 4886 {"unallocated"}}, 4887 {"unallocated = 1;\nfunction f() { return unallocated++; }\nf()", 4888 1 * kPointerSize, 4889 1, 4890 13, 4891 { 4892 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), // 4893 B(ToNumber), // 4894 B(Star), R(0), // 4895 B(Inc), // 4896 B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), // 4897 B(Ldar), R(0), // 4898 B(Return), 4899 }, 4900 1, 4901 {"unallocated"}}, 4902 }; 4903 4904 for (size_t i = 0; i < arraysize(snippets); i++) { 4905 Handle<BytecodeArray> bytecode_array = 4906 helper.MakeBytecode(snippets[i].code_snippet, "f"); 4907 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 4908 } 4909 } 4910 4911 4912 TEST(CompoundExpressions) { 4913 InitializedHandleScope handle_scope; 4914 BytecodeGeneratorHelper helper; 4915 Zone zone; 4916 4917 int closure = Register::function_closure().index(); 4918 int first_context_slot = Context::MIN_CONTEXT_SLOTS; 4919 4920 FeedbackVectorSpec feedback_spec(&zone); 4921 FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot(); 4922 FeedbackVectorSlot slot2 = feedback_spec.AddStoreICSlot(); 4923 4924 Handle<i::TypeFeedbackVector> vector = 4925 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 4926 4927 int object_literal_flags = 4928 ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos; 4929 ExpectedSnippet<InstanceType> snippets[] = { 4930 {"var a = 1; a += 2;", 4931 2 * kPointerSize, 4932 1, 4933 14, 4934 { 4935 B(LdaSmi8), U8(1), // 4936 B(Star), R(0), // 4937 B(Star), R(1), // 4938 B(LdaSmi8), U8(2), // 4939 B(Add), R(1), // 4940 B(Star), R(0), // 4941 B(LdaUndefined), // 4942 B(Return), // 4943 }}, 4944 {"var a = 1; a /= 2;", 4945 2 * kPointerSize, 4946 1, 4947 14, 4948 { 4949 B(LdaSmi8), U8(1), // 4950 B(Star), R(0), // 4951 B(Star), R(1), // 4952 B(LdaSmi8), U8(2), // 4953 B(Div), R(1), // 4954 B(Star), R(0), // 4955 B(LdaUndefined), // 4956 B(Return), // 4957 }}, 4958 {"var a = { val: 2 }; a.name *= 2;", 4959 3 * kPointerSize, 4960 1, 4961 24, 4962 { 4963 B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), // 4964 B(Star), R(0), // 4965 B(Star), R(1), // 4966 B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), // 4967 B(Star), R(2), // 4968 B(LdaSmi8), U8(2), // 4969 B(Mul), R(2), // 4970 B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)), // 4971 B(LdaUndefined), // 4972 B(Return), // 4973 }, 4974 2, 4975 {InstanceType::FIXED_ARRAY_TYPE, 4976 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 4977 {"var a = { 1: 2 }; a[1] ^= 2;", 4978 4 * kPointerSize, 4979 1, 4980 27, 4981 { 4982 B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), // 4983 B(Star), R(0), // 4984 B(Star), R(1), // 4985 B(LdaSmi8), U8(1), // 4986 B(Star), R(2), // 4987 B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot1)), // 4988 B(Star), R(3), // 4989 B(LdaSmi8), U8(2), // 4990 B(BitwiseXor), R(3), // 4991 B(KeyedStoreICSloppy), R(1), R(2), U8(vector->GetIndex(slot2)), // 4992 B(LdaUndefined), // 4993 B(Return), // 4994 }, 4995 1, 4996 {InstanceType::FIXED_ARRAY_TYPE}}, 4997 {"var a = 1; (function f() { return a; }); a |= 24;", 4998 2 * kPointerSize, 4999 1, 5000 29, 5001 { 5002 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // 5003 U8(1), // 5004 B(PushContext), R(0), // 5005 B(LdaSmi8), U8(1), // 5006 B(StaContextSlot), R(0), U8(first_context_slot), // 5007 B(CreateClosure), U8(0), U8(0), // 5008 B(LdaContextSlot), R(0), U8(first_context_slot), // 5009 B(Star), R(1), // 5010 B(LdaSmi8), U8(24), // 5011 B(BitwiseOr), R(1), // 5012 B(StaContextSlot), R(0), U8(first_context_slot), // 5013 B(LdaUndefined), // 5014 B(Return), // 5015 }, 5016 1, 5017 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 5018 }; 5019 5020 for (size_t i = 0; i < arraysize(snippets); i++) { 5021 Handle<BytecodeArray> bytecode_array = 5022 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 5023 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 5024 } 5025 } 5026 5027 5028 TEST(GlobalCompoundExpressions) { 5029 InitializedHandleScope handle_scope; 5030 BytecodeGeneratorHelper helper; 5031 Zone zone; 5032 5033 FeedbackVectorSpec feedback_spec(&zone); 5034 FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot(); 5035 FeedbackVectorSlot slot2 = feedback_spec.AddStoreICSlot(); 5036 5037 Handle<i::TypeFeedbackVector> vector = 5038 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 5039 5040 ExpectedSnippet<const char*> snippets[] = { 5041 {"var global = 1;\nfunction f() { return global &= 1; }\nf()", 5042 1 * kPointerSize, 5043 1, 5044 13, 5045 { 5046 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), // 5047 B(Star), R(0), // 5048 B(LdaSmi8), U8(1), // 5049 B(BitwiseAnd), R(0), // 5050 B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), // 5051 B(Return), // 5052 }, 5053 1, 5054 {"global"}}, 5055 {"unallocated = 1;\nfunction f() { return unallocated += 1; }\nf()", 5056 1 * kPointerSize, 5057 1, 5058 13, 5059 { 5060 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), // 5061 B(Star), R(0), // 5062 B(LdaSmi8), U8(1), // 5063 B(Add), R(0), // 5064 B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), // 5065 B(Return), // 5066 }, 5067 1, 5068 {"unallocated"}}, 5069 }; 5070 5071 for (size_t i = 0; i < arraysize(snippets); i++) { 5072 Handle<BytecodeArray> bytecode_array = 5073 helper.MakeBytecode(snippets[i].code_snippet, "f"); 5074 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 5075 } 5076 } 5077 5078 5079 TEST(CreateArguments) { 5080 InitializedHandleScope handle_scope; 5081 BytecodeGeneratorHelper helper; 5082 Zone zone; 5083 5084 int closure = Register::function_closure().index(); 5085 int first_context_slot = Context::MIN_CONTEXT_SLOTS; 5086 5087 FeedbackVectorSpec feedback_spec(&zone); 5088 FeedbackVectorSlot slot = feedback_spec.AddKeyedLoadICSlot(); 5089 5090 Handle<i::TypeFeedbackVector> vector = 5091 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 5092 5093 ExpectedSnippet<const char*> snippets[] = { 5094 {"function f() { return arguments; }", 5095 1 * kPointerSize, 5096 1, 5097 4, 5098 { 5099 B(CreateMappedArguments), // 5100 B(Star), R(0), // 5101 B(Return), // 5102 }}, 5103 {"function f() { return arguments[0]; }", 5104 2 * kPointerSize, 5105 1, 5106 10, 5107 { 5108 B(CreateMappedArguments), // 5109 B(Star), R(0), // 5110 B(Star), R(1), // 5111 B(LdaZero), // 5112 B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot)), // 5113 B(Return), // 5114 }}, 5115 {"function f() { 'use strict'; return arguments; }", 5116 1 * kPointerSize, 5117 1, 5118 4, 5119 { 5120 B(CreateUnmappedArguments), // 5121 B(Star), R(0), // 5122 B(Return), // 5123 }}, 5124 {"function f(a) { return arguments[0]; }", 5125 3 * kPointerSize, 5126 2, 5127 22, 5128 { 5129 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // 5130 U8(1), // 5131 B(PushContext), R(1), // 5132 B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex), // 5133 B(StaContextSlot), R(1), U8(first_context_slot), // 5134 B(CreateMappedArguments), // 5135 B(Star), R(0), // 5136 B(Star), R(2), // 5137 B(LdaZero), // 5138 B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot)), // 5139 B(Return), // 5140 }}, 5141 {"function f(a, b, c) { return arguments; }", 5142 2 * kPointerSize, 5143 4, 5144 26, 5145 { 5146 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // 5147 U8(1), // 5148 B(PushContext), R(1), // 5149 B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex - 2), // 5150 B(StaContextSlot), R(1), U8(first_context_slot + 2), // 5151 B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex - 1), // 5152 B(StaContextSlot), R(1), U8(first_context_slot + 1), // 5153 B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex), // 5154 B(StaContextSlot), R(1), U8(first_context_slot), // 5155 B(CreateMappedArguments), // 5156 B(Star), R(0), // 5157 B(Return), // 5158 }}, 5159 {"function f(a, b, c) { 'use strict'; return arguments; }", 5160 1 * kPointerSize, 5161 4, 5162 4, 5163 { 5164 B(CreateUnmappedArguments), // 5165 B(Star), R(0), // 5166 B(Return), // 5167 }}, 5168 }; 5169 5170 for (size_t i = 0; i < arraysize(snippets); i++) { 5171 Handle<BytecodeArray> bytecode_array = 5172 helper.MakeBytecodeForFunction(snippets[i].code_snippet); 5173 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 5174 } 5175 } 5176 5177 5178 TEST(IllegalRedeclaration) { 5179 InitializedHandleScope handle_scope; 5180 BytecodeGeneratorHelper helper; 5181 5182 CHECK_GE(MessageTemplate::kVarRedeclaration, 128); 5183 // Must adapt bytecode if this changes. 5184 5185 ExpectedSnippet<Handle<Object>, 2> snippets[] = { 5186 {"const a = 1; { var a = 2; }", 5187 3 * kPointerSize, 5188 1, 5189 14, 5190 { 5191 B(LdaConstant), U8(0), // 5192 B(Star), R(1), // 5193 B(LdaConstant), U8(1), // 5194 B(Star), R(2), // 5195 B(CallRuntime), U16(Runtime::kNewSyntaxError), R(1), U8(2), // 5196 B(Throw), // 5197 }, 5198 2, 5199 {helper.factory()->NewNumberFromInt(MessageTemplate::kVarRedeclaration), 5200 helper.factory()->NewStringFromAsciiChecked("a")}}, 5201 }; 5202 5203 for (size_t i = 0; i < arraysize(snippets); i++) { 5204 Handle<BytecodeArray> bytecode_array = 5205 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 5206 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 5207 } 5208 } 5209 5210 5211 TEST(ForIn) { 5212 InitializedHandleScope handle_scope; 5213 BytecodeGeneratorHelper helper; 5214 Zone zone; 5215 5216 int simple_flags = 5217 ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements; 5218 int deep_elements_flags = 5219 ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos; 5220 5221 FeedbackVectorSpec feedback_spec(&zone); 5222 feedback_spec.AddStoreICSlot(); 5223 FeedbackVectorSlot slot2 = feedback_spec.AddStoreICSlot(); 5224 FeedbackVectorSlot slot3 = feedback_spec.AddStoreICSlot(); 5225 FeedbackVectorSlot slot4 = feedback_spec.AddStoreICSlot(); 5226 Handle<i::TypeFeedbackVector> vector = 5227 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 5228 5229 ExpectedSnippet<InstanceType> snippets[] = { 5230 {"for (var p in null) {}", 5231 2 * kPointerSize, 5232 1, 5233 2, 5234 {B(LdaUndefined), B(Return)}, 5235 0}, 5236 {"for (var p in undefined) {}", 5237 2 * kPointerSize, 5238 1, 5239 2, 5240 {B(LdaUndefined), B(Return)}, 5241 0}, 5242 {"for (var p in undefined) {}", 5243 2 * kPointerSize, 5244 1, 5245 2, 5246 {B(LdaUndefined), B(Return)}, 5247 0}, 5248 {"var x = 'potatoes';\n" 5249 "for (var p in x) { return p; }", 5250 8 * kPointerSize, 5251 1, 5252 45, 5253 { 5254 B(LdaConstant), U8(0), // 5255 B(Star), R(1), // 5256 B(JumpIfUndefined), U8(39), // 5257 B(JumpIfNull), U8(37), // 5258 B(ToObject), // 5259 B(JumpIfNull), U8(34), // 5260 B(Star), R(3), // 5261 B(ForInPrepare), R(4), R(5), R(6), // 5262 B(LdaZero), // 5263 B(Star), R(7), // 5264 B(ForInDone), R(7), R(6), // 5265 B(JumpIfTrue), U8(20), // 5266 B(ForInNext), R(3), R(4), R(5), R(7), // 5267 B(JumpIfUndefined), U8(7), // 5268 B(Star), R(0), // 5269 B(Star), R(2), // 5270 B(Return), // 5271 B(ForInStep), R(7), // 5272 B(Star), R(7), // 5273 B(Jump), U8(-21), // 5274 B(LdaUndefined), // 5275 B(Return), // 5276 }, 5277 1, 5278 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 5279 {"var x = 0;\n" 5280 "for (var p in [1,2,3]) { x += p; }", 5281 9 * kPointerSize, 5282 1, 5283 57, 5284 { 5285 B(LdaZero), // 5286 B(Star), R(1), // 5287 B(CreateArrayLiteral), U8(0), U8(0), U8(3), // 5288 B(JumpIfUndefined), U8(48), // 5289 B(JumpIfNull), U8(46), // 5290 B(ToObject), // 5291 B(JumpIfNull), U8(43), // 5292 B(Star), R(3), // 5293 B(ForInPrepare), R(4), R(5), R(6), // 5294 B(LdaZero), // 5295 B(Star), R(7), // 5296 B(ForInDone), R(7), R(6), // 5297 B(JumpIfTrue), U8(29), // 5298 B(ForInNext), R(3), R(4), R(5), R(7), // 5299 B(JumpIfUndefined), U8(16), // 5300 B(Star), R(0), // 5301 B(Star), R(2), // 5302 B(Ldar), R(1), // 5303 B(Star), R(8), // 5304 B(Ldar), R(2), // 5305 B(Add), R(8), // 5306 B(Star), R(1), // 5307 B(ForInStep), R(7), // 5308 B(Star), R(7), // 5309 B(Jump), U8(-30), // 5310 B(LdaUndefined), // 5311 B(Return), // 5312 }, 5313 1, 5314 {InstanceType::FIXED_ARRAY_TYPE}}, 5315 {"var x = { 'a': 1, 'b': 2 };\n" 5316 "for (x['a'] in [10, 20, 30]) {\n" 5317 " if (x['a'] == 10) continue;\n" 5318 " if (x['a'] == 20) break;\n" 5319 "}", 5320 8 * kPointerSize, 5321 1, 5322 94, 5323 { 5324 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), // 5325 B(Star), R(0), // 5326 B(CreateArrayLiteral), U8(1), U8(1), U8(simple_flags), // 5327 B(JumpIfUndefined), U8(82), // 5328 B(JumpIfNull), U8(80), // 5329 B(ToObject), // 5330 B(JumpIfNull), U8(77), // 5331 B(Star), R(1), // 5332 B(ForInPrepare), R(2), R(3), R(4), // 5333 B(LdaZero), // 5334 B(Star), R(5), // 5335 B(ForInDone), R(5), R(4), // 5336 B(JumpIfTrue), U8(63), // 5337 B(ForInNext), R(1), R(2), R(3), R(5), // 5338 B(JumpIfUndefined), U8(50), // 5339 B(Star), R(6), // 5340 B(Ldar), R(0), // 5341 B(Star), R(7), // 5342 B(Ldar), R(6), // 5343 B(StoreICSloppy), R(7), U8(2), U8(vector->GetIndex(slot4)), // 5344 B(Ldar), R(0), // 5345 B(Star), R(6), // 5346 B(LoadICSloppy), R(6), U8(2), U8(vector->GetIndex(slot2)), // 5347 B(Star), R(7), // 5348 B(LdaSmi8), U8(10), // 5349 B(TestEqual), R(7), // 5350 B(JumpIfFalse), U8(4), // 5351 B(Jump), U8(20), // 5352 B(Ldar), R(0), // 5353 B(Star), R(6), // 5354 B(LoadICSloppy), R(6), U8(2), U8(vector->GetIndex(slot3)), // 5355 B(Star), R(7), // 5356 B(LdaSmi8), U8(20), // 5357 B(TestEqual), R(7), // 5358 B(JumpIfFalse), U8(4), // 5359 B(Jump), U8(8), // 5360 B(ForInStep), R(5), // 5361 B(Star), R(5), // 5362 B(Jump), U8(-64), // 5363 B(LdaUndefined), // 5364 B(Return), // 5365 }, 5366 3, 5367 {InstanceType::FIXED_ARRAY_TYPE, InstanceType::FIXED_ARRAY_TYPE, 5368 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 5369 {"var x = [ 10, 11, 12 ] ;\n" 5370 "for (x[0] in [1,2,3]) { return x[3]; }", 5371 9 * kPointerSize, 5372 1, 5373 71, 5374 { 5375 B(CreateArrayLiteral), U8(0), U8(0), U8(simple_flags), // 5376 B(Star), R(0), // 5377 B(CreateArrayLiteral), U8(1), U8(1), U8(simple_flags), // 5378 B(JumpIfUndefined), U8(59), // 5379 B(JumpIfNull), U8(57), // 5380 B(ToObject), // 5381 B(JumpIfNull), U8(54), // 5382 B(Star), R(1), // 5383 B(ForInPrepare), R(2), R(3), R(4), // 5384 B(LdaZero), // 5385 B(Star), R(5), // 5386 B(ForInDone), R(5), R(4), // 5387 B(JumpIfTrue), U8(40), // 5388 B(ForInNext), R(1), R(2), R(3), R(5), // 5389 B(JumpIfUndefined), U8(27), // 5390 B(Star), R(6), // 5391 B(Ldar), R(0), // 5392 B(Star), R(7), // 5393 B(LdaZero), // 5394 B(Star), R(8), // 5395 B(Ldar), R(6), // 5396 B(KeyedStoreICSloppy), R(7), R(8), U8(vector->GetIndex(slot3)), // 5397 B(Ldar), R(0), // 5398 B(Star), R(6), // 5399 B(LdaSmi8), U8(3), // 5400 B(KeyedLoadICSloppy), R(6), U8(vector->GetIndex(slot2)), // 5401 B(Return), // 5402 B(ForInStep), R(5), // 5403 B(Star), R(5), // 5404 B(Jump), U8(-41), // 5405 B(LdaUndefined), // 5406 B(Return), // 5407 }, 5408 2, 5409 {InstanceType::FIXED_ARRAY_TYPE, InstanceType::FIXED_ARRAY_TYPE}}, 5410 }; 5411 5412 for (size_t i = 0; i < arraysize(snippets); i++) { 5413 Handle<BytecodeArray> bytecode_array = 5414 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 5415 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 5416 } 5417 } 5418 5419 5420 TEST(Conditional) { 5421 InitializedHandleScope handle_scope; 5422 BytecodeGeneratorHelper helper; 5423 5424 ExpectedSnippet<int> snippets[] = { 5425 {"return 1 ? 2 : 3;", 5426 0, 5427 1, 5428 11, 5429 { 5430 B(LdaSmi8), U8(1), // 5431 B(JumpIfToBooleanFalse), U8(6), // 5432 B(LdaSmi8), U8(2), // 5433 B(Jump), U8(4), // 5434 B(LdaSmi8), U8(3), // 5435 B(Return), // 5436 }}, 5437 {"return 1 ? 2 ? 3 : 4 : 5;", 5438 0, 5439 1, 5440 19, 5441 { 5442 B(LdaSmi8), U8(1), // 5443 B(JumpIfToBooleanFalse), U8(14), // 5444 B(LdaSmi8), U8(2), // 5445 B(JumpIfToBooleanFalse), U8(6), // 5446 B(LdaSmi8), U8(3), // 5447 B(Jump), U8(4), // 5448 B(LdaSmi8), U8(4), // 5449 B(Jump), U8(4), // 5450 B(LdaSmi8), U8(5), // 5451 B(Return), // 5452 }}, 5453 }; 5454 5455 for (size_t i = 0; i < arraysize(snippets); i++) { 5456 Handle<BytecodeArray> bytecode_array = 5457 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 5458 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 5459 } 5460 } 5461 5462 5463 TEST(Switch) { 5464 InitializedHandleScope handle_scope; 5465 BytecodeGeneratorHelper helper; 5466 5467 ExpectedSnippet<int> snippets[] = { 5468 {"var a = 1;\n" 5469 "switch(a) {\n" 5470 " case 1: return 2;\n" 5471 " case 2: return 3;\n" 5472 "}\n", 5473 3 * kPointerSize, 5474 1, 5475 30, 5476 { 5477 B(LdaSmi8), U8(1), // 5478 B(Star), R(1), // The tag variable is allocated as a 5479 B(Star), R(0), // local by the parser, hence the store 5480 B(Star), R(2), // to another local register. 5481 B(LdaSmi8), U8(1), // 5482 B(TestEqualStrict), R(2), // 5483 B(JumpIfTrue), U8(10), // 5484 B(LdaSmi8), U8(2), // 5485 B(TestEqualStrict), R(2), // 5486 B(JumpIfTrue), U8(7), // 5487 B(Jump), U8(8), // 5488 B(LdaSmi8), U8(2), // 5489 B(Return), // 5490 B(LdaSmi8), U8(3), // 5491 B(Return), // 5492 B(LdaUndefined), // 5493 B(Return), // 5494 }}, 5495 {"var a = 1;\n" 5496 "switch(a) {\n" 5497 " case 1: a = 2; break;\n" 5498 " case 2: a = 3; break;\n" 5499 "}\n", 5500 3 * kPointerSize, 5501 1, 5502 36, 5503 { 5504 B(LdaSmi8), U8(1), // 5505 B(Star), R(1), // 5506 B(Star), R(0), // 5507 B(Star), R(2), // 5508 B(LdaSmi8), U8(1), // 5509 B(TestEqualStrict), R(2), // 5510 B(JumpIfTrue), U8(10), // 5511 B(LdaSmi8), U8(2), // 5512 B(TestEqualStrict), R(2), // 5513 B(JumpIfTrue), U8(10), // 5514 B(Jump), U8(14), // 5515 B(LdaSmi8), U8(2), // 5516 B(Star), R(1), // 5517 B(Jump), U8(8), // 5518 B(LdaSmi8), U8(3), // 5519 B(Star), R(1), // 5520 B(Jump), U8(2), // 5521 B(LdaUndefined), // 5522 B(Return), // 5523 }}, 5524 {"var a = 1;\n" 5525 "switch(a) {\n" 5526 " case 1: a = 2; // fall-through\n" 5527 " case 2: a = 3; break;\n" 5528 "}\n", 5529 3 * kPointerSize, 5530 1, 5531 34, 5532 { 5533 B(LdaSmi8), U8(1), // 5534 B(Star), R(1), // 5535 B(Star), R(0), // 5536 B(Star), R(2), // 5537 B(LdaSmi8), U8(1), // 5538 B(TestEqualStrict), R(2), // 5539 B(JumpIfTrue), U8(10), // 5540 B(LdaSmi8), U8(2), // 5541 B(TestEqualStrict), R(2), // 5542 B(JumpIfTrue), U8(8), // 5543 B(Jump), U8(12), // 5544 B(LdaSmi8), U8(2), // 5545 B(Star), R(1), // 5546 B(LdaSmi8), U8(3), // 5547 B(Star), R(1), // 5548 B(Jump), U8(2), // 5549 B(LdaUndefined), // 5550 B(Return), // 5551 }}, 5552 {"var a = 1;\n" 5553 "switch(a) {\n" 5554 " case 2: break;\n" 5555 " case 3: break;\n" 5556 " default: a = 1; break;\n" 5557 "}\n", 5558 3 * kPointerSize, 5559 1, 5560 34, 5561 { 5562 B(LdaSmi8), U8(1), // 5563 B(Star), R(1), // 5564 B(Star), R(0), // 5565 B(Star), R(2), // 5566 B(LdaSmi8), U8(2), // 5567 B(TestEqualStrict), R(2), // 5568 B(JumpIfTrue), U8(10), // 5569 B(LdaSmi8), U8(3), // 5570 B(TestEqualStrict), R(2), // 5571 B(JumpIfTrue), U8(6), // 5572 B(Jump), U8(6), // 5573 B(Jump), U8(10), // 5574 B(Jump), U8(8), // 5575 B(LdaSmi8), U8(1), // 5576 B(Star), R(1), // 5577 B(Jump), U8(2), // 5578 B(LdaUndefined), // 5579 B(Return), // 5580 }}, 5581 {"var a = 1;\n" 5582 "switch(typeof(a)) {\n" 5583 " case 2: a = 1; break;\n" 5584 " case 3: a = 2; break;\n" 5585 " default: a = 3; break;\n" 5586 "}\n", 5587 3 * kPointerSize, 5588 1, 5589 43, 5590 { 5591 B(LdaSmi8), U8(1), // 5592 B(Star), R(1), // 5593 B(TypeOf), // 5594 B(Star), R(0), // 5595 B(Star), R(2), // 5596 B(LdaSmi8), U8(2), // 5597 B(TestEqualStrict), R(2), // 5598 B(JumpIfTrue), U8(10), // 5599 B(LdaSmi8), U8(3), // 5600 B(TestEqualStrict), R(2), // 5601 B(JumpIfTrue), U8(10), // 5602 B(Jump), U8(14), // 5603 B(LdaSmi8), U8(1), // 5604 B(Star), R(1), // 5605 B(Jump), U8(14), // 5606 B(LdaSmi8), U8(2), // 5607 B(Star), R(1), // 5608 B(Jump), U8(8), // 5609 B(LdaSmi8), U8(3), // 5610 B(Star), R(1), // 5611 B(Jump), U8(2), // 5612 B(LdaUndefined), // 5613 B(Return), // 5614 }}, 5615 {"var a = 1;\n" 5616 "switch(a) {\n" 5617 " case typeof(a): a = 1; break;\n" 5618 " default: a = 2; break;\n" 5619 "}\n", 5620 3 * kPointerSize, 5621 1, 5622 31, 5623 { 5624 B(LdaSmi8), U8(1), // 5625 B(Star), R(1), // 5626 B(Star), R(0), // 5627 B(Star), R(2), // 5628 B(Ldar), R(1), // 5629 B(TypeOf), // 5630 B(TestEqualStrict), R(2), // 5631 B(JumpIfTrue), U8(4), // 5632 B(Jump), U8(8), // 5633 B(LdaSmi8), U8(1), // 5634 B(Star), R(1), // 5635 B(Jump), U8(8), // 5636 B(LdaSmi8), U8(2), // 5637 B(Star), R(1), // 5638 B(Jump), U8(2), // 5639 B(LdaUndefined), // 5640 B(Return), // 5641 }}, 5642 {"var a = 1;\n" 5643 "switch(a) {\n" 5644 " case 1:\n" REPEAT_64(SPACE, " a = 2;") 5645 "break;\n" 5646 " case 2: a = 3; break;" 5647 "}\n", 5648 3 * kPointerSize, 5649 1, 5650 288, 5651 { 5652 B(LdaSmi8), U8(1), // 5653 B(Star), R(1), // 5654 B(Star), R(0), // 5655 B(Star), R(2), // 5656 B(LdaSmi8), U8(1), // 5657 B(TestEqualStrict), R(2), // 5658 B(JumpIfTrue), U8(10), // 5659 B(LdaSmi8), U8(2), // 5660 B(TestEqualStrict), R(2), // 5661 B(JumpIfTrueConstant), U8(0), // 5662 B(JumpConstant), U8(1), // 5663 REPEAT_64(COMMA, // 5664 B(LdaSmi8), U8(2), // 5665 B(Star), R(1)), // 5666 B(Jump), U8(8), // 5667 B(LdaSmi8), U8(3), // 5668 B(Star), R(1), // 5669 B(Jump), U8(2), // 5670 B(LdaUndefined), // 5671 B(Return), // 5672 }, 5673 2, 5674 {262, 266}}, 5675 {"var a = 1;\n" 5676 "switch(a) {\n" 5677 " case 1: \n" 5678 " switch(a + 1) {\n" 5679 " case 2 : a = 1; break;\n" 5680 " default : a = 2; break;\n" 5681 " } // fall-through\n" 5682 " case 2: a = 3;\n" 5683 "}\n", 5684 5 * kPointerSize, 5685 1, 5686 60, 5687 { 5688 B(LdaSmi8), U8(1), // 5689 B(Star), R(2), // 5690 B(Star), R(0), // 5691 B(Star), R(3), // 5692 B(LdaSmi8), U8(1), // 5693 B(TestEqualStrict), R(3), // 5694 B(JumpIfTrue), U8(10), // 5695 B(LdaSmi8), U8(2), // 5696 B(TestEqualStrict), R(3), // 5697 B(JumpIfTrue), U8(36), // 5698 B(Jump), U8(38), // 5699 B(Ldar), R(2), // 5700 B(Star), R(4), // 5701 B(LdaSmi8), U8(1), // 5702 B(Add), R(4), // 5703 B(Star), R(1), // 5704 B(Star), R(4), // 5705 B(LdaSmi8), U8(2), // 5706 B(TestEqualStrict), R(4), // 5707 B(JumpIfTrue), U8(4), // 5708 B(Jump), U8(8), // 5709 B(LdaSmi8), U8(1), // 5710 B(Star), R(2), // 5711 B(Jump), U8(8), // 5712 B(LdaSmi8), U8(2), // 5713 B(Star), R(2), // 5714 B(Jump), U8(2), // 5715 B(LdaSmi8), U8(3), // 5716 B(Star), R(2), // 5717 B(LdaUndefined), // 5718 B(Return), // 5719 }}, 5720 }; 5721 5722 for (size_t i = 0; i < arraysize(snippets); i++) { 5723 Handle<BytecodeArray> bytecode_array = 5724 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 5725 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 5726 } 5727 } 5728 5729 5730 TEST(BasicBlockToBoolean) { 5731 InitializedHandleScope handle_scope; 5732 BytecodeGeneratorHelper helper; 5733 5734 // Check that we generate JumpIfToBoolean if they are at the start of basic 5735 // blocks. 5736 ExpectedSnippet<int> snippets[] = { 5737 {"var a = 1; if (a || a < 0) { return 1; }", 5738 2 * kPointerSize, 5739 1, 5740 20, 5741 { 5742 B(LdaSmi8), U8(1), // 5743 B(Star), R(0), // 5744 B(JumpIfToBooleanTrue), U8(9), // 5745 B(Ldar), R(0), // 5746 B(Star), R(1), // 5747 B(LdaZero), // 5748 B(TestLessThan), R(1), // 5749 B(JumpIfToBooleanFalse), U8(5), // 5750 B(LdaSmi8), U8(1), // 5751 B(Return), // 5752 B(LdaUndefined), // 5753 B(Return), // 5754 }}, 5755 {"var a = 1; if (a && a < 0) { return 1; }", 5756 2 * kPointerSize, 5757 1, 5758 20, 5759 { 5760 B(LdaSmi8), U8(1), // 5761 B(Star), R(0), // 5762 B(JumpIfToBooleanFalse), U8(9), // 5763 B(Ldar), R(0), // 5764 B(Star), R(1), // 5765 B(LdaZero), // 5766 B(TestLessThan), R(1), // 5767 B(JumpIfToBooleanFalse), U8(5), // 5768 B(LdaSmi8), U8(1), // 5769 B(Return), // 5770 B(LdaUndefined), // 5771 B(Return), // 5772 }}, 5773 {"var a = 1; a = (a || a < 0) ? 2 : 3;", 5774 2 * kPointerSize, 5775 1, 5776 25, 5777 { 5778 B(LdaSmi8), U8(1), // 5779 B(Star), R(0), // 5780 B(JumpIfToBooleanTrue), U8(9), // 5781 B(Ldar), R(0), // 5782 B(Star), R(1), // 5783 B(LdaZero), // 5784 B(TestLessThan), R(1), // 5785 B(JumpIfToBooleanFalse), U8(6), // 5786 B(LdaSmi8), U8(2), // 5787 B(Jump), U8(4), // 5788 B(LdaSmi8), U8(3), // 5789 B(Star), R(0), // 5790 B(LdaUndefined), // 5791 B(Return), // 5792 }}, 5793 }; 5794 5795 for (size_t i = 0; i < arraysize(snippets); i++) { 5796 Handle<BytecodeArray> bytecode_array = 5797 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 5798 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 5799 } 5800 } 5801 5802 5803 TEST(DeadCodeRemoval) { 5804 InitializedHandleScope handle_scope; 5805 BytecodeGeneratorHelper helper; 5806 5807 ExpectedSnippet<int> snippets[] = { 5808 {"return; var a = 1; a();", 5809 1 * kPointerSize, 5810 1, 5811 2, 5812 { 5813 B(LdaUndefined), // 5814 B(Return), // 5815 }}, 5816 {"if (false) { return; }; var a = 1;", 5817 1 * kPointerSize, 5818 1, 5819 6, 5820 { 5821 B(LdaSmi8), U8(1), // 5822 B(Star), R(0), // 5823 B(LdaUndefined), // 5824 B(Return), // 5825 }}, 5826 {"if (true) { return 1; } else { return 2; };", 5827 0, 5828 1, 5829 3, 5830 { 5831 B(LdaSmi8), U8(1), // 5832 B(Return), // 5833 }}, 5834 {"var a = 1; if (a) { return 1; }; return 2;", 5835 1 * kPointerSize, 5836 1, 5837 12, 5838 { 5839 B(LdaSmi8), U8(1), // 5840 B(Star), R(0), // 5841 B(JumpIfToBooleanFalse), U8(5), // 5842 B(LdaSmi8), U8(1), // 5843 B(Return), // 5844 B(LdaSmi8), U8(2), // 5845 B(Return), // 5846 }}, 5847 }; 5848 5849 for (size_t i = 0; i < arraysize(snippets); i++) { 5850 Handle<BytecodeArray> bytecode_array = 5851 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 5852 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 5853 } 5854 } 5855 5856 5857 TEST(ThisFunction) { 5858 InitializedHandleScope handle_scope; 5859 BytecodeGeneratorHelper helper; 5860 5861 int closure = Register::function_closure().index(); 5862 5863 ExpectedSnippet<int> snippets[] = { 5864 {"var f;\n f = function f() { }", 5865 1 * kPointerSize, 5866 1, 5867 9, 5868 { 5869 B(LdaTheHole), // 5870 B(Star), R(0), // 5871 B(Ldar), R(closure), // 5872 B(Star), R(0), // 5873 B(LdaUndefined), // 5874 B(Return), // 5875 }}, 5876 {"var f;\n f = function f() { return f; }", 5877 1 * kPointerSize, 5878 1, 5879 8, 5880 { 5881 B(LdaTheHole), // 5882 B(Star), R(0), // 5883 B(Ldar), R(closure), // 5884 B(Star), R(0), // 5885 B(Return), // 5886 }}, 5887 }; 5888 5889 for (size_t i = 0; i < arraysize(snippets); i++) { 5890 Handle<BytecodeArray> bytecode_array = 5891 helper.MakeBytecodeForFunction(snippets[i].code_snippet); 5892 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 5893 } 5894 } 5895 5896 5897 TEST(NewTarget) { 5898 InitializedHandleScope handle_scope; 5899 BytecodeGeneratorHelper helper; 5900 5901 int new_target = Register::new_target().index(); 5902 5903 ExpectedSnippet<int> snippets[] = { 5904 {"return new.target;", 5905 1 * kPointerSize, 5906 1, 5907 5, 5908 { 5909 B(Ldar), R(new_target), // 5910 B(Star), R(0), // 5911 B(Return), // 5912 }}, 5913 {"new.target;", 5914 1 * kPointerSize, 5915 1, 5916 6, 5917 { 5918 B(Ldar), R(new_target), // 5919 B(Star), R(0), // 5920 B(LdaUndefined), // 5921 B(Return), // 5922 }}, 5923 }; 5924 5925 for (size_t i = 0; i < arraysize(snippets); i++) { 5926 Handle<BytecodeArray> bytecode_array = 5927 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 5928 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 5929 } 5930 } 5931 5932 5933 TEST(RemoveRedundantLdar) { 5934 InitializedHandleScope handle_scope; 5935 BytecodeGeneratorHelper helper; 5936 5937 ExpectedSnippet<int> snippets[] = { 5938 {"var ld_a = 1;\n" // This test is to check Ldar does not 5939 "while(true) {\n" // get removed if the preceding Star is 5940 " ld_a = ld_a + ld_a;\n" // in a different basicblock. 5941 " if (ld_a > 10) break;\n" 5942 "}\n" 5943 "return ld_a;", 5944 2 * kPointerSize, 5945 1, 5946 29, 5947 {B(LdaSmi8), U8(1), // 5948 B(Star), R(0), // 5949 B(Ldar), R(0), // This load should not be removed as it 5950 B(Star), R(1), // is the target of the branch. 5951 B(Ldar), R(0), // 5952 B(Add), R(1), // 5953 B(Star), R(0), // 5954 B(Star), R(1), // 5955 B(LdaSmi8), U8(10), // 5956 B(TestGreaterThan), R(1), // 5957 B(JumpIfFalse), U8(4), // 5958 B(Jump), U8(4), // 5959 B(Jump), U8(-20), // 5960 B(Ldar), R(0), // 5961 B(Return)}}, 5962 {"var ld_a = 1;\n" 5963 "do {\n" 5964 " ld_a = ld_a + ld_a;\n" 5965 " if (ld_a > 10) continue;\n" 5966 "} while(false);\n" 5967 "return ld_a;", 5968 2 * kPointerSize, 5969 1, 5970 27, 5971 {B(LdaSmi8), U8(1), // 5972 B(Star), R(0), // 5973 B(Ldar), R(0), // 5974 B(Star), R(1), // 5975 B(Ldar), R(0), // 5976 B(Add), R(1), // 5977 B(Star), R(0), // 5978 B(Star), R(1), // 5979 B(LdaSmi8), U8(10), // 5980 B(TestGreaterThan), R(1), // 5981 B(JumpIfFalse), U8(4), // 5982 B(Jump), U8(2), // 5983 B(Ldar), R(0), // 5984 B(Return)}}, 5985 {"var ld_a = 1;\n" 5986 " ld_a = ld_a + ld_a;\n" 5987 " return ld_a;", 5988 2 * kPointerSize, 5989 1, 5990 13, 5991 { 5992 B(LdaSmi8), U8(1), // 5993 B(Star), R(0), // 5994 B(Star), R(1), // 5995 B(Ldar), R(0), // 5996 B(Add), R(1), // 5997 B(Star), R(0), // 5998 B(Return) // 5999 }}, 6000 }; 6001 6002 for (size_t i = 0; i < arraysize(snippets); i++) { 6003 Handle<BytecodeArray> bytecode_array = 6004 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 6005 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 6006 } 6007 } 6008 6009 6010 TEST(AssignmentsInBinaryExpression) { 6011 InitializedHandleScope handle_scope; 6012 BytecodeGeneratorHelper helper; 6013 6014 ExpectedSnippet<const char*> snippets[] = { 6015 {"var x = 0, y = 1;\n" 6016 "return (x = 2, y = 3, x = 4, y = 5)", 6017 2 * kPointerSize, 6018 1, 6019 24, 6020 { 6021 B(LdaZero), B(Star), R(0), // 6022 B(LdaSmi8), U8(1), // 6023 B(Star), R(1), // 6024 B(LdaSmi8), U8(2), // 6025 B(Star), R(0), // 6026 B(LdaSmi8), U8(3), // 6027 B(Star), R(1), // 6028 B(LdaSmi8), U8(4), // 6029 B(Star), R(0), // 6030 B(LdaSmi8), U8(5), // 6031 B(Star), R(1), // 6032 B(Return), // 6033 }, 6034 0}, 6035 {"var x = 55;\n" 6036 "var y = (x = 100);\n" 6037 "return y", 6038 2 * kPointerSize, 6039 1, 6040 11, 6041 { 6042 B(LdaSmi8), U8(55), // 6043 B(Star), R(0), // 6044 B(LdaSmi8), U8(100), // 6045 B(Star), R(0), // 6046 B(Star), R(1), // 6047 B(Return), // 6048 }, 6049 0}, 6050 {"var x = 55;\n" 6051 "x = x + (x = 100) + (x = 101);\n" 6052 "return x;", 6053 3 * kPointerSize, 6054 1, 6055 23, 6056 { 6057 B(LdaSmi8), U8(55), // 6058 B(Star), R(0), // 6059 B(Star), R(1), // 6060 B(LdaSmi8), U8(100), // 6061 B(Star), R(0), // 6062 B(Add), R(1), // 6063 B(Star), R(2), // 6064 B(LdaSmi8), U8(101), // 6065 B(Star), R(0), // 6066 B(Add), R(2), // 6067 B(Star), R(0), // 6068 B(Return), // 6069 }, 6070 0}, 6071 {"var x = 55;\n" 6072 "x = (x = 56) - x + (x = 57);\n" 6073 "x++;\n" 6074 "return x;", 6075 3 * kPointerSize, 6076 1, 6077 31, 6078 { 6079 B(LdaSmi8), U8(55), // 6080 B(Star), R(0), // 6081 B(LdaSmi8), U8(56), // 6082 B(Star), R(0), // 6083 B(Star), R(1), // 6084 B(Ldar), R(0), // 6085 B(Sub), R(1), // 6086 B(Star), R(2), // 6087 B(LdaSmi8), U8(57), // 6088 B(Star), R(0), // 6089 B(Add), R(2), // 6090 B(Star), R(0), // 6091 B(ToNumber), // 6092 B(Star), R(1), // 6093 B(Inc), // 6094 B(Star), R(0), // 6095 B(Return), // 6096 }, 6097 0}, 6098 {"var x = 55;\n" 6099 "var y = x + (x = 1) + (x = 2) + (x = 3);\n" 6100 "return y;", 6101 4 * kPointerSize, 6102 1, 6103 31, 6104 { 6105 B(LdaSmi8), U8(55), // 6106 B(Star), R(0), // 6107 B(Star), R(2), // 6108 B(LdaSmi8), U8(1), // 6109 B(Star), R(0), // 6110 B(Add), R(2), // 6111 B(Star), R(3), // 6112 B(LdaSmi8), U8(2), // 6113 B(Star), R(0), // 6114 B(Add), R(3), // 6115 B(Star), R(2), // 6116 B(LdaSmi8), U8(3), // 6117 B(Star), R(0), // 6118 B(Add), R(2), // 6119 B(Star), R(1), // 6120 B(Return), // 6121 }, 6122 0}, 6123 {"var x = 55;\n" 6124 "var x = x + (x = 1) + (x = 2) + (x = 3);\n" 6125 "return x;", 6126 3 * kPointerSize, 6127 1, 6128 31, 6129 { 6130 B(LdaSmi8), U8(55), // 6131 B(Star), R(0), // 6132 B(Star), R(1), // 6133 B(LdaSmi8), U8(1), // 6134 B(Star), R(0), // 6135 B(Add), R(1), // 6136 B(Star), R(2), // 6137 B(LdaSmi8), U8(2), // 6138 B(Star), R(0), // 6139 B(Add), R(2), // 6140 B(Star), R(1), // 6141 B(LdaSmi8), U8(3), // 6142 B(Star), R(0), // 6143 B(Add), R(1), // 6144 B(Star), R(0), // 6145 B(Return), // 6146 }, 6147 0}, 6148 {"var x = 10, y = 20;\n" 6149 "return x + (x = 1) + (x + 1) * (y = 2) + (y = 3) + (x = 4) + (y = 5) + " 6150 "y;\n", 6151 5 * kPointerSize, 6152 1, 6153 69, 6154 { 6155 B(LdaSmi8), U8(10), // 6156 B(Star), R(0), // 6157 B(LdaSmi8), U8(20), // 6158 B(Star), R(1), // 6159 B(Ldar), R(0), // 6160 B(Star), R(2), // 6161 B(LdaSmi8), U8(1), // 6162 B(Star), R(0), // 6163 B(Add), R(2), // 6164 B(Star), R(3), // 6165 B(Ldar), R(0), // 6166 B(Star), R(2), // 6167 B(LdaSmi8), U8(1), // 6168 B(Add), R(2), // 6169 B(Star), R(4), // 6170 B(LdaSmi8), U8(2), // 6171 B(Star), R(1), // 6172 B(Mul), R(4), // 6173 B(Add), R(3), // 6174 B(Star), R(2), // 6175 B(LdaSmi8), U8(3), // 6176 B(Star), R(1), // 6177 B(Add), R(2), // 6178 B(Star), R(3), // 6179 B(LdaSmi8), U8(4), // 6180 B(Star), R(0), // 6181 B(Add), R(3), // 6182 B(Star), R(2), // 6183 B(LdaSmi8), U8(5), // 6184 B(Star), R(1), // 6185 B(Add), R(2), // 6186 B(Star), R(3), // 6187 B(Ldar), R(1), // 6188 B(Add), R(3), // 6189 B(Return), // 6190 }, 6191 0}, 6192 {"var x = 17;\n" 6193 "return 1 + x + (x++) + (++x);\n", 6194 4 * kPointerSize, 6195 1, 6196 37, 6197 { 6198 B(LdaSmi8), U8(17), // 6199 B(Star), R(0), // 6200 B(LdaSmi8), U8(1), // 6201 B(Star), R(1), // 6202 B(Ldar), R(0), // 6203 B(Add), R(1), // 6204 B(Star), R(2), // 6205 B(Ldar), R(0), // 6206 B(ToNumber), // 6207 B(Star), R(1), // 6208 B(Inc), // 6209 B(Star), R(0), // 6210 B(Ldar), R(1), // 6211 B(Add), R(2), // 6212 B(Star), R(3), // 6213 B(Ldar), R(0), // 6214 B(ToNumber), // 6215 B(Inc), // 6216 B(Star), R(0), // 6217 B(Add), R(3), // 6218 B(Return), // 6219 }, 6220 0}}; 6221 6222 for (size_t i = 0; i < arraysize(snippets); i++) { 6223 Handle<BytecodeArray> bytecode_array = 6224 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 6225 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 6226 } 6227 } 6228 6229 6230 TEST(Eval) { 6231 InitializedHandleScope handle_scope; 6232 BytecodeGeneratorHelper helper; 6233 Zone zone; 6234 6235 int closure = Register::function_closure().index(); 6236 int context = Register::function_context().index(); 6237 int new_target = Register::new_target().index(); 6238 6239 int first_context_slot = Context::MIN_CONTEXT_SLOTS; 6240 6241 ExpectedSnippet<const char*> snippets[] = { 6242 {"return eval('1;');", 6243 9 * kPointerSize, 6244 1, 6245 67, 6246 { 6247 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // 6248 U8(1), // 6249 B(PushContext), R(0), // 6250 B(Ldar), THIS(1), // 6251 B(StaContextSlot), R(0), U8(first_context_slot), // 6252 B(CreateMappedArguments), // 6253 B(StaContextSlot), R(0), U8(first_context_slot + 1), // 6254 B(Ldar), R(new_target), // 6255 B(StaContextSlot), R(0), U8(first_context_slot + 2), // 6256 B(Mov), R(context), R(3), // 6257 B(LdaConstant), U8(0), // 6258 B(Star), R(4), // 6259 B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), // 6260 R(3), U8(2), R(1), // 6261 B(LdaConstant), U8(1), // 6262 B(Star), R(3), // 6263 B(Mov), R(1), R(4), // 6264 B(Mov), R(3), R(5), // 6265 B(Mov), R(closure), R(6), // 6266 B(LdaZero), // 6267 B(Star), R(7), // 6268 B(LdaSmi8), U8(10), // 6269 B(Star), R(8), // 6270 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // 6271 U8(5), // 6272 B(Star), R(1), // 6273 B(Call), R(1), R(2), U8(1), U8(0), // 6274 B(Return), // 6275 }, 6276 2, 6277 {"eval", "1;"}}, 6278 }; 6279 6280 for (size_t i = 0; i < arraysize(snippets); i++) { 6281 Handle<BytecodeArray> bytecode_array = 6282 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 6283 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 6284 } 6285 } 6286 6287 6288 TEST(LookupSlot) { 6289 InitializedHandleScope handle_scope; 6290 BytecodeGeneratorHelper helper; 6291 6292 int closure = Register::function_closure().index(); 6293 int first_context_slot = Context::MIN_CONTEXT_SLOTS; 6294 int context = Register::function_context().index(); 6295 int new_target = Register::new_target().index(); 6296 6297 ExpectedSnippet<const char*> snippets[] = { 6298 {"eval('var x = 10;'); return x;", 6299 9 * kPointerSize, 6300 1, 6301 69, 6302 { 6303 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // 6304 U8(1), // 6305 B(PushContext), R(0), // 6306 B(Ldar), THIS(1), // 6307 B(StaContextSlot), R(0), U8(first_context_slot), // 6308 B(CreateMappedArguments), // 6309 B(StaContextSlot), R(0), U8(first_context_slot + 1), // 6310 B(Ldar), R(new_target), // 6311 B(StaContextSlot), R(0), U8(first_context_slot + 2), // 6312 B(Mov), R(context), R(3), // 6313 B(LdaConstant), U8(0), // 6314 B(Star), R(4), // 6315 B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), // 6316 R(3), U8(2), R(1), // 6317 B(LdaConstant), U8(1), // 6318 B(Star), R(3), // 6319 B(Mov), R(1), R(4), // 6320 B(Mov), R(3), R(5), // 6321 B(Mov), R(closure), R(6), // 6322 B(LdaZero), // 6323 B(Star), R(7), // 6324 B(LdaSmi8), U8(10), // 6325 B(Star), R(8), // 6326 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // 6327 U8(5), // 6328 B(Star), R(1), // 6329 B(Call), R(1), R(2), U8(1), U8(0), // 6330 B(LdaLookupSlot), U8(2), // 6331 B(Return), // 6332 }, 6333 3, 6334 {"eval", "var x = 10;", "x"}}, 6335 {"eval('var x = 10;'); return typeof x;", 6336 9 * kPointerSize, 6337 1, 6338 70, 6339 { 6340 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // 6341 U8(1), // 6342 B(PushContext), R(0), // 6343 B(Ldar), THIS(1), // 6344 B(StaContextSlot), R(0), U8(first_context_slot), // 6345 B(CreateMappedArguments), // 6346 B(StaContextSlot), R(0), U8(first_context_slot + 1), // 6347 B(Ldar), R(new_target), // 6348 B(StaContextSlot), R(0), U8(first_context_slot + 2), // 6349 B(Mov), R(context), R(3), // 6350 B(LdaConstant), U8(0), // 6351 B(Star), R(4), // 6352 B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), // 6353 R(3), U8(2), R(1), // 6354 B(LdaConstant), U8(1), // 6355 B(Star), R(3), // 6356 B(Mov), R(1), R(4), // 6357 B(Mov), R(3), R(5), // 6358 B(Mov), R(closure), R(6), // 6359 B(LdaZero), // 6360 B(Star), R(7), // 6361 B(LdaSmi8), U8(10), // 6362 B(Star), R(8), // 6363 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // 6364 U8(5), // 6365 B(Star), R(1), // 6366 B(Call), R(1), R(2), U8(1), U8(0), // 6367 B(LdaLookupSlotInsideTypeof), U8(2), // 6368 B(TypeOf), // 6369 B(Return), // 6370 }, 6371 3, 6372 {"eval", "var x = 10;", "x"}}, 6373 {"x = 20; return eval('');", 6374 9 * kPointerSize, 6375 1, 6376 71, 6377 { 6378 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // 6379 U8(1), // 6380 B(PushContext), R(0), // 6381 B(Ldar), THIS(1), // 6382 B(StaContextSlot), R(0), U8(first_context_slot), // 6383 B(CreateMappedArguments), // 6384 B(StaContextSlot), R(0), U8(first_context_slot + 1), // 6385 B(Ldar), R(new_target), // 6386 B(StaContextSlot), R(0), U8(first_context_slot + 2), // 6387 B(LdaSmi8), U8(20), // 6388 B(StaLookupSlotSloppy), U8(0), // 6389 B(Mov), R(context), R(3), // 6390 B(LdaConstant), U8(1), // 6391 B(Star), R(4), // 6392 B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), // 6393 R(3), U8(2), R(1), // 6394 B(LdaConstant), U8(2), // 6395 B(Star), R(3), // 6396 B(Mov), R(1), R(4), // 6397 B(Mov), R(3), R(5), // 6398 B(Mov), R(closure), R(6), // 6399 B(LdaZero), // 6400 B(Star), R(7), // 6401 B(LdaSmi8), U8(10), // 6402 B(Star), R(8), // 6403 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // 6404 U8(5), // 6405 B(Star), R(1), // 6406 B(Call), R(1), R(2), U8(1), U8(0), // 6407 B(Return), // 6408 }, 6409 3, 6410 {"x", "eval", ""}}, 6411 }; 6412 6413 for (size_t i = 0; i < arraysize(snippets); i++) { 6414 Handle<BytecodeArray> bytecode_array = 6415 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 6416 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 6417 } 6418 } 6419 6420 6421 TEST(CallLookupSlot) { 6422 InitializedHandleScope handle_scope; 6423 BytecodeGeneratorHelper helper; 6424 Zone zone; 6425 6426 FeedbackVectorSpec feedback_spec(&zone); 6427 FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot(); 6428 FeedbackVectorSlot slot2 = feedback_spec.AddCallICSlot(); 6429 USE(slot1); 6430 6431 Handle<i::TypeFeedbackVector> vector = 6432 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 6433 6434 int closure = Register::function_closure().index(); 6435 int context = Register::function_context().index(); 6436 int new_target = Register::new_target().index(); 6437 6438 ExpectedSnippet<InstanceType> snippets[] = { 6439 {"g = function(){}; eval(''); return g();", 6440 9 * kPointerSize, 6441 1, 6442 90, 6443 { 6444 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // 6445 U8(1), // 6446 B(PushContext), R(0), // 6447 B(Ldar), THIS(1), // 6448 B(StaContextSlot), R(0), U8(4), // 6449 B(CreateMappedArguments), // 6450 B(StaContextSlot), R(0), U8(5), // 6451 B(Ldar), R(new_target), // 6452 B(StaContextSlot), R(0), U8(6), // 6453 B(CreateClosure), U8(0), U8(0), // 6454 B(StaLookupSlotSloppy), U8(1), // 6455 B(Mov), R(context), R(3), // 6456 B(LdaConstant), U8(2), // 6457 B(Star), R(4), // 6458 B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), // 6459 R(3), U8(2), R(1), // 6460 B(LdaConstant), U8(3), // 6461 B(Star), R(3), // 6462 B(Mov), R(1), R(4), // 6463 B(Mov), R(3), R(5), // 6464 B(Mov), R(closure), R(6), // 6465 B(LdaZero), // 6466 B(Star), R(7), // 6467 B(LdaSmi8), U8(10), // 6468 B(Star), R(8), // 6469 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // 6470 U8(5), // 6471 B(Star), R(1), // 6472 B(Call), R(1), R(2), U8(1), U8(0), // 6473 B(Mov), R(context), R(3), // 6474 B(LdaConstant), U8(1), // 6475 B(Star), R(4), // 6476 B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), // 6477 R(3), U8(2), R(1), // 6478 B(Call), R(1), R(2), U8(0), U8(vector->GetIndex(slot2)), // 6479 B(Return), // 6480 }, 6481 4, 6482 {InstanceType::SHARED_FUNCTION_INFO_TYPE, 6483 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 6484 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 6485 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 6486 }; 6487 6488 for (size_t i = 0; i < arraysize(snippets); i++) { 6489 Handle<BytecodeArray> bytecode_array = 6490 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 6491 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 6492 } 6493 } 6494 6495 6496 TEST(LookupSlotInEval) { 6497 InitializedHandleScope handle_scope; 6498 BytecodeGeneratorHelper helper; 6499 6500 const char* function_prologue = "var f;" 6501 "var x = 1;" 6502 "function f1() {" 6503 " eval(\"function t() {"; 6504 const char* function_epilogue = " }; f = t; f();\");" 6505 "}" 6506 "f1();"; 6507 6508 ExpectedSnippet<const char*> snippets[] = { 6509 {"return x;", 6510 0 * kPointerSize, 6511 1, 6512 3, 6513 { 6514 B(LdaLookupSlot), U8(0), // 6515 B(Return) // 6516 }, 6517 1, 6518 {"x"}}, 6519 {"x = 10;", 6520 0 * kPointerSize, 6521 1, 6522 6, 6523 { 6524 B(LdaSmi8), U8(10), // 6525 B(StaLookupSlotSloppy), U8(0), // 6526 B(LdaUndefined), // 6527 B(Return), // 6528 }, 6529 1, 6530 {"x"}}, 6531 {"'use strict'; x = 10;", 6532 0 * kPointerSize, 6533 1, 6534 6, 6535 { 6536 B(LdaSmi8), U8(10), // 6537 B(StaLookupSlotStrict), U8(0), // 6538 B(LdaUndefined), // 6539 B(Return), // 6540 }, 6541 1, 6542 {"x"}}, 6543 {"return typeof x;", 6544 0 * kPointerSize, 6545 1, 6546 4, 6547 { 6548 B(LdaLookupSlotInsideTypeof), U8(0), // 6549 B(TypeOf), // 6550 B(Return), // 6551 }, 6552 1, 6553 {"x"}}, 6554 }; 6555 6556 for (size_t i = 0; i < arraysize(snippets); i++) { 6557 std::string script = std::string(function_prologue) + 6558 std::string(snippets[i].code_snippet) + 6559 std::string(function_epilogue); 6560 // TODO(mythria): use * as filter when function declarations are supported 6561 // inside eval. 6562 Handle<BytecodeArray> bytecode_array = 6563 helper.MakeBytecode(script.c_str(), "t", "f"); 6564 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 6565 } 6566 } 6567 6568 6569 TEST(LookupSlotWideInEval) { 6570 InitializedHandleScope handle_scope; 6571 BytecodeGeneratorHelper helper; 6572 6573 const char* function_prologue = 6574 "var f;" 6575 "var x = 1;" 6576 "function f1() {" 6577 " eval(\"function t() {"; 6578 const char* function_epilogue = 6579 " }; f = t; f();\");" 6580 "}" 6581 "f1();"; 6582 6583 int const_count[] = {0, 0, 0, 0}; 6584 ExpectedSnippet<InstanceType, 257> snippets[] = { 6585 {REPEAT_256(SPACE, "var y = 2.3;") 6586 "return x;", 6587 1 * kPointerSize, 6588 1, 6589 1028, 6590 { 6591 REPEAT_256(SPACE, // 6592 B(LdaConstant), U8(const_count[0]++), // 6593 B(Star), R(0), ) // 6594 B(LdaLookupSlotWide), U16(256), // 6595 B(Return) // 6596 }, 6597 257, 6598 {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE), 6599 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 6600 {REPEAT_256(SPACE, "var y = 2.3;") 6601 "return typeof x;", 6602 1 * kPointerSize, 6603 1, 6604 1029, 6605 { 6606 REPEAT_256(SPACE, // 6607 B(LdaConstant), U8(const_count[1]++), // 6608 B(Star), R(0), ) // 6609 B(LdaLookupSlotInsideTypeofWide), U16(256), // 6610 B(TypeOf), // 6611 B(Return) // 6612 }, 6613 257, 6614 {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE), 6615 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 6616 {REPEAT_256(SPACE, "var y = 2.3;") 6617 "x = 10;", 6618 1 * kPointerSize, 6619 1, 6620 1031, 6621 { 6622 REPEAT_256(SPACE, // 6623 B(LdaConstant), U8(const_count[2]++), // 6624 B(Star), R(0), ) // 6625 B(LdaSmi8), U8(10), // 6626 B(StaLookupSlotSloppyWide), U16(256), // 6627 B(LdaUndefined), // 6628 B(Return) // 6629 }, 6630 257, 6631 {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE), 6632 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 6633 {"'use strict';" 6634 REPEAT_256(SPACE, "var y = 2.3;") 6635 "x = 10;", 6636 1 * kPointerSize, 6637 1, 6638 1031, 6639 { 6640 REPEAT_256(SPACE, 6641 B(LdaConstant), U8(const_count[3]++), // 6642 B(Star), R(0), ) // 6643 B(LdaSmi8), U8(10), // 6644 B(StaLookupSlotStrictWide), U16(256), // 6645 B(LdaUndefined), // 6646 B(Return) // 6647 }, 6648 257, 6649 {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE), 6650 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 6651 }; 6652 6653 for (size_t i = 0; i < arraysize(snippets); i++) { 6654 std::string script = std::string(function_prologue) + 6655 std::string(snippets[i].code_snippet) + 6656 std::string(function_epilogue); 6657 // TODO(mythria): use * as filter when function declarations are supported 6658 // inside eval. 6659 Handle<BytecodeArray> bytecode_array = 6660 helper.MakeBytecode(script.c_str(), "t", "f"); 6661 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 6662 } 6663 } 6664 6665 6666 TEST(DeleteLookupSlotInEval) { 6667 InitializedHandleScope handle_scope; 6668 BytecodeGeneratorHelper helper; 6669 6670 const char* function_prologue = "var f;" 6671 "var x = 1;" 6672 "z = 10;" 6673 "function f1() {" 6674 " var y;" 6675 " eval(\"function t() {"; 6676 const char* function_epilogue = " }; f = t; f();\");" 6677 "}" 6678 "f1();"; 6679 6680 ExpectedSnippet<const char*> snippets[] = { 6681 {"delete x;", 6682 0 * kPointerSize, 6683 1, 6684 5, 6685 { 6686 B(LdaConstant), U8(0), // 6687 B(DeleteLookupSlot), // 6688 B(LdaUndefined), // 6689 B(Return) // 6690 }, 6691 1, 6692 {"x"}}, 6693 {"return delete y;", 6694 0 * kPointerSize, 6695 1, 6696 2, 6697 { 6698 B(LdaFalse), // 6699 B(Return) // 6700 }, 6701 0}, 6702 {"return delete z;", 6703 0 * kPointerSize, 6704 1, 6705 4, 6706 { 6707 B(LdaConstant), U8(0), // 6708 B(DeleteLookupSlot), // 6709 B(Return) // 6710 }, 6711 1, 6712 {"z"}}, 6713 }; 6714 6715 for (size_t i = 0; i < arraysize(snippets); i++) { 6716 std::string script = std::string(function_prologue) + 6717 std::string(snippets[i].code_snippet) + 6718 std::string(function_epilogue); 6719 Handle<BytecodeArray> bytecode_array = 6720 helper.MakeBytecode(script.c_str(), "t", "f"); 6721 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 6722 } 6723 } 6724 6725 } // namespace interpreter 6726 } // namespace internal 6727 } // namespace v8 6728