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/execution.h" 8 #include "src/handles.h" 9 #include "src/interpreter/bytecode-array-builder.h" 10 #include "src/interpreter/bytecode-array-iterator.h" 11 #include "src/interpreter/bytecode-label.h" 12 #include "src/interpreter/interpreter.h" 13 #include "test/cctest/cctest.h" 14 #include "test/cctest/interpreter/interpreter-tester.h" 15 #include "test/cctest/test-feedback-vector.h" 16 17 namespace v8 { 18 namespace internal { 19 namespace interpreter { 20 21 22 TEST(InterpreterReturn) { 23 HandleAndZoneScope handles; 24 Handle<Object> undefined_value = 25 handles.main_isolate()->factory()->undefined_value(); 26 27 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 28 0, 0); 29 builder.Return(); 30 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 31 32 InterpreterTester tester(handles.main_isolate(), bytecode_array); 33 auto callable = tester.GetCallable<>(); 34 Handle<Object> return_val = callable().ToHandleChecked(); 35 CHECK(return_val.is_identical_to(undefined_value)); 36 } 37 38 39 TEST(InterpreterLoadUndefined) { 40 HandleAndZoneScope handles; 41 Handle<Object> undefined_value = 42 handles.main_isolate()->factory()->undefined_value(); 43 44 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 45 0, 0); 46 builder.LoadUndefined().Return(); 47 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 48 49 InterpreterTester tester(handles.main_isolate(), bytecode_array); 50 auto callable = tester.GetCallable<>(); 51 Handle<Object> return_val = callable().ToHandleChecked(); 52 CHECK(return_val.is_identical_to(undefined_value)); 53 } 54 55 56 TEST(InterpreterLoadNull) { 57 HandleAndZoneScope handles; 58 Handle<Object> null_value = handles.main_isolate()->factory()->null_value(); 59 60 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 61 0, 0); 62 builder.LoadNull().Return(); 63 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 64 65 InterpreterTester tester(handles.main_isolate(), bytecode_array); 66 auto callable = tester.GetCallable<>(); 67 Handle<Object> return_val = callable().ToHandleChecked(); 68 CHECK(return_val.is_identical_to(null_value)); 69 } 70 71 72 TEST(InterpreterLoadTheHole) { 73 HandleAndZoneScope handles; 74 Handle<Object> the_hole_value = 75 handles.main_isolate()->factory()->the_hole_value(); 76 77 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 78 0, 0); 79 builder.LoadTheHole().Return(); 80 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 81 82 InterpreterTester tester(handles.main_isolate(), bytecode_array); 83 auto callable = tester.GetCallable<>(); 84 Handle<Object> return_val = callable().ToHandleChecked(); 85 CHECK(return_val.is_identical_to(the_hole_value)); 86 } 87 88 89 TEST(InterpreterLoadTrue) { 90 HandleAndZoneScope handles; 91 Handle<Object> true_value = handles.main_isolate()->factory()->true_value(); 92 93 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 94 0, 0); 95 builder.LoadTrue().Return(); 96 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 97 98 InterpreterTester tester(handles.main_isolate(), bytecode_array); 99 auto callable = tester.GetCallable<>(); 100 Handle<Object> return_val = callable().ToHandleChecked(); 101 CHECK(return_val.is_identical_to(true_value)); 102 } 103 104 105 TEST(InterpreterLoadFalse) { 106 HandleAndZoneScope handles; 107 Handle<Object> false_value = handles.main_isolate()->factory()->false_value(); 108 109 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 110 0, 0); 111 builder.LoadFalse().Return(); 112 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 113 114 InterpreterTester tester(handles.main_isolate(), bytecode_array); 115 auto callable = tester.GetCallable<>(); 116 Handle<Object> return_val = callable().ToHandleChecked(); 117 CHECK(return_val.is_identical_to(false_value)); 118 } 119 120 121 TEST(InterpreterLoadLiteral) { 122 HandleAndZoneScope handles; 123 i::Factory* factory = handles.main_isolate()->factory(); 124 125 // Small Smis. 126 for (int i = -128; i < 128; i++) { 127 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 128 0, 0); 129 builder.LoadLiteral(Smi::FromInt(i)).Return(); 130 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 131 132 InterpreterTester tester(handles.main_isolate(), bytecode_array); 133 auto callable = tester.GetCallable<>(); 134 Handle<Object> return_val = callable().ToHandleChecked(); 135 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(i)); 136 } 137 138 // Large Smis. 139 { 140 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 141 0, 0); 142 143 builder.LoadLiteral(Smi::FromInt(0x12345678)).Return(); 144 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 145 146 InterpreterTester tester(handles.main_isolate(), bytecode_array); 147 auto callable = tester.GetCallable<>(); 148 Handle<Object> return_val = callable().ToHandleChecked(); 149 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(0x12345678)); 150 } 151 152 // Heap numbers. 153 { 154 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 155 0, 0); 156 157 builder.LoadLiteral(factory->NewHeapNumber(-2.1e19)).Return(); 158 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 159 160 InterpreterTester tester(handles.main_isolate(), bytecode_array); 161 auto callable = tester.GetCallable<>(); 162 Handle<Object> return_val = callable().ToHandleChecked(); 163 CHECK_EQ(i::HeapNumber::cast(*return_val)->value(), -2.1e19); 164 } 165 166 // Strings. 167 { 168 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 169 0, 0); 170 171 Handle<i::String> string = factory->NewStringFromAsciiChecked("String"); 172 builder.LoadLiteral(string).Return(); 173 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 174 175 InterpreterTester tester(handles.main_isolate(), bytecode_array); 176 auto callable = tester.GetCallable<>(); 177 Handle<Object> return_val = callable().ToHandleChecked(); 178 CHECK(i::String::cast(*return_val)->Equals(*string)); 179 } 180 } 181 182 183 TEST(InterpreterLoadStoreRegisters) { 184 HandleAndZoneScope handles; 185 Handle<Object> true_value = handles.main_isolate()->factory()->true_value(); 186 for (int i = 0; i <= kMaxInt8; i++) { 187 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 188 0, i + 1); 189 190 Register reg(i); 191 builder.LoadTrue() 192 .StoreAccumulatorInRegister(reg) 193 .LoadFalse() 194 .LoadAccumulatorWithRegister(reg) 195 .Return(); 196 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 197 198 InterpreterTester tester(handles.main_isolate(), bytecode_array); 199 auto callable = tester.GetCallable<>(); 200 Handle<Object> return_val = callable().ToHandleChecked(); 201 CHECK(return_val.is_identical_to(true_value)); 202 } 203 } 204 205 206 static const Token::Value kShiftOperators[] = { 207 Token::Value::SHL, Token::Value::SAR, Token::Value::SHR}; 208 209 210 static const Token::Value kArithmeticOperators[] = { 211 Token::Value::BIT_OR, Token::Value::BIT_XOR, Token::Value::BIT_AND, 212 Token::Value::SHL, Token::Value::SAR, Token::Value::SHR, 213 Token::Value::ADD, Token::Value::SUB, Token::Value::MUL, 214 Token::Value::DIV, Token::Value::MOD}; 215 216 217 static double BinaryOpC(Token::Value op, double lhs, double rhs) { 218 switch (op) { 219 case Token::Value::ADD: 220 return lhs + rhs; 221 case Token::Value::SUB: 222 return lhs - rhs; 223 case Token::Value::MUL: 224 return lhs * rhs; 225 case Token::Value::DIV: 226 return lhs / rhs; 227 case Token::Value::MOD: 228 return std::fmod(lhs, rhs); 229 case Token::Value::BIT_OR: 230 return (v8::internal::DoubleToInt32(lhs) | 231 v8::internal::DoubleToInt32(rhs)); 232 case Token::Value::BIT_XOR: 233 return (v8::internal::DoubleToInt32(lhs) ^ 234 v8::internal::DoubleToInt32(rhs)); 235 case Token::Value::BIT_AND: 236 return (v8::internal::DoubleToInt32(lhs) & 237 v8::internal::DoubleToInt32(rhs)); 238 case Token::Value::SHL: { 239 int32_t val = v8::internal::DoubleToInt32(lhs); 240 uint32_t count = v8::internal::DoubleToUint32(rhs) & 0x1F; 241 int32_t result = val << count; 242 return result; 243 } 244 case Token::Value::SAR: { 245 int32_t val = v8::internal::DoubleToInt32(lhs); 246 uint32_t count = v8::internal::DoubleToUint32(rhs) & 0x1F; 247 int32_t result = val >> count; 248 return result; 249 } 250 case Token::Value::SHR: { 251 uint32_t val = v8::internal::DoubleToUint32(lhs); 252 uint32_t count = v8::internal::DoubleToUint32(rhs) & 0x1F; 253 uint32_t result = val >> count; 254 return result; 255 } 256 default: 257 UNREACHABLE(); 258 return std::numeric_limits<double>::min(); 259 } 260 } 261 262 263 TEST(InterpreterShiftOpsSmi) { 264 int lhs_inputs[] = {0, -17, -182, 1073741823, -1}; 265 int rhs_inputs[] = {5, 2, 1, -1, -2, 0, 31, 32, -32, 64, 37}; 266 for (size_t l = 0; l < arraysize(lhs_inputs); l++) { 267 for (size_t r = 0; r < arraysize(rhs_inputs); r++) { 268 for (size_t o = 0; o < arraysize(kShiftOperators); o++) { 269 HandleAndZoneScope handles; 270 i::Factory* factory = handles.main_isolate()->factory(); 271 BytecodeArrayBuilder builder(handles.main_isolate(), 272 handles.main_zone(), 1, 0, 1); 273 Register reg(0); 274 int lhs = lhs_inputs[l]; 275 int rhs = rhs_inputs[r]; 276 builder.LoadLiteral(Smi::FromInt(lhs)) 277 .StoreAccumulatorInRegister(reg) 278 .LoadLiteral(Smi::FromInt(rhs)) 279 .BinaryOperation(kShiftOperators[o], reg) 280 .Return(); 281 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 282 283 InterpreterTester tester(handles.main_isolate(), bytecode_array); 284 auto callable = tester.GetCallable<>(); 285 Handle<Object> return_value = callable().ToHandleChecked(); 286 Handle<Object> expected_value = 287 factory->NewNumber(BinaryOpC(kShiftOperators[o], lhs, rhs)); 288 CHECK(return_value->SameValue(*expected_value)); 289 } 290 } 291 } 292 } 293 294 295 TEST(InterpreterBinaryOpsSmi) { 296 int lhs_inputs[] = {3266, 1024, 0, -17, -18000}; 297 int rhs_inputs[] = {3266, 5, 4, 3, 2, 1, -1, -2}; 298 for (size_t l = 0; l < arraysize(lhs_inputs); l++) { 299 for (size_t r = 0; r < arraysize(rhs_inputs); r++) { 300 for (size_t o = 0; o < arraysize(kArithmeticOperators); o++) { 301 HandleAndZoneScope handles; 302 i::Factory* factory = handles.main_isolate()->factory(); 303 BytecodeArrayBuilder builder(handles.main_isolate(), 304 handles.main_zone(), 1, 0, 1); 305 306 Register reg(0); 307 int lhs = lhs_inputs[l]; 308 int rhs = rhs_inputs[r]; 309 builder.LoadLiteral(Smi::FromInt(lhs)) 310 .StoreAccumulatorInRegister(reg) 311 .LoadLiteral(Smi::FromInt(rhs)) 312 .BinaryOperation(kArithmeticOperators[o], reg) 313 .Return(); 314 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 315 316 InterpreterTester tester(handles.main_isolate(), bytecode_array); 317 auto callable = tester.GetCallable<>(); 318 Handle<Object> return_value = callable().ToHandleChecked(); 319 Handle<Object> expected_value = 320 factory->NewNumber(BinaryOpC(kArithmeticOperators[o], lhs, rhs)); 321 CHECK(return_value->SameValue(*expected_value)); 322 } 323 } 324 } 325 } 326 327 328 TEST(InterpreterBinaryOpsHeapNumber) { 329 double lhs_inputs[] = {3266.101, 1024.12, 0.01, -17.99, -18000.833, 9.1e17}; 330 double rhs_inputs[] = {3266.101, 5.999, 4.778, 3.331, 2.643, 331 1.1, -1.8, -2.9, 8.3e-27}; 332 for (size_t l = 0; l < arraysize(lhs_inputs); l++) { 333 for (size_t r = 0; r < arraysize(rhs_inputs); r++) { 334 for (size_t o = 0; o < arraysize(kArithmeticOperators); o++) { 335 HandleAndZoneScope handles; 336 i::Factory* factory = handles.main_isolate()->factory(); 337 BytecodeArrayBuilder builder(handles.main_isolate(), 338 handles.main_zone(), 1, 0, 1); 339 Register reg(0); 340 double lhs = lhs_inputs[l]; 341 double rhs = rhs_inputs[r]; 342 builder.LoadLiteral(factory->NewNumber(lhs)) 343 .StoreAccumulatorInRegister(reg) 344 .LoadLiteral(factory->NewNumber(rhs)) 345 .BinaryOperation(kArithmeticOperators[o], reg) 346 .Return(); 347 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 348 349 InterpreterTester tester(handles.main_isolate(), bytecode_array); 350 auto callable = tester.GetCallable<>(); 351 Handle<Object> return_value = callable().ToHandleChecked(); 352 Handle<Object> expected_value = 353 factory->NewNumber(BinaryOpC(kArithmeticOperators[o], lhs, rhs)); 354 CHECK(return_value->SameValue(*expected_value)); 355 } 356 } 357 } 358 } 359 360 361 TEST(InterpreterStringAdd) { 362 HandleAndZoneScope handles; 363 i::Factory* factory = handles.main_isolate()->factory(); 364 365 struct TestCase { 366 Handle<Object> lhs; 367 Handle<Object> rhs; 368 Handle<Object> expected_value; 369 } test_cases[] = { 370 {factory->NewStringFromStaticChars("a"), 371 factory->NewStringFromStaticChars("b"), 372 factory->NewStringFromStaticChars("ab")}, 373 {factory->NewStringFromStaticChars("aaaaaa"), 374 factory->NewStringFromStaticChars("b"), 375 factory->NewStringFromStaticChars("aaaaaab")}, 376 {factory->NewStringFromStaticChars("aaa"), 377 factory->NewStringFromStaticChars("bbbbb"), 378 factory->NewStringFromStaticChars("aaabbbbb")}, 379 {factory->NewStringFromStaticChars(""), 380 factory->NewStringFromStaticChars("b"), 381 factory->NewStringFromStaticChars("b")}, 382 {factory->NewStringFromStaticChars("a"), 383 factory->NewStringFromStaticChars(""), 384 factory->NewStringFromStaticChars("a")}, 385 {factory->NewStringFromStaticChars("1.11"), factory->NewHeapNumber(2.5), 386 factory->NewStringFromStaticChars("1.112.5")}, 387 {factory->NewStringFromStaticChars("-1.11"), factory->NewHeapNumber(2.56), 388 factory->NewStringFromStaticChars("-1.112.56")}, 389 {factory->NewStringFromStaticChars(""), factory->NewHeapNumber(2.5), 390 factory->NewStringFromStaticChars("2.5")}, 391 }; 392 393 for (size_t i = 0; i < arraysize(test_cases); i++) { 394 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 395 0, 1); 396 397 Register reg(0); 398 builder.LoadLiteral(test_cases[i].lhs) 399 .StoreAccumulatorInRegister(reg) 400 .LoadLiteral(test_cases[i].rhs) 401 .BinaryOperation(Token::Value::ADD, reg) 402 .Return(); 403 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 404 405 InterpreterTester tester(handles.main_isolate(), bytecode_array); 406 auto callable = tester.GetCallable<>(); 407 Handle<Object> return_value = callable().ToHandleChecked(); 408 CHECK(return_value->SameValue(*test_cases[i].expected_value)); 409 } 410 } 411 412 413 TEST(InterpreterParameter1) { 414 HandleAndZoneScope handles; 415 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 416 0, 0); 417 418 builder.LoadAccumulatorWithRegister(builder.Parameter(0)).Return(); 419 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 420 421 InterpreterTester tester(handles.main_isolate(), bytecode_array); 422 auto callable = tester.GetCallable<Handle<Object>>(); 423 424 // Check for heap objects. 425 Handle<Object> true_value = handles.main_isolate()->factory()->true_value(); 426 Handle<Object> return_val = callable(true_value).ToHandleChecked(); 427 CHECK(return_val.is_identical_to(true_value)); 428 429 // Check for Smis. 430 return_val = callable(Handle<Smi>(Smi::FromInt(3), handles.main_isolate())) 431 .ToHandleChecked(); 432 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(3)); 433 } 434 435 436 TEST(InterpreterParameter8) { 437 HandleAndZoneScope handles; 438 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 8, 439 0, 0); 440 441 builder.LoadAccumulatorWithRegister(builder.Parameter(0)) 442 .BinaryOperation(Token::Value::ADD, builder.Parameter(1)) 443 .BinaryOperation(Token::Value::ADD, builder.Parameter(2)) 444 .BinaryOperation(Token::Value::ADD, builder.Parameter(3)) 445 .BinaryOperation(Token::Value::ADD, builder.Parameter(4)) 446 .BinaryOperation(Token::Value::ADD, builder.Parameter(5)) 447 .BinaryOperation(Token::Value::ADD, builder.Parameter(6)) 448 .BinaryOperation(Token::Value::ADD, builder.Parameter(7)) 449 .Return(); 450 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 451 452 InterpreterTester tester(handles.main_isolate(), bytecode_array); 453 typedef Handle<Object> H; 454 auto callable = tester.GetCallable<H, H, H, H, H, H, H, H>(); 455 456 Handle<Smi> arg1 = Handle<Smi>(Smi::FromInt(1), handles.main_isolate()); 457 Handle<Smi> arg2 = Handle<Smi>(Smi::FromInt(2), handles.main_isolate()); 458 Handle<Smi> arg3 = Handle<Smi>(Smi::FromInt(3), handles.main_isolate()); 459 Handle<Smi> arg4 = Handle<Smi>(Smi::FromInt(4), handles.main_isolate()); 460 Handle<Smi> arg5 = Handle<Smi>(Smi::FromInt(5), handles.main_isolate()); 461 Handle<Smi> arg6 = Handle<Smi>(Smi::FromInt(6), handles.main_isolate()); 462 Handle<Smi> arg7 = Handle<Smi>(Smi::FromInt(7), handles.main_isolate()); 463 Handle<Smi> arg8 = Handle<Smi>(Smi::FromInt(8), handles.main_isolate()); 464 // Check for Smis. 465 Handle<Object> return_val = 466 callable(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) 467 .ToHandleChecked(); 468 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(36)); 469 } 470 471 472 TEST(InterpreterParameter1Assign) { 473 HandleAndZoneScope handles; 474 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 475 0, 0); 476 477 builder.LoadLiteral(Smi::FromInt(5)) 478 .StoreAccumulatorInRegister(builder.Parameter(0)) 479 .LoadAccumulatorWithRegister(builder.Parameter(0)) 480 .Return(); 481 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 482 483 InterpreterTester tester(handles.main_isolate(), bytecode_array); 484 auto callable = tester.GetCallable<Handle<Object>>(); 485 486 Handle<Object> return_val = 487 callable(Handle<Smi>(Smi::FromInt(3), handles.main_isolate())) 488 .ToHandleChecked(); 489 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(5)); 490 } 491 492 493 TEST(InterpreterLoadGlobal) { 494 HandleAndZoneScope handles; 495 496 // Test loading a global. 497 std::string source( 498 "var global = 321;\n" 499 "function " + InterpreterTester::function_name() + "() {\n" 500 " return global;\n" 501 "}"); 502 InterpreterTester tester(handles.main_isolate(), source.c_str()); 503 auto callable = tester.GetCallable<>(); 504 505 Handle<Object> return_val = callable().ToHandleChecked(); 506 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(321)); 507 } 508 509 510 TEST(InterpreterStoreGlobal) { 511 HandleAndZoneScope handles; 512 i::Isolate* isolate = handles.main_isolate(); 513 i::Factory* factory = isolate->factory(); 514 515 // Test storing to a global. 516 std::string source( 517 "var global = 321;\n" 518 "function " + InterpreterTester::function_name() + "() {\n" 519 " global = 999;\n" 520 "}"); 521 InterpreterTester tester(handles.main_isolate(), source.c_str()); 522 auto callable = tester.GetCallable<>(); 523 524 callable().ToHandleChecked(); 525 Handle<i::String> name = factory->InternalizeUtf8String("global"); 526 Handle<i::Object> global_obj = 527 Object::GetProperty(isolate->global_object(), name).ToHandleChecked(); 528 CHECK_EQ(Smi::cast(*global_obj), Smi::FromInt(999)); 529 } 530 531 532 TEST(InterpreterCallGlobal) { 533 HandleAndZoneScope handles; 534 535 // Test calling a global function. 536 std::string source( 537 "function g_add(a, b) { return a + b; }\n" 538 "function " + InterpreterTester::function_name() + "() {\n" 539 " return g_add(5, 10);\n" 540 "}"); 541 InterpreterTester tester(handles.main_isolate(), source.c_str()); 542 auto callable = tester.GetCallable<>(); 543 544 Handle<Object> return_val = callable().ToHandleChecked(); 545 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(15)); 546 } 547 548 549 TEST(InterpreterLoadUnallocated) { 550 HandleAndZoneScope handles; 551 552 // Test loading an unallocated global. 553 std::string source( 554 "unallocated = 123;\n" 555 "function " + InterpreterTester::function_name() + "() {\n" 556 " return unallocated;\n" 557 "}"); 558 InterpreterTester tester(handles.main_isolate(), source.c_str()); 559 auto callable = tester.GetCallable<>(); 560 561 Handle<Object> return_val = callable().ToHandleChecked(); 562 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123)); 563 } 564 565 566 TEST(InterpreterStoreUnallocated) { 567 HandleAndZoneScope handles; 568 i::Isolate* isolate = handles.main_isolate(); 569 i::Factory* factory = isolate->factory(); 570 571 // Test storing to an unallocated global. 572 std::string source( 573 "unallocated = 321;\n" 574 "function " + InterpreterTester::function_name() + "() {\n" 575 " unallocated = 999;\n" 576 "}"); 577 InterpreterTester tester(handles.main_isolate(), source.c_str()); 578 auto callable = tester.GetCallable<>(); 579 580 callable().ToHandleChecked(); 581 Handle<i::String> name = factory->InternalizeUtf8String("unallocated"); 582 Handle<i::Object> global_obj = 583 Object::GetProperty(isolate->global_object(), name).ToHandleChecked(); 584 CHECK_EQ(Smi::cast(*global_obj), Smi::FromInt(999)); 585 } 586 587 588 TEST(InterpreterLoadNamedProperty) { 589 HandleAndZoneScope handles; 590 i::Isolate* isolate = handles.main_isolate(); 591 i::Factory* factory = isolate->factory(); 592 i::Zone zone(isolate->allocator()); 593 594 i::FeedbackVectorSpec feedback_spec(&zone); 595 i::FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot(); 596 597 Handle<i::TypeFeedbackVector> vector = 598 i::NewTypeFeedbackVector(isolate, &feedback_spec); 599 600 Handle<i::String> name = factory->NewStringFromAsciiChecked("val"); 601 name = factory->string_table()->LookupString(isolate, name); 602 603 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 604 0, 0); 605 606 builder.LoadNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot)) 607 .Return(); 608 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 609 610 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); 611 auto callable = tester.GetCallable<Handle<Object>>(); 612 613 Handle<Object> object = InterpreterTester::NewObject("({ val : 123 })"); 614 // Test IC miss. 615 Handle<Object> return_val = callable(object).ToHandleChecked(); 616 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123)); 617 618 // Test transition to monomorphic IC. 619 return_val = callable(object).ToHandleChecked(); 620 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123)); 621 622 // Test transition to polymorphic IC. 623 Handle<Object> object2 = 624 InterpreterTester::NewObject("({ val : 456, other : 123 })"); 625 return_val = callable(object2).ToHandleChecked(); 626 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(456)); 627 628 // Test transition to megamorphic IC. 629 Handle<Object> object3 = 630 InterpreterTester::NewObject("({ val : 789, val2 : 123 })"); 631 callable(object3).ToHandleChecked(); 632 Handle<Object> object4 = 633 InterpreterTester::NewObject("({ val : 789, val3 : 123 })"); 634 callable(object4).ToHandleChecked(); 635 Handle<Object> object5 = 636 InterpreterTester::NewObject("({ val : 789, val4 : 123 })"); 637 return_val = callable(object5).ToHandleChecked(); 638 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(789)); 639 } 640 641 642 TEST(InterpreterLoadKeyedProperty) { 643 HandleAndZoneScope handles; 644 i::Isolate* isolate = handles.main_isolate(); 645 i::Factory* factory = isolate->factory(); 646 i::Zone zone(isolate->allocator()); 647 648 i::FeedbackVectorSpec feedback_spec(&zone); 649 i::FeedbackVectorSlot slot = feedback_spec.AddKeyedLoadICSlot(); 650 651 Handle<i::TypeFeedbackVector> vector = 652 i::NewTypeFeedbackVector(isolate, &feedback_spec); 653 654 Handle<i::String> key = factory->NewStringFromAsciiChecked("key"); 655 key = factory->string_table()->LookupString(isolate, key); 656 657 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 658 0, 1); 659 660 builder.LoadLiteral(key) 661 .LoadKeyedProperty(builder.Parameter(0), vector->GetIndex(slot)) 662 .Return(); 663 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 664 665 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); 666 auto callable = tester.GetCallable<Handle<Object>>(); 667 668 Handle<Object> object = InterpreterTester::NewObject("({ key : 123 })"); 669 // Test IC miss. 670 Handle<Object> return_val = callable(object).ToHandleChecked(); 671 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123)); 672 673 // Test transition to monomorphic IC. 674 return_val = callable(object).ToHandleChecked(); 675 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123)); 676 677 // Test transition to megamorphic IC. 678 Handle<Object> object3 = 679 InterpreterTester::NewObject("({ key : 789, val2 : 123 })"); 680 return_val = callable(object3).ToHandleChecked(); 681 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(789)); 682 } 683 684 685 TEST(InterpreterStoreNamedProperty) { 686 HandleAndZoneScope handles; 687 i::Isolate* isolate = handles.main_isolate(); 688 i::Factory* factory = isolate->factory(); 689 i::Zone zone(isolate->allocator()); 690 691 i::FeedbackVectorSpec feedback_spec(&zone); 692 i::FeedbackVectorSlot slot = feedback_spec.AddStoreICSlot(); 693 694 Handle<i::TypeFeedbackVector> vector = 695 i::NewTypeFeedbackVector(isolate, &feedback_spec); 696 697 Handle<i::String> name = factory->NewStringFromAsciiChecked("val"); 698 name = factory->string_table()->LookupString(isolate, name); 699 700 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 701 0, 0); 702 703 builder.LoadLiteral(Smi::FromInt(999)) 704 .StoreNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot), 705 i::STRICT) 706 .Return(); 707 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 708 709 InterpreterTester tester(isolate, bytecode_array, vector); 710 auto callable = tester.GetCallable<Handle<Object>>(); 711 Handle<Object> object = InterpreterTester::NewObject("({ val : 123 })"); 712 // Test IC miss. 713 Handle<Object> result; 714 callable(object).ToHandleChecked(); 715 CHECK(Runtime::GetObjectProperty(isolate, object, name).ToHandle(&result)); 716 CHECK_EQ(Smi::cast(*result), Smi::FromInt(999)); 717 718 // Test transition to monomorphic IC. 719 callable(object).ToHandleChecked(); 720 CHECK(Runtime::GetObjectProperty(isolate, object, name).ToHandle(&result)); 721 CHECK_EQ(Smi::cast(*result), Smi::FromInt(999)); 722 723 // Test transition to polymorphic IC. 724 Handle<Object> object2 = 725 InterpreterTester::NewObject("({ val : 456, other : 123 })"); 726 callable(object2).ToHandleChecked(); 727 CHECK(Runtime::GetObjectProperty(isolate, object2, name).ToHandle(&result)); 728 CHECK_EQ(Smi::cast(*result), Smi::FromInt(999)); 729 730 // Test transition to megamorphic IC. 731 Handle<Object> object3 = 732 InterpreterTester::NewObject("({ val : 789, val2 : 123 })"); 733 callable(object3).ToHandleChecked(); 734 Handle<Object> object4 = 735 InterpreterTester::NewObject("({ val : 789, val3 : 123 })"); 736 callable(object4).ToHandleChecked(); 737 Handle<Object> object5 = 738 InterpreterTester::NewObject("({ val : 789, val4 : 123 })"); 739 callable(object5).ToHandleChecked(); 740 CHECK(Runtime::GetObjectProperty(isolate, object5, name).ToHandle(&result)); 741 CHECK_EQ(Smi::cast(*result), Smi::FromInt(999)); 742 } 743 744 745 TEST(InterpreterStoreKeyedProperty) { 746 HandleAndZoneScope handles; 747 i::Isolate* isolate = handles.main_isolate(); 748 i::Factory* factory = isolate->factory(); 749 i::Zone zone(isolate->allocator()); 750 751 i::FeedbackVectorSpec feedback_spec(&zone); 752 i::FeedbackVectorSlot slot = feedback_spec.AddKeyedStoreICSlot(); 753 754 Handle<i::TypeFeedbackVector> vector = 755 i::NewTypeFeedbackVector(isolate, &feedback_spec); 756 757 Handle<i::String> name = factory->NewStringFromAsciiChecked("val"); 758 name = factory->string_table()->LookupString(isolate, name); 759 760 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 761 0, 1); 762 763 builder.LoadLiteral(name) 764 .StoreAccumulatorInRegister(Register(0)) 765 .LoadLiteral(Smi::FromInt(999)) 766 .StoreKeyedProperty(builder.Parameter(0), Register(0), 767 vector->GetIndex(slot), i::SLOPPY) 768 .Return(); 769 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 770 771 InterpreterTester tester(isolate, bytecode_array, vector); 772 auto callable = tester.GetCallable<Handle<Object>>(); 773 Handle<Object> object = InterpreterTester::NewObject("({ val : 123 })"); 774 // Test IC miss. 775 Handle<Object> result; 776 callable(object).ToHandleChecked(); 777 CHECK(Runtime::GetObjectProperty(isolate, object, name).ToHandle(&result)); 778 CHECK_EQ(Smi::cast(*result), Smi::FromInt(999)); 779 780 // Test transition to monomorphic IC. 781 callable(object).ToHandleChecked(); 782 CHECK(Runtime::GetObjectProperty(isolate, object, name).ToHandle(&result)); 783 CHECK_EQ(Smi::cast(*result), Smi::FromInt(999)); 784 785 // Test transition to megamorphic IC. 786 Handle<Object> object2 = 787 InterpreterTester::NewObject("({ val : 456, other : 123 })"); 788 callable(object2).ToHandleChecked(); 789 CHECK(Runtime::GetObjectProperty(isolate, object2, name).ToHandle(&result)); 790 CHECK_EQ(Smi::cast(*result), Smi::FromInt(999)); 791 } 792 793 static void TestInterpreterCall(TailCallMode tail_call_mode) { 794 HandleAndZoneScope handles; 795 i::Isolate* isolate = handles.main_isolate(); 796 i::Factory* factory = isolate->factory(); 797 i::Zone zone(isolate->allocator()); 798 799 i::FeedbackVectorSpec feedback_spec(&zone); 800 i::FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot(); 801 802 Handle<i::TypeFeedbackVector> vector = 803 i::NewTypeFeedbackVector(isolate, &feedback_spec); 804 int slot_index = vector->GetIndex(slot); 805 806 Handle<i::String> name = factory->NewStringFromAsciiChecked("func"); 807 name = factory->string_table()->LookupString(isolate, name); 808 809 // Check with no args. 810 { 811 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 812 0, 1); 813 814 builder.LoadNamedProperty(builder.Parameter(0), name, slot_index) 815 .StoreAccumulatorInRegister(Register(0)) 816 .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode) 817 .Return(); 818 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 819 820 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); 821 auto callable = tester.GetCallable<Handle<Object>>(); 822 823 Handle<Object> object = InterpreterTester::NewObject( 824 "new (function Obj() { this.func = function() { return 0x265; }})()"); 825 Handle<Object> return_val = callable(object).ToHandleChecked(); 826 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(0x265)); 827 } 828 829 // Check that receiver is passed properly. 830 { 831 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 832 0, 1); 833 834 builder.LoadNamedProperty(builder.Parameter(0), name, slot_index) 835 .StoreAccumulatorInRegister(Register(0)) 836 .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode) 837 .Return(); 838 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 839 840 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); 841 auto callable = tester.GetCallable<Handle<Object>>(); 842 843 Handle<Object> object = InterpreterTester::NewObject( 844 "new (function Obj() {" 845 " this.val = 1234;" 846 " this.func = function() { return this.val; };" 847 "})()"); 848 Handle<Object> return_val = callable(object).ToHandleChecked(); 849 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(1234)); 850 } 851 852 // Check with two parameters (+ receiver). 853 { 854 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 855 0, 4); 856 857 builder.LoadNamedProperty(builder.Parameter(0), name, slot_index) 858 .StoreAccumulatorInRegister(Register(0)) 859 .LoadAccumulatorWithRegister(builder.Parameter(0)) 860 .StoreAccumulatorInRegister(Register(1)) 861 .LoadLiteral(Smi::FromInt(51)) 862 .StoreAccumulatorInRegister(Register(2)) 863 .LoadLiteral(Smi::FromInt(11)) 864 .StoreAccumulatorInRegister(Register(3)) 865 .Call(Register(0), Register(1), 3, 0, tail_call_mode) 866 .Return(); 867 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 868 869 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); 870 auto callable = tester.GetCallable<Handle<Object>>(); 871 872 Handle<Object> object = InterpreterTester::NewObject( 873 "new (function Obj() { " 874 " this.func = function(a, b) { return a - b; }" 875 "})()"); 876 Handle<Object> return_val = callable(object).ToHandleChecked(); 877 CHECK(return_val->SameValue(Smi::FromInt(40))); 878 } 879 880 // Check with 10 parameters (+ receiver). 881 { 882 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 883 0, 12); 884 885 builder.LoadNamedProperty(builder.Parameter(0), name, slot_index) 886 .StoreAccumulatorInRegister(Register(0)) 887 .LoadAccumulatorWithRegister(builder.Parameter(0)) 888 .StoreAccumulatorInRegister(Register(1)) 889 .LoadLiteral(factory->NewStringFromAsciiChecked("a")) 890 .StoreAccumulatorInRegister(Register(2)) 891 .LoadLiteral(factory->NewStringFromAsciiChecked("b")) 892 .StoreAccumulatorInRegister(Register(3)) 893 .LoadLiteral(factory->NewStringFromAsciiChecked("c")) 894 .StoreAccumulatorInRegister(Register(4)) 895 .LoadLiteral(factory->NewStringFromAsciiChecked("d")) 896 .StoreAccumulatorInRegister(Register(5)) 897 .LoadLiteral(factory->NewStringFromAsciiChecked("e")) 898 .StoreAccumulatorInRegister(Register(6)) 899 .LoadLiteral(factory->NewStringFromAsciiChecked("f")) 900 .StoreAccumulatorInRegister(Register(7)) 901 .LoadLiteral(factory->NewStringFromAsciiChecked("g")) 902 .StoreAccumulatorInRegister(Register(8)) 903 .LoadLiteral(factory->NewStringFromAsciiChecked("h")) 904 .StoreAccumulatorInRegister(Register(9)) 905 .LoadLiteral(factory->NewStringFromAsciiChecked("i")) 906 .StoreAccumulatorInRegister(Register(10)) 907 .LoadLiteral(factory->NewStringFromAsciiChecked("j")) 908 .StoreAccumulatorInRegister(Register(11)) 909 .Call(Register(0), Register(1), 11, 0, tail_call_mode) 910 .Return(); 911 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 912 913 InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); 914 auto callable = tester.GetCallable<Handle<Object>>(); 915 916 Handle<Object> object = InterpreterTester::NewObject( 917 "new (function Obj() { " 918 " this.prefix = \"prefix_\";" 919 " this.func = function(a, b, c, d, e, f, g, h, i, j) {" 920 " return this.prefix + a + b + c + d + e + f + g + h + i + j;" 921 " }" 922 "})()"); 923 Handle<Object> return_val = callable(object).ToHandleChecked(); 924 Handle<i::String> expected = 925 factory->NewStringFromAsciiChecked("prefix_abcdefghij"); 926 CHECK(i::String::cast(*return_val)->Equals(*expected)); 927 } 928 } 929 930 TEST(InterpreterCall) { TestInterpreterCall(TailCallMode::kDisallow); } 931 932 TEST(InterpreterTailCall) { TestInterpreterCall(TailCallMode::kAllow); } 933 934 static BytecodeArrayBuilder& SetRegister(BytecodeArrayBuilder& builder, 935 Register reg, int value, 936 Register scratch) { 937 return builder.StoreAccumulatorInRegister(scratch) 938 .LoadLiteral(Smi::FromInt(value)) 939 .StoreAccumulatorInRegister(reg) 940 .LoadAccumulatorWithRegister(scratch); 941 } 942 943 944 static BytecodeArrayBuilder& IncrementRegister(BytecodeArrayBuilder& builder, 945 Register reg, int value, 946 Register scratch) { 947 return builder.StoreAccumulatorInRegister(scratch) 948 .LoadLiteral(Smi::FromInt(value)) 949 .BinaryOperation(Token::Value::ADD, reg) 950 .StoreAccumulatorInRegister(reg) 951 .LoadAccumulatorWithRegister(scratch); 952 } 953 954 955 TEST(InterpreterJumps) { 956 HandleAndZoneScope handles; 957 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0, 958 0, 2); 959 960 Register reg(0), scratch(1); 961 BytecodeLabel label[3]; 962 963 builder.LoadLiteral(Smi::FromInt(0)) 964 .StoreAccumulatorInRegister(reg) 965 .Jump(&label[1]); 966 SetRegister(builder, reg, 1024, scratch).Bind(&label[0]); 967 IncrementRegister(builder, reg, 1, scratch).Jump(&label[2]); 968 SetRegister(builder, reg, 2048, scratch).Bind(&label[1]); 969 IncrementRegister(builder, reg, 2, scratch).Jump(&label[0]); 970 SetRegister(builder, reg, 4096, scratch).Bind(&label[2]); 971 IncrementRegister(builder, reg, 4, scratch) 972 .LoadAccumulatorWithRegister(reg) 973 .Return(); 974 975 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 976 InterpreterTester tester(handles.main_isolate(), bytecode_array); 977 auto callable = tester.GetCallable<>(); 978 Handle<Object> return_value = callable().ToHandleChecked(); 979 CHECK_EQ(Smi::cast(*return_value)->value(), 7); 980 } 981 982 983 TEST(InterpreterConditionalJumps) { 984 HandleAndZoneScope handles; 985 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0, 986 0, 2); 987 988 Register reg(0), scratch(1); 989 BytecodeLabel label[2]; 990 BytecodeLabel done, done1; 991 992 builder.LoadLiteral(Smi::FromInt(0)) 993 .StoreAccumulatorInRegister(reg) 994 .LoadFalse() 995 .JumpIfFalse(&label[0]); 996 IncrementRegister(builder, reg, 1024, scratch) 997 .Bind(&label[0]) 998 .LoadTrue() 999 .JumpIfFalse(&done); 1000 IncrementRegister(builder, reg, 1, scratch).LoadTrue().JumpIfTrue(&label[1]); 1001 IncrementRegister(builder, reg, 2048, scratch).Bind(&label[1]); 1002 IncrementRegister(builder, reg, 2, scratch).LoadFalse().JumpIfTrue(&done1); 1003 IncrementRegister(builder, reg, 4, scratch) 1004 .LoadAccumulatorWithRegister(reg) 1005 .Bind(&done) 1006 .Bind(&done1) 1007 .Return(); 1008 1009 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 1010 InterpreterTester tester(handles.main_isolate(), bytecode_array); 1011 auto callable = tester.GetCallable<>(); 1012 Handle<Object> return_value = callable().ToHandleChecked(); 1013 CHECK_EQ(Smi::cast(*return_value)->value(), 7); 1014 } 1015 1016 TEST(InterpreterConditionalJumps2) { 1017 // TODO(oth): Add tests for all conditional jumps near and far. 1018 HandleAndZoneScope handles; 1019 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0, 1020 0, 2); 1021 1022 Register reg(0), scratch(1); 1023 BytecodeLabel label[2]; 1024 BytecodeLabel done, done1; 1025 1026 builder.LoadLiteral(Smi::FromInt(0)) 1027 .StoreAccumulatorInRegister(reg) 1028 .LoadFalse() 1029 .JumpIfFalse(&label[0]); 1030 IncrementRegister(builder, reg, 1024, scratch) 1031 .Bind(&label[0]) 1032 .LoadTrue() 1033 .JumpIfFalse(&done); 1034 IncrementRegister(builder, reg, 1, scratch).LoadTrue().JumpIfTrue(&label[1]); 1035 IncrementRegister(builder, reg, 2048, scratch).Bind(&label[1]); 1036 IncrementRegister(builder, reg, 2, scratch).LoadFalse().JumpIfTrue(&done1); 1037 IncrementRegister(builder, reg, 4, scratch) 1038 .LoadAccumulatorWithRegister(reg) 1039 .Bind(&done) 1040 .Bind(&done1) 1041 .Return(); 1042 1043 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 1044 InterpreterTester tester(handles.main_isolate(), bytecode_array); 1045 auto callable = tester.GetCallable<>(); 1046 Handle<Object> return_value = callable().ToHandleChecked(); 1047 CHECK_EQ(Smi::cast(*return_value)->value(), 7); 1048 } 1049 1050 TEST(InterpreterJumpConstantWith16BitOperand) { 1051 HandleAndZoneScope handles; 1052 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 1053 0, 257); 1054 1055 Register reg(0), scratch(256); 1056 BytecodeLabel done, fake; 1057 1058 builder.LoadLiteral(Smi::FromInt(0)); 1059 builder.StoreAccumulatorInRegister(reg); 1060 // Consume all 8-bit operands 1061 for (int i = 1; i <= 256; i++) { 1062 builder.LoadLiteral(handles.main_isolate()->factory()->NewNumber(i)); 1063 builder.BinaryOperation(Token::Value::ADD, reg); 1064 builder.StoreAccumulatorInRegister(reg); 1065 } 1066 builder.Jump(&done); 1067 1068 // Emit more than 16-bit immediate operands worth of code to jump over. 1069 builder.Bind(&fake); 1070 for (int i = 0; i < 6600; i++) { 1071 builder.LoadLiteral(Smi::FromInt(0)); // 1-byte 1072 builder.BinaryOperation(Token::Value::ADD, scratch); // 4-bytes 1073 builder.StoreAccumulatorInRegister(scratch); // 4-bytes 1074 builder.MoveRegister(scratch, reg); // 6-bytes 1075 } 1076 builder.Bind(&done); 1077 builder.LoadAccumulatorWithRegister(reg); 1078 builder.Return(); 1079 1080 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 1081 BytecodeArrayIterator iterator(bytecode_array); 1082 1083 bool found_16bit_constant_jump = false; 1084 while (!iterator.done()) { 1085 if (iterator.current_bytecode() == Bytecode::kJumpConstant && 1086 iterator.current_operand_scale() == OperandScale::kDouble) { 1087 found_16bit_constant_jump = true; 1088 break; 1089 } 1090 iterator.Advance(); 1091 } 1092 CHECK(found_16bit_constant_jump); 1093 1094 InterpreterTester tester(handles.main_isolate(), bytecode_array); 1095 auto callable = tester.GetCallable<>(); 1096 Handle<Object> return_value = callable().ToHandleChecked(); 1097 CHECK_EQ(Smi::cast(*return_value)->value(), 256.0 / 2 * (1 + 256)); 1098 } 1099 1100 TEST(InterpreterJumpWith32BitOperand) { 1101 HandleAndZoneScope handles; 1102 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 1103 0, 1); 1104 Register reg(0); 1105 BytecodeLabel done; 1106 1107 builder.LoadLiteral(Smi::FromInt(0)); 1108 builder.StoreAccumulatorInRegister(reg); 1109 // Consume all 16-bit constant pool entries 1110 for (int i = 1; i <= 65536; i++) { 1111 builder.LoadLiteral(handles.main_isolate()->factory()->NewNumber(i)); 1112 } 1113 builder.Jump(&done); 1114 builder.LoadLiteral(Smi::FromInt(0)); 1115 builder.Bind(&done); 1116 builder.Return(); 1117 1118 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 1119 BytecodeArrayIterator iterator(bytecode_array); 1120 1121 bool found_32bit_jump = false; 1122 while (!iterator.done()) { 1123 if (iterator.current_bytecode() == Bytecode::kJump && 1124 iterator.current_operand_scale() == OperandScale::kQuadruple) { 1125 found_32bit_jump = true; 1126 break; 1127 } 1128 iterator.Advance(); 1129 } 1130 CHECK(found_32bit_jump); 1131 1132 InterpreterTester tester(handles.main_isolate(), bytecode_array); 1133 auto callable = tester.GetCallable<>(); 1134 Handle<Object> return_value = callable().ToHandleChecked(); 1135 CHECK_EQ(Smi::cast(*return_value)->value(), 65536.0); 1136 } 1137 1138 static const Token::Value kComparisonTypes[] = { 1139 Token::Value::EQ, Token::Value::NE, Token::Value::EQ_STRICT, 1140 Token::Value::LT, Token::Value::LTE, Token::Value::GT, 1141 Token::Value::GTE}; 1142 1143 template <typename T> 1144 bool CompareC(Token::Value op, T lhs, T rhs, bool types_differed = false) { 1145 switch (op) { 1146 case Token::Value::EQ: 1147 return lhs == rhs; 1148 case Token::Value::NE: 1149 return lhs != rhs; 1150 case Token::Value::EQ_STRICT: 1151 return (lhs == rhs) && !types_differed; 1152 case Token::Value::NE_STRICT: 1153 return (lhs != rhs) || types_differed; 1154 case Token::Value::LT: 1155 return lhs < rhs; 1156 case Token::Value::LTE: 1157 return lhs <= rhs; 1158 case Token::Value::GT: 1159 return lhs > rhs; 1160 case Token::Value::GTE: 1161 return lhs >= rhs; 1162 default: 1163 UNREACHABLE(); 1164 return false; 1165 } 1166 } 1167 1168 1169 TEST(InterpreterSmiComparisons) { 1170 // NB Constants cover 31-bit space. 1171 int inputs[] = {v8::internal::kMinInt / 2, 1172 v8::internal::kMinInt / 4, 1173 -108733832, 1174 -999, 1175 -42, 1176 -2, 1177 -1, 1178 0, 1179 +1, 1180 +2, 1181 42, 1182 12345678, 1183 v8::internal::kMaxInt / 4, 1184 v8::internal::kMaxInt / 2}; 1185 1186 for (size_t c = 0; c < arraysize(kComparisonTypes); c++) { 1187 Token::Value comparison = kComparisonTypes[c]; 1188 for (size_t i = 0; i < arraysize(inputs); i++) { 1189 for (size_t j = 0; j < arraysize(inputs); j++) { 1190 HandleAndZoneScope handles; 1191 BytecodeArrayBuilder builder(handles.main_isolate(), 1192 handles.main_zone(), 0, 0, 1); 1193 1194 Register r0(0); 1195 builder.LoadLiteral(Smi::FromInt(inputs[i])) 1196 .StoreAccumulatorInRegister(r0) 1197 .LoadLiteral(Smi::FromInt(inputs[j])) 1198 .CompareOperation(comparison, r0) 1199 .Return(); 1200 1201 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 1202 InterpreterTester tester(handles.main_isolate(), bytecode_array); 1203 auto callable = tester.GetCallable<>(); 1204 Handle<Object> return_value = callable().ToHandleChecked(); 1205 CHECK(return_value->IsBoolean()); 1206 CHECK_EQ(return_value->BooleanValue(), 1207 CompareC(comparison, inputs[i], inputs[j])); 1208 } 1209 } 1210 } 1211 } 1212 1213 1214 TEST(InterpreterHeapNumberComparisons) { 1215 double inputs[] = {std::numeric_limits<double>::min(), 1216 std::numeric_limits<double>::max(), 1217 -0.001, 1218 0.01, 1219 0.1000001, 1220 1e99, 1221 -1e-99}; 1222 for (size_t c = 0; c < arraysize(kComparisonTypes); c++) { 1223 Token::Value comparison = kComparisonTypes[c]; 1224 for (size_t i = 0; i < arraysize(inputs); i++) { 1225 for (size_t j = 0; j < arraysize(inputs); j++) { 1226 HandleAndZoneScope handles; 1227 i::Factory* factory = handles.main_isolate()->factory(); 1228 BytecodeArrayBuilder builder(handles.main_isolate(), 1229 handles.main_zone(), 0, 0, 1); 1230 1231 Register r0(0); 1232 builder.LoadLiteral(factory->NewHeapNumber(inputs[i])) 1233 .StoreAccumulatorInRegister(r0) 1234 .LoadLiteral(factory->NewHeapNumber(inputs[j])) 1235 .CompareOperation(comparison, r0) 1236 .Return(); 1237 1238 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 1239 InterpreterTester tester(handles.main_isolate(), bytecode_array); 1240 auto callable = tester.GetCallable<>(); 1241 Handle<Object> return_value = callable().ToHandleChecked(); 1242 CHECK(return_value->IsBoolean()); 1243 CHECK_EQ(return_value->BooleanValue(), 1244 CompareC(comparison, inputs[i], inputs[j])); 1245 } 1246 } 1247 } 1248 } 1249 1250 1251 TEST(InterpreterStringComparisons) { 1252 std::string inputs[] = {"A", "abc", "z", "", "Foo!", "Foo"}; 1253 1254 for (size_t c = 0; c < arraysize(kComparisonTypes); c++) { 1255 Token::Value comparison = kComparisonTypes[c]; 1256 for (size_t i = 0; i < arraysize(inputs); i++) { 1257 for (size_t j = 0; j < arraysize(inputs); j++) { 1258 const char* lhs = inputs[i].c_str(); 1259 const char* rhs = inputs[j].c_str(); 1260 HandleAndZoneScope handles; 1261 i::Factory* factory = handles.main_isolate()->factory(); 1262 BytecodeArrayBuilder builder(handles.main_isolate(), 1263 handles.main_zone(), 0, 0, 1); 1264 1265 Register r0(0); 1266 builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs)) 1267 .StoreAccumulatorInRegister(r0) 1268 .LoadLiteral(factory->NewStringFromAsciiChecked(rhs)) 1269 .CompareOperation(comparison, r0) 1270 .Return(); 1271 1272 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 1273 InterpreterTester tester(handles.main_isolate(), bytecode_array); 1274 auto callable = tester.GetCallable<>(); 1275 Handle<Object> return_value = callable().ToHandleChecked(); 1276 CHECK(return_value->IsBoolean()); 1277 CHECK_EQ(return_value->BooleanValue(), 1278 CompareC(comparison, inputs[i], inputs[j])); 1279 } 1280 } 1281 } 1282 } 1283 1284 1285 TEST(InterpreterMixedComparisons) { 1286 // This test compares a HeapNumber with a String. The latter is 1287 // convertible to a HeapNumber so comparison will be between numeric 1288 // values except for the strict comparisons where no conversion is 1289 // performed. 1290 const char* inputs[] = {"-1.77", "-40.333", "0.01", "55.77e5", "2.01"}; 1291 1292 i::UnicodeCache unicode_cache; 1293 1294 for (size_t c = 0; c < arraysize(kComparisonTypes); c++) { 1295 Token::Value comparison = kComparisonTypes[c]; 1296 for (size_t i = 0; i < arraysize(inputs); i++) { 1297 for (size_t j = 0; j < arraysize(inputs); j++) { 1298 for (int pass = 0; pass < 2; pass++) { 1299 const char* lhs_cstr = inputs[i]; 1300 const char* rhs_cstr = inputs[j]; 1301 double lhs = StringToDouble(&unicode_cache, lhs_cstr, 1302 i::ConversionFlags::NO_FLAGS); 1303 double rhs = StringToDouble(&unicode_cache, rhs_cstr, 1304 i::ConversionFlags::NO_FLAGS); 1305 HandleAndZoneScope handles; 1306 i::Factory* factory = handles.main_isolate()->factory(); 1307 BytecodeArrayBuilder builder(handles.main_isolate(), 1308 handles.main_zone(), 0, 0, 1); 1309 1310 Register r0(0); 1311 if (pass == 0) { 1312 // Comparison with HeapNumber on the lhs and String on the rhs 1313 builder.LoadLiteral(factory->NewNumber(lhs)) 1314 .StoreAccumulatorInRegister(r0) 1315 .LoadLiteral(factory->NewStringFromAsciiChecked(rhs_cstr)) 1316 .CompareOperation(comparison, r0) 1317 .Return(); 1318 } else { 1319 // Comparison with HeapNumber on the rhs and String on the lhs 1320 builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs_cstr)) 1321 .StoreAccumulatorInRegister(r0) 1322 .LoadLiteral(factory->NewNumber(rhs)) 1323 .CompareOperation(comparison, r0) 1324 .Return(); 1325 } 1326 1327 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 1328 InterpreterTester tester(handles.main_isolate(), bytecode_array); 1329 auto callable = tester.GetCallable<>(); 1330 Handle<Object> return_value = callable().ToHandleChecked(); 1331 CHECK(return_value->IsBoolean()); 1332 CHECK_EQ(return_value->BooleanValue(), 1333 CompareC(comparison, lhs, rhs, true)); 1334 } 1335 } 1336 } 1337 } 1338 } 1339 1340 TEST(InterpreterStrictNotEqual) { 1341 HandleAndZoneScope handles; 1342 i::Factory* factory = handles.main_isolate()->factory(); 1343 const char* code_snippet = 1344 "function f(lhs, rhs) {\n" 1345 " return lhs !== rhs;\n" 1346 "}\n" 1347 "f(0, 0);\n"; 1348 InterpreterTester tester(handles.main_isolate(), code_snippet); 1349 auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>(); 1350 1351 // Test passing different types. 1352 const char* inputs[] = {"-1.77", "-40.333", "0.01", "55.77e5", "2.01"}; 1353 i::UnicodeCache unicode_cache; 1354 for (size_t i = 0; i < arraysize(inputs); i++) { 1355 for (size_t j = 0; j < arraysize(inputs); j++) { 1356 double lhs = StringToDouble(&unicode_cache, inputs[i], 1357 i::ConversionFlags::NO_FLAGS); 1358 double rhs = StringToDouble(&unicode_cache, inputs[j], 1359 i::ConversionFlags::NO_FLAGS); 1360 Handle<Object> lhs_obj = factory->NewNumber(lhs); 1361 Handle<Object> rhs_obj = factory->NewStringFromAsciiChecked(inputs[j]); 1362 1363 Handle<Object> return_value = 1364 callable(lhs_obj, rhs_obj).ToHandleChecked(); 1365 CHECK(return_value->IsBoolean()); 1366 CHECK_EQ(return_value->BooleanValue(), 1367 CompareC(Token::Value::NE_STRICT, lhs, rhs, true)); 1368 } 1369 } 1370 1371 // Test passing string types. 1372 const char* inputs_str[] = {"A", "abc", "z", "", "Foo!", "Foo"}; 1373 for (size_t i = 0; i < arraysize(inputs_str); i++) { 1374 for (size_t j = 0; j < arraysize(inputs_str); j++) { 1375 Handle<Object> lhs_obj = 1376 factory->NewStringFromAsciiChecked(inputs_str[i]); 1377 Handle<Object> rhs_obj = 1378 factory->NewStringFromAsciiChecked(inputs_str[j]); 1379 1380 Handle<Object> return_value = 1381 callable(lhs_obj, rhs_obj).ToHandleChecked(); 1382 CHECK(return_value->IsBoolean()); 1383 CHECK_EQ(return_value->BooleanValue(), 1384 CompareC(Token::Value::NE_STRICT, inputs_str[i], inputs_str[j])); 1385 } 1386 } 1387 1388 // Test passing doubles. 1389 double inputs_number[] = {std::numeric_limits<double>::min(), 1390 std::numeric_limits<double>::max(), 1391 -0.001, 1392 0.01, 1393 0.1000001, 1394 1e99, 1395 -1e-99}; 1396 for (size_t i = 0; i < arraysize(inputs_number); i++) { 1397 for (size_t j = 0; j < arraysize(inputs_number); j++) { 1398 Handle<Object> lhs_obj = factory->NewNumber(inputs_number[i]); 1399 Handle<Object> rhs_obj = factory->NewNumber(inputs_number[j]); 1400 1401 Handle<Object> return_value = 1402 callable(lhs_obj, rhs_obj).ToHandleChecked(); 1403 CHECK(return_value->IsBoolean()); 1404 CHECK_EQ(return_value->BooleanValue(), 1405 CompareC(Token::Value::NE_STRICT, inputs_number[i], 1406 inputs_number[j])); 1407 } 1408 } 1409 } 1410 1411 TEST(InterpreterInstanceOf) { 1412 HandleAndZoneScope handles; 1413 i::Factory* factory = handles.main_isolate()->factory(); 1414 Handle<i::String> name = factory->NewStringFromAsciiChecked("cons"); 1415 Handle<i::JSFunction> func = factory->NewFunction(name); 1416 Handle<i::JSObject> instance = factory->NewJSObject(func); 1417 Handle<i::Object> other = factory->NewNumber(3.3333); 1418 Handle<i::Object> cases[] = {Handle<i::Object>::cast(instance), other}; 1419 for (size_t i = 0; i < arraysize(cases); i++) { 1420 bool expected_value = (i == 0); 1421 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0, 1422 0, 1); 1423 1424 Register r0(0); 1425 builder.LoadLiteral(cases[i]); 1426 builder.StoreAccumulatorInRegister(r0) 1427 .LoadLiteral(func) 1428 .CompareOperation(Token::Value::INSTANCEOF, r0) 1429 .Return(); 1430 1431 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 1432 InterpreterTester tester(handles.main_isolate(), bytecode_array); 1433 auto callable = tester.GetCallable<>(); 1434 Handle<Object> return_value = callable().ToHandleChecked(); 1435 CHECK(return_value->IsBoolean()); 1436 CHECK_EQ(return_value->BooleanValue(), expected_value); 1437 } 1438 } 1439 1440 1441 TEST(InterpreterTestIn) { 1442 HandleAndZoneScope handles; 1443 i::Factory* factory = handles.main_isolate()->factory(); 1444 // Allocate an array 1445 Handle<i::JSArray> array = 1446 factory->NewJSArray(0, i::ElementsKind::FAST_SMI_ELEMENTS); 1447 // Check for these properties on the array object 1448 const char* properties[] = {"length", "fuzzle", "x", "0"}; 1449 for (size_t i = 0; i < arraysize(properties); i++) { 1450 bool expected_value = (i == 0); 1451 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0, 1452 0, 1); 1453 1454 Register r0(0); 1455 builder.LoadLiteral(factory->NewStringFromAsciiChecked(properties[i])) 1456 .StoreAccumulatorInRegister(r0) 1457 .LoadLiteral(Handle<Object>::cast(array)) 1458 .CompareOperation(Token::Value::IN, r0) 1459 .Return(); 1460 1461 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 1462 InterpreterTester tester(handles.main_isolate(), bytecode_array); 1463 auto callable = tester.GetCallable<>(); 1464 Handle<Object> return_value = callable().ToHandleChecked(); 1465 CHECK(return_value->IsBoolean()); 1466 CHECK_EQ(return_value->BooleanValue(), expected_value); 1467 } 1468 } 1469 1470 1471 TEST(InterpreterUnaryNot) { 1472 HandleAndZoneScope handles; 1473 for (size_t i = 1; i < 10; i++) { 1474 bool expected_value = ((i & 1) == 1); 1475 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0, 1476 0, 0); 1477 1478 Register r0(0); 1479 builder.LoadFalse(); 1480 for (size_t j = 0; j < i; j++) { 1481 builder.LogicalNot(); 1482 } 1483 builder.Return(); 1484 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 1485 InterpreterTester tester(handles.main_isolate(), bytecode_array); 1486 auto callable = tester.GetCallable<>(); 1487 Handle<Object> return_value = callable().ToHandleChecked(); 1488 CHECK(return_value->IsBoolean()); 1489 CHECK_EQ(return_value->BooleanValue(), expected_value); 1490 } 1491 } 1492 1493 1494 static void LoadAny(BytecodeArrayBuilder* builder, 1495 v8::internal::Factory* factory, Handle<Object> obj) { 1496 if (obj->IsOddball()) { 1497 if (obj->SameValue(*factory->true_value())) { 1498 builder->LoadTrue(); 1499 } else if (obj->SameValue(*factory->false_value())) { 1500 builder->LoadFalse(); 1501 } else if (obj->SameValue(*factory->the_hole_value())) { 1502 builder->LoadTheHole(); 1503 } else if (obj->SameValue(*factory->null_value())) { 1504 builder->LoadNull(); 1505 } else if (obj->SameValue(*factory->undefined_value())) { 1506 builder->LoadUndefined(); 1507 } else { 1508 UNREACHABLE(); 1509 } 1510 } else if (obj->IsSmi()) { 1511 builder->LoadLiteral(*Handle<Smi>::cast(obj)); 1512 } else { 1513 builder->LoadLiteral(obj); 1514 } 1515 } 1516 1517 1518 TEST(InterpreterUnaryNotNonBoolean) { 1519 HandleAndZoneScope handles; 1520 i::Factory* factory = handles.main_isolate()->factory(); 1521 1522 std::pair<Handle<Object>, bool> object_type_tuples[] = { 1523 std::make_pair(factory->undefined_value(), true), 1524 std::make_pair(factory->null_value(), true), 1525 std::make_pair(factory->false_value(), true), 1526 std::make_pair(factory->true_value(), false), 1527 std::make_pair(factory->NewNumber(9.1), false), 1528 std::make_pair(factory->NewNumberFromInt(0), true), 1529 std::make_pair( 1530 Handle<Object>::cast(factory->NewStringFromStaticChars("hello")), 1531 false), 1532 std::make_pair( 1533 Handle<Object>::cast(factory->NewStringFromStaticChars("")), true), 1534 }; 1535 1536 for (size_t i = 0; i < arraysize(object_type_tuples); i++) { 1537 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0, 1538 0, 0); 1539 1540 Register r0(0); 1541 LoadAny(&builder, factory, object_type_tuples[i].first); 1542 builder.LogicalNot(); 1543 builder.Return(); 1544 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 1545 InterpreterTester tester(handles.main_isolate(), bytecode_array); 1546 auto callable = tester.GetCallable<>(); 1547 Handle<Object> return_value = callable().ToHandleChecked(); 1548 CHECK(return_value->IsBoolean()); 1549 CHECK_EQ(return_value->BooleanValue(), object_type_tuples[i].second); 1550 } 1551 } 1552 1553 1554 TEST(InterpreterTypeof) { 1555 HandleAndZoneScope handles; 1556 1557 std::pair<const char*, const char*> typeof_vals[] = { 1558 std::make_pair("return typeof undefined;", "undefined"), 1559 std::make_pair("return typeof null;", "object"), 1560 std::make_pair("return typeof true;", "boolean"), 1561 std::make_pair("return typeof false;", "boolean"), 1562 std::make_pair("return typeof 9.1;", "number"), 1563 std::make_pair("return typeof 7771;", "number"), 1564 std::make_pair("return typeof 'hello';", "string"), 1565 std::make_pair("return typeof global_unallocated;", "undefined"), 1566 }; 1567 1568 for (size_t i = 0; i < arraysize(typeof_vals); i++) { 1569 std::string source(InterpreterTester::SourceForBody(typeof_vals[i].first)); 1570 InterpreterTester tester(handles.main_isolate(), source.c_str()); 1571 1572 auto callable = tester.GetCallable<>(); 1573 Handle<v8::internal::String> return_value = 1574 Handle<v8::internal::String>::cast(callable().ToHandleChecked()); 1575 auto actual = return_value->ToCString(); 1576 CHECK_EQ(strcmp(&actual[0], typeof_vals[i].second), 0); 1577 } 1578 } 1579 1580 1581 TEST(InterpreterCallRuntime) { 1582 HandleAndZoneScope handles; 1583 1584 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 1585 0, 2); 1586 1587 builder.LoadLiteral(Smi::FromInt(15)) 1588 .StoreAccumulatorInRegister(Register(0)) 1589 .LoadLiteral(Smi::FromInt(40)) 1590 .StoreAccumulatorInRegister(Register(1)) 1591 .CallRuntime(Runtime::kAdd, Register(0), 2) 1592 .Return(); 1593 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 1594 1595 InterpreterTester tester(handles.main_isolate(), bytecode_array); 1596 auto callable = tester.GetCallable<>(); 1597 1598 Handle<Object> return_val = callable().ToHandleChecked(); 1599 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(55)); 1600 } 1601 1602 TEST(InterpreterInvokeIntrinsic) { 1603 HandleAndZoneScope handles; 1604 1605 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, 1606 0, 2); 1607 1608 builder.LoadLiteral(Smi::FromInt(15)) 1609 .StoreAccumulatorInRegister(Register(0)) 1610 .CallRuntime(Runtime::kInlineIsArray, Register(0), 1) 1611 .Return(); 1612 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 1613 1614 InterpreterTester tester(handles.main_isolate(), bytecode_array); 1615 auto callable = tester.GetCallable<>(); 1616 1617 Handle<Object> return_val = callable().ToHandleChecked(); 1618 CHECK(return_val->IsBoolean()); 1619 CHECK_EQ(return_val->BooleanValue(), false); 1620 } 1621 1622 TEST(InterpreterFunctionLiteral) { 1623 HandleAndZoneScope handles; 1624 1625 // Test calling a function literal. 1626 std::string source( 1627 "function " + InterpreterTester::function_name() + "(a) {\n" 1628 " return (function(x){ return x + 2; })(a);\n" 1629 "}"); 1630 InterpreterTester tester(handles.main_isolate(), source.c_str()); 1631 auto callable = tester.GetCallable<Handle<Object>>(); 1632 1633 Handle<i::Object> return_val = callable( 1634 Handle<Smi>(Smi::FromInt(3), handles.main_isolate())).ToHandleChecked(); 1635 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(5)); 1636 } 1637 1638 1639 TEST(InterpreterRegExpLiterals) { 1640 HandleAndZoneScope handles; 1641 i::Isolate* isolate = handles.main_isolate(); 1642 i::Factory* factory = isolate->factory(); 1643 1644 std::pair<const char*, Handle<Object>> literals[] = { 1645 std::make_pair("return /abd/.exec('cccabbdd');\n", 1646 factory->null_value()), 1647 std::make_pair("return /ab+d/.exec('cccabbdd')[0];\n", 1648 factory->NewStringFromStaticChars("abbd")), 1649 std::make_pair("return /AbC/i.exec('ssaBC')[0];\n", 1650 factory->NewStringFromStaticChars("aBC")), 1651 std::make_pair("return 'ssaBC'.match(/AbC/i)[0];\n", 1652 factory->NewStringFromStaticChars("aBC")), 1653 std::make_pair("return 'ssaBCtAbC'.match(/(AbC)/gi)[1];\n", 1654 factory->NewStringFromStaticChars("AbC")), 1655 }; 1656 1657 for (size_t i = 0; i < arraysize(literals); i++) { 1658 std::string source(InterpreterTester::SourceForBody(literals[i].first)); 1659 InterpreterTester tester(handles.main_isolate(), source.c_str()); 1660 auto callable = tester.GetCallable<>(); 1661 1662 Handle<i::Object> return_value = callable().ToHandleChecked(); 1663 CHECK(return_value->SameValue(*literals[i].second)); 1664 } 1665 } 1666 1667 1668 TEST(InterpreterArrayLiterals) { 1669 HandleAndZoneScope handles; 1670 i::Isolate* isolate = handles.main_isolate(); 1671 i::Factory* factory = isolate->factory(); 1672 1673 std::pair<const char*, Handle<Object>> literals[] = { 1674 std::make_pair("return [][0];\n", 1675 factory->undefined_value()), 1676 std::make_pair("return [1, 3, 2][1];\n", 1677 handle(Smi::FromInt(3), isolate)), 1678 std::make_pair("return ['a', 'b', 'c'][2];\n", 1679 factory->NewStringFromStaticChars("c")), 1680 std::make_pair("var a = 100; return [a, a + 1, a + 2, a + 3][2];\n", 1681 handle(Smi::FromInt(102), isolate)), 1682 std::make_pair("return [[1, 2, 3], ['a', 'b', 'c']][1][0];\n", 1683 factory->NewStringFromStaticChars("a")), 1684 std::make_pair("var t = 't'; return [[t, t + 'est'], [1 + t]][0][1];\n", 1685 factory->NewStringFromStaticChars("test")) 1686 }; 1687 1688 for (size_t i = 0; i < arraysize(literals); i++) { 1689 std::string source(InterpreterTester::SourceForBody(literals[i].first)); 1690 InterpreterTester tester(handles.main_isolate(), source.c_str()); 1691 auto callable = tester.GetCallable<>(); 1692 1693 Handle<i::Object> return_value = callable().ToHandleChecked(); 1694 CHECK(return_value->SameValue(*literals[i].second)); 1695 } 1696 } 1697 1698 1699 TEST(InterpreterObjectLiterals) { 1700 HandleAndZoneScope handles; 1701 i::Isolate* isolate = handles.main_isolate(); 1702 i::Factory* factory = isolate->factory(); 1703 1704 std::pair<const char*, Handle<Object>> literals[] = { 1705 std::make_pair("return { }.name;", 1706 factory->undefined_value()), 1707 std::make_pair("return { name: 'string', val: 9.2 }.name;", 1708 factory->NewStringFromStaticChars("string")), 1709 std::make_pair("var a = 15; return { name: 'string', val: a }.val;", 1710 handle(Smi::FromInt(15), isolate)), 1711 std::make_pair("var a = 5; return { val: a, val: a + 1 }.val;", 1712 handle(Smi::FromInt(6), isolate)), 1713 std::make_pair("return { func: function() { return 'test' } }.func();", 1714 factory->NewStringFromStaticChars("test")), 1715 std::make_pair("return { func(a) { return a + 'st'; } }.func('te');", 1716 factory->NewStringFromStaticChars("test")), 1717 std::make_pair("return { get a() { return 22; } }.a;", 1718 handle(Smi::FromInt(22), isolate)), 1719 std::make_pair("var a = { get b() { return this.x + 't'; },\n" 1720 " set b(val) { this.x = val + 's' } };\n" 1721 "a.b = 'te';\n" 1722 "return a.b;", 1723 factory->NewStringFromStaticChars("test")), 1724 std::make_pair("var a = 123; return { 1: a }[1];", 1725 handle(Smi::FromInt(123), isolate)), 1726 std::make_pair("return Object.getPrototypeOf({ __proto__: null });", 1727 factory->null_value()), 1728 std::make_pair("var a = 'test'; return { [a]: 1 }.test;", 1729 handle(Smi::FromInt(1), isolate)), 1730 std::make_pair("var a = 'test'; return { b: a, [a]: a + 'ing' }['test']", 1731 factory->NewStringFromStaticChars("testing")), 1732 std::make_pair("var a = 'proto_str';\n" 1733 "var b = { [a]: 1, __proto__: { var : a } };\n" 1734 "return Object.getPrototypeOf(b).var", 1735 factory->NewStringFromStaticChars("proto_str")), 1736 std::make_pair("var n = 'name';\n" 1737 "return { [n]: 'val', get a() { return 987 } }['a'];", 1738 handle(Smi::FromInt(987), isolate)), 1739 }; 1740 1741 for (size_t i = 0; i < arraysize(literals); i++) { 1742 std::string source(InterpreterTester::SourceForBody(literals[i].first)); 1743 InterpreterTester tester(handles.main_isolate(), source.c_str()); 1744 auto callable = tester.GetCallable<>(); 1745 1746 Handle<i::Object> return_value = callable().ToHandleChecked(); 1747 CHECK(return_value->SameValue(*literals[i].second)); 1748 } 1749 } 1750 1751 1752 TEST(InterpreterConstruct) { 1753 HandleAndZoneScope handles; 1754 1755 std::string source( 1756 "function counter() { this.count = 0; }\n" 1757 "function " + 1758 InterpreterTester::function_name() + 1759 "() {\n" 1760 " var c = new counter();\n" 1761 " return c.count;\n" 1762 "}"); 1763 InterpreterTester tester(handles.main_isolate(), source.c_str()); 1764 auto callable = tester.GetCallable<>(); 1765 1766 Handle<Object> return_val = callable().ToHandleChecked(); 1767 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(0)); 1768 } 1769 1770 1771 TEST(InterpreterConstructWithArgument) { 1772 HandleAndZoneScope handles; 1773 1774 std::string source( 1775 "function counter(arg0) { this.count = 17; this.x = arg0; }\n" 1776 "function " + 1777 InterpreterTester::function_name() + 1778 "() {\n" 1779 " var c = new counter(3);\n" 1780 " return c.x;\n" 1781 "}"); 1782 InterpreterTester tester(handles.main_isolate(), source.c_str()); 1783 auto callable = tester.GetCallable<>(); 1784 1785 Handle<Object> return_val = callable().ToHandleChecked(); 1786 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(3)); 1787 } 1788 1789 1790 TEST(InterpreterConstructWithArguments) { 1791 HandleAndZoneScope handles; 1792 1793 std::string source( 1794 "function counter(arg0, arg1) {\n" 1795 " this.count = 7; this.x = arg0; this.y = arg1;\n" 1796 "}\n" 1797 "function " + 1798 InterpreterTester::function_name() + 1799 "() {\n" 1800 " var c = new counter(3, 5);\n" 1801 " return c.count + c.x + c.y;\n" 1802 "}"); 1803 InterpreterTester tester(handles.main_isolate(), source.c_str()); 1804 auto callable = tester.GetCallable<>(); 1805 1806 Handle<Object> return_val = callable().ToHandleChecked(); 1807 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(15)); 1808 } 1809 1810 1811 TEST(InterpreterContextVariables) { 1812 HandleAndZoneScope handles; 1813 i::Isolate* isolate = handles.main_isolate(); 1814 1815 std::ostringstream unique_vars; 1816 for (int i = 0; i < 250; i++) { 1817 unique_vars << "var a" << i << " = 0;"; 1818 } 1819 std::pair<std::string, Handle<Object>> context_vars[] = { 1820 std::make_pair("var a; (function() { a = 1; })(); return a;", 1821 handle(Smi::FromInt(1), isolate)), 1822 std::make_pair("var a = 10; (function() { a; })(); return a;", 1823 handle(Smi::FromInt(10), isolate)), 1824 std::make_pair("var a = 20; var b = 30;\n" 1825 "return (function() { return a + b; })();", 1826 handle(Smi::FromInt(50), isolate)), 1827 std::make_pair("'use strict'; let a = 1;\n" 1828 "{ let b = 2; return (function() { return a + b; })(); }", 1829 handle(Smi::FromInt(3), isolate)), 1830 std::make_pair("'use strict'; let a = 10;\n" 1831 "{ let b = 20; var c = function() { [a, b] };\n" 1832 " return a + b; }", 1833 handle(Smi::FromInt(30), isolate)), 1834 std::make_pair("'use strict';" + unique_vars.str() + 1835 "eval(); var b = 100; return b;", 1836 handle(Smi::FromInt(100), isolate)), 1837 }; 1838 1839 for (size_t i = 0; i < arraysize(context_vars); i++) { 1840 std::string source( 1841 InterpreterTester::SourceForBody(context_vars[i].first.c_str())); 1842 InterpreterTester tester(handles.main_isolate(), source.c_str()); 1843 auto callable = tester.GetCallable<>(); 1844 1845 Handle<i::Object> return_value = callable().ToHandleChecked(); 1846 CHECK(return_value->SameValue(*context_vars[i].second)); 1847 } 1848 } 1849 1850 1851 TEST(InterpreterContextParameters) { 1852 HandleAndZoneScope handles; 1853 i::Isolate* isolate = handles.main_isolate(); 1854 1855 std::pair<const char*, Handle<Object>> context_params[] = { 1856 std::make_pair("return (function() { return arg1; })();", 1857 handle(Smi::FromInt(1), isolate)), 1858 std::make_pair("(function() { arg1 = 4; })(); return arg1;", 1859 handle(Smi::FromInt(4), isolate)), 1860 std::make_pair("(function() { arg3 = arg2 - arg1; })(); return arg3;", 1861 handle(Smi::FromInt(1), isolate)), 1862 }; 1863 1864 for (size_t i = 0; i < arraysize(context_params); i++) { 1865 std::string source = "function " + InterpreterTester::function_name() + 1866 "(arg1, arg2, arg3) {" + context_params[i].first + "}"; 1867 InterpreterTester tester(handles.main_isolate(), source.c_str()); 1868 auto callable = 1869 tester.GetCallable<Handle<Object>, Handle<Object>, Handle<Object>>(); 1870 1871 Handle<Object> a1 = handle(Smi::FromInt(1), isolate); 1872 Handle<Object> a2 = handle(Smi::FromInt(2), isolate); 1873 Handle<Object> a3 = handle(Smi::FromInt(3), isolate); 1874 Handle<i::Object> return_value = callable(a1, a2, a3).ToHandleChecked(); 1875 CHECK(return_value->SameValue(*context_params[i].second)); 1876 } 1877 } 1878 1879 1880 TEST(InterpreterOuterContextVariables) { 1881 HandleAndZoneScope handles; 1882 i::Isolate* isolate = handles.main_isolate(); 1883 1884 std::pair<const char*, Handle<Object>> context_vars[] = { 1885 std::make_pair("return outerVar * innerArg;", 1886 handle(Smi::FromInt(200), isolate)), 1887 std::make_pair("outerVar = innerArg; return outerVar", 1888 handle(Smi::FromInt(20), isolate)), 1889 }; 1890 1891 std::string header( 1892 "function Outer() {" 1893 " var outerVar = 10;" 1894 " function Inner(innerArg) {" 1895 " this.innerFunc = function() { "); 1896 std::string footer( 1897 " }}" 1898 " this.getInnerFunc = function() { return new Inner(20).innerFunc; }" 1899 "}" 1900 "var f = new Outer().getInnerFunc();"); 1901 1902 for (size_t i = 0; i < arraysize(context_vars); i++) { 1903 std::string source = header + context_vars[i].first + footer; 1904 InterpreterTester tester(handles.main_isolate(), source.c_str(), "*"); 1905 auto callable = tester.GetCallable<>(); 1906 1907 Handle<i::Object> return_value = callable().ToHandleChecked(); 1908 CHECK(return_value->SameValue(*context_vars[i].second)); 1909 } 1910 } 1911 1912 1913 TEST(InterpreterComma) { 1914 HandleAndZoneScope handles; 1915 i::Isolate* isolate = handles.main_isolate(); 1916 i::Factory* factory = isolate->factory(); 1917 1918 std::pair<const char*, Handle<Object>> literals[] = { 1919 std::make_pair("var a; return 0, a;\n", factory->undefined_value()), 1920 std::make_pair("return 'a', 2.2, 3;\n", 1921 handle(Smi::FromInt(3), isolate)), 1922 std::make_pair("return 'a', 'b', 'c';\n", 1923 factory->NewStringFromStaticChars("c")), 1924 std::make_pair("return 3.2, 2.3, 4.5;\n", factory->NewNumber(4.5)), 1925 std::make_pair("var a = 10; return b = a, b = b+1;\n", 1926 handle(Smi::FromInt(11), isolate)), 1927 std::make_pair("var a = 10; return b = a, b = b+1, b + 10;\n", 1928 handle(Smi::FromInt(21), isolate))}; 1929 1930 for (size_t i = 0; i < arraysize(literals); i++) { 1931 std::string source(InterpreterTester::SourceForBody(literals[i].first)); 1932 InterpreterTester tester(handles.main_isolate(), source.c_str()); 1933 auto callable = tester.GetCallable<>(); 1934 1935 Handle<i::Object> return_value = callable().ToHandleChecked(); 1936 CHECK(return_value->SameValue(*literals[i].second)); 1937 } 1938 } 1939 1940 1941 TEST(InterpreterLogicalOr) { 1942 HandleAndZoneScope handles; 1943 i::Isolate* isolate = handles.main_isolate(); 1944 i::Factory* factory = isolate->factory(); 1945 1946 std::pair<const char*, Handle<Object>> literals[] = { 1947 std::make_pair("var a, b; return a || b;\n", factory->undefined_value()), 1948 std::make_pair("var a, b = 10; return a || b;\n", 1949 handle(Smi::FromInt(10), isolate)), 1950 std::make_pair("var a = '0', b = 10; return a || b;\n", 1951 factory->NewStringFromStaticChars("0")), 1952 std::make_pair("return 0 || 3.2;\n", factory->NewNumber(3.2)), 1953 std::make_pair("return 'a' || 0;\n", 1954 factory->NewStringFromStaticChars("a")), 1955 std::make_pair("var a = '0', b = 10; return (a == 0) || b;\n", 1956 factory->true_value())}; 1957 1958 for (size_t i = 0; i < arraysize(literals); i++) { 1959 std::string source(InterpreterTester::SourceForBody(literals[i].first)); 1960 InterpreterTester tester(handles.main_isolate(), source.c_str()); 1961 auto callable = tester.GetCallable<>(); 1962 1963 Handle<i::Object> return_value = callable().ToHandleChecked(); 1964 CHECK(return_value->SameValue(*literals[i].second)); 1965 } 1966 } 1967 1968 1969 TEST(InterpreterLogicalAnd) { 1970 HandleAndZoneScope handles; 1971 i::Isolate* isolate = handles.main_isolate(); 1972 i::Factory* factory = isolate->factory(); 1973 1974 std::pair<const char*, Handle<Object>> literals[] = { 1975 std::make_pair("var a, b = 10; return a && b;\n", 1976 factory->undefined_value()), 1977 std::make_pair("var a = 0, b = 10; return a && b / a;\n", 1978 handle(Smi::FromInt(0), isolate)), 1979 std::make_pair("var a = '0', b = 10; return a && b;\n", 1980 handle(Smi::FromInt(10), isolate)), 1981 std::make_pair("return 0.0 && 3.2;\n", handle(Smi::FromInt(0), isolate)), 1982 std::make_pair("return 'a' && 'b';\n", 1983 factory->NewStringFromStaticChars("b")), 1984 std::make_pair("return 'a' && 0 || 'b', 'c';\n", 1985 factory->NewStringFromStaticChars("c")), 1986 std::make_pair("var x = 1, y = 3; return x && 0 + 1 || y;\n", 1987 handle(Smi::FromInt(1), isolate)), 1988 std::make_pair("var x = 1, y = 3; return (x == 1) && (3 == 3) || y;\n", 1989 factory->true_value())}; 1990 1991 for (size_t i = 0; i < arraysize(literals); i++) { 1992 std::string source(InterpreterTester::SourceForBody(literals[i].first)); 1993 InterpreterTester tester(handles.main_isolate(), source.c_str()); 1994 auto callable = tester.GetCallable<>(); 1995 1996 Handle<i::Object> return_value = callable().ToHandleChecked(); 1997 CHECK(return_value->SameValue(*literals[i].second)); 1998 } 1999 } 2000 2001 2002 TEST(InterpreterTryCatch) { 2003 HandleAndZoneScope handles; 2004 i::Isolate* isolate = handles.main_isolate(); 2005 2006 std::pair<const char*, Handle<Object>> catches[] = { 2007 std::make_pair("var a = 1; try { a = 2 } catch(e) { a = 3 }; return a;", 2008 handle(Smi::FromInt(2), isolate)), 2009 std::make_pair("var a; try { undef.x } catch(e) { a = 2 }; return a;", 2010 handle(Smi::FromInt(2), isolate)), 2011 std::make_pair("var a; try { throw 1 } catch(e) { a = e + 2 }; return a;", 2012 handle(Smi::FromInt(3), isolate)), 2013 std::make_pair("var a; try { throw 1 } catch(e) { a = e + 2 };" 2014 " try { throw a } catch(e) { a = e + 3 }; return a;", 2015 handle(Smi::FromInt(6), isolate)), 2016 }; 2017 2018 for (size_t i = 0; i < arraysize(catches); i++) { 2019 std::string source(InterpreterTester::SourceForBody(catches[i].first)); 2020 InterpreterTester tester(handles.main_isolate(), source.c_str()); 2021 auto callable = tester.GetCallable<>(); 2022 2023 Handle<i::Object> return_value = callable().ToHandleChecked(); 2024 CHECK(return_value->SameValue(*catches[i].second)); 2025 } 2026 } 2027 2028 2029 TEST(InterpreterTryFinally) { 2030 HandleAndZoneScope handles; 2031 i::Isolate* isolate = handles.main_isolate(); 2032 i::Factory* factory = isolate->factory(); 2033 2034 std::pair<const char*, Handle<Object>> finallies[] = { 2035 std::make_pair( 2036 "var a = 1; try { a = a + 1; } finally { a = a + 2; }; return a;", 2037 factory->NewStringFromStaticChars("R4")), 2038 std::make_pair( 2039 "var a = 1; try { a = 2; return 23; } finally { a = 3 }; return a;", 2040 factory->NewStringFromStaticChars("R23")), 2041 std::make_pair( 2042 "var a = 1; try { a = 2; throw 23; } finally { a = 3 }; return a;", 2043 factory->NewStringFromStaticChars("E23")), 2044 std::make_pair( 2045 "var a = 1; try { a = 2; throw 23; } finally { return a; };", 2046 factory->NewStringFromStaticChars("R2")), 2047 std::make_pair( 2048 "var a = 1; try { a = 2; throw 23; } finally { throw 42; };", 2049 factory->NewStringFromStaticChars("E42")), 2050 std::make_pair("var a = 1; for (var i = 10; i < 20; i += 5) {" 2051 " try { a = 2; break; } finally { a = 3; }" 2052 "} return a + i;", 2053 factory->NewStringFromStaticChars("R13")), 2054 std::make_pair("var a = 1; for (var i = 10; i < 20; i += 5) {" 2055 " try { a = 2; continue; } finally { a = 3; }" 2056 "} return a + i;", 2057 factory->NewStringFromStaticChars("R23")), 2058 std::make_pair("var a = 1; try { a = 2;" 2059 " try { a = 3; throw 23; } finally { a = 4; }" 2060 "} catch(e) { a = a + e; } return a;", 2061 factory->NewStringFromStaticChars("R27")), 2062 std::make_pair("var func_name;" 2063 "function tcf2(a) {" 2064 " try { throw new Error('boom');} " 2065 " catch(e) {return 153; } " 2066 " finally {func_name = tcf2.name;}" 2067 "}" 2068 "tcf2();" 2069 "return func_name;", 2070 factory->NewStringFromStaticChars("Rtcf2")), 2071 }; 2072 2073 const char* try_wrapper = 2074 "(function() { try { return 'R' + f() } catch(e) { return 'E' + e }})()"; 2075 2076 for (size_t i = 0; i < arraysize(finallies); i++) { 2077 std::string source(InterpreterTester::SourceForBody(finallies[i].first)); 2078 InterpreterTester tester(handles.main_isolate(), source.c_str()); 2079 tester.GetCallable<>(); 2080 Handle<Object> wrapped = v8::Utils::OpenHandle(*CompileRun(try_wrapper)); 2081 CHECK(wrapped->SameValue(*finallies[i].second)); 2082 } 2083 } 2084 2085 2086 TEST(InterpreterThrow) { 2087 HandleAndZoneScope handles; 2088 i::Isolate* isolate = handles.main_isolate(); 2089 i::Factory* factory = isolate->factory(); 2090 2091 std::pair<const char*, Handle<Object>> throws[] = { 2092 std::make_pair("throw undefined;\n", 2093 factory->undefined_value()), 2094 std::make_pair("throw 1;\n", 2095 handle(Smi::FromInt(1), isolate)), 2096 std::make_pair("throw 'Error';\n", 2097 factory->NewStringFromStaticChars("Error")), 2098 std::make_pair("var a = true; if (a) { throw 'Error'; }\n", 2099 factory->NewStringFromStaticChars("Error")), 2100 std::make_pair("var a = false; if (a) { throw 'Error'; }\n", 2101 factory->undefined_value()), 2102 std::make_pair("throw 'Error1'; throw 'Error2'\n", 2103 factory->NewStringFromStaticChars("Error1")), 2104 }; 2105 2106 const char* try_wrapper = 2107 "(function() { try { f(); } catch(e) { return e; }})()"; 2108 2109 for (size_t i = 0; i < arraysize(throws); i++) { 2110 std::string source(InterpreterTester::SourceForBody(throws[i].first)); 2111 InterpreterTester tester(handles.main_isolate(), source.c_str()); 2112 tester.GetCallable<>(); 2113 Handle<Object> thrown_obj = v8::Utils::OpenHandle(*CompileRun(try_wrapper)); 2114 CHECK(thrown_obj->SameValue(*throws[i].second)); 2115 } 2116 } 2117 2118 2119 TEST(InterpreterCountOperators) { 2120 HandleAndZoneScope handles; 2121 i::Isolate* isolate = handles.main_isolate(); 2122 i::Factory* factory = isolate->factory(); 2123 2124 std::pair<const char*, Handle<Object>> count_ops[] = { 2125 std::make_pair("var a = 1; return ++a;", 2126 handle(Smi::FromInt(2), isolate)), 2127 std::make_pair("var a = 1; return a++;", 2128 handle(Smi::FromInt(1), isolate)), 2129 std::make_pair("var a = 5; return --a;", 2130 handle(Smi::FromInt(4), isolate)), 2131 std::make_pair("var a = 5; return a--;", 2132 handle(Smi::FromInt(5), isolate)), 2133 std::make_pair("var a = 5.2; return --a;", 2134 factory->NewHeapNumber(4.2)), 2135 std::make_pair("var a = 'string'; return ++a;", 2136 factory->nan_value()), 2137 std::make_pair("var a = 'string'; return a--;", 2138 factory->nan_value()), 2139 std::make_pair("var a = true; return ++a;", 2140 handle(Smi::FromInt(2), isolate)), 2141 std::make_pair("var a = false; return a--;", 2142 handle(Smi::FromInt(0), isolate)), 2143 std::make_pair("var a = { val: 11 }; return ++a.val;", 2144 handle(Smi::FromInt(12), isolate)), 2145 std::make_pair("var a = { val: 11 }; return a.val--;", 2146 handle(Smi::FromInt(11), isolate)), 2147 std::make_pair("var a = { val: 11 }; return ++a.val;", 2148 handle(Smi::FromInt(12), isolate)), 2149 std::make_pair("var name = 'val'; var a = { val: 22 }; return --a[name];", 2150 handle(Smi::FromInt(21), isolate)), 2151 std::make_pair("var name = 'val'; var a = { val: 22 }; return a[name]++;", 2152 handle(Smi::FromInt(22), isolate)), 2153 std::make_pair("var a = 1; (function() { a = 2 })(); return ++a;", 2154 handle(Smi::FromInt(3), isolate)), 2155 std::make_pair("var a = 1; (function() { a = 2 })(); return a--;", 2156 handle(Smi::FromInt(2), isolate)), 2157 std::make_pair("var i = 5; while(i--) {}; return i;", 2158 handle(Smi::FromInt(-1), isolate)), 2159 std::make_pair("var i = 1; if(i--) { return 1; } else { return 2; };", 2160 handle(Smi::FromInt(1), isolate)), 2161 std::make_pair("var i = -2; do {} while(i++) {}; return i;", 2162 handle(Smi::FromInt(1), isolate)), 2163 std::make_pair("var i = -1; for(; i++; ) {}; return i", 2164 handle(Smi::FromInt(1), isolate)), 2165 std::make_pair("var i = 20; switch(i++) {\n" 2166 " case 20: return 1;\n" 2167 " default: return 2;\n" 2168 "}", 2169 handle(Smi::FromInt(1), isolate)), 2170 }; 2171 2172 for (size_t i = 0; i < arraysize(count_ops); i++) { 2173 std::string source(InterpreterTester::SourceForBody(count_ops[i].first)); 2174 InterpreterTester tester(handles.main_isolate(), source.c_str()); 2175 auto callable = tester.GetCallable<>(); 2176 2177 Handle<i::Object> return_value = callable().ToHandleChecked(); 2178 CHECK(return_value->SameValue(*count_ops[i].second)); 2179 } 2180 } 2181 2182 2183 TEST(InterpreterGlobalCountOperators) { 2184 HandleAndZoneScope handles; 2185 i::Isolate* isolate = handles.main_isolate(); 2186 2187 std::pair<const char*, Handle<Object>> count_ops[] = { 2188 std::make_pair("var global = 100;function f(){ return ++global; }", 2189 handle(Smi::FromInt(101), isolate)), 2190 std::make_pair("var global = 100; function f(){ return --global; }", 2191 handle(Smi::FromInt(99), isolate)), 2192 std::make_pair("var global = 100; function f(){ return global++; }", 2193 handle(Smi::FromInt(100), isolate)), 2194 std::make_pair("unallocated = 200; function f(){ return ++unallocated; }", 2195 handle(Smi::FromInt(201), isolate)), 2196 std::make_pair("unallocated = 200; function f(){ return --unallocated; }", 2197 handle(Smi::FromInt(199), isolate)), 2198 std::make_pair("unallocated = 200; function f(){ return unallocated++; }", 2199 handle(Smi::FromInt(200), isolate)), 2200 }; 2201 2202 for (size_t i = 0; i < arraysize(count_ops); i++) { 2203 InterpreterTester tester(handles.main_isolate(), count_ops[i].first); 2204 auto callable = tester.GetCallable<>(); 2205 2206 Handle<i::Object> return_value = callable().ToHandleChecked(); 2207 CHECK(return_value->SameValue(*count_ops[i].second)); 2208 } 2209 } 2210 2211 2212 TEST(InterpreterCompoundExpressions) { 2213 HandleAndZoneScope handles; 2214 i::Isolate* isolate = handles.main_isolate(); 2215 i::Factory* factory = isolate->factory(); 2216 2217 std::pair<const char*, Handle<Object>> compound_expr[] = { 2218 std::make_pair("var a = 1; a += 2; return a;", 2219 Handle<Object>(Smi::FromInt(3), isolate)), 2220 std::make_pair("var a = 10; a /= 2; return a;", 2221 Handle<Object>(Smi::FromInt(5), isolate)), 2222 std::make_pair("var a = 'test'; a += 'ing'; return a;", 2223 factory->NewStringFromStaticChars("testing")), 2224 std::make_pair("var a = { val: 2 }; a.val *= 2; return a.val;", 2225 Handle<Object>(Smi::FromInt(4), isolate)), 2226 std::make_pair("var a = 1; (function f() { a = 2; })(); a += 24;" 2227 "return a;", 2228 Handle<Object>(Smi::FromInt(26), isolate)), 2229 }; 2230 2231 for (size_t i = 0; i < arraysize(compound_expr); i++) { 2232 std::string source( 2233 InterpreterTester::SourceForBody(compound_expr[i].first)); 2234 InterpreterTester tester(handles.main_isolate(), source.c_str()); 2235 auto callable = tester.GetCallable<>(); 2236 2237 Handle<i::Object> return_value = callable().ToHandleChecked(); 2238 CHECK(return_value->SameValue(*compound_expr[i].second)); 2239 } 2240 } 2241 2242 2243 TEST(InterpreterGlobalCompoundExpressions) { 2244 HandleAndZoneScope handles; 2245 i::Isolate* isolate = handles.main_isolate(); 2246 2247 std::pair<const char*, Handle<Object>> compound_expr[2] = { 2248 std::make_pair("var global = 100;" 2249 "function f() { global += 20; return global; }", 2250 Handle<Object>(Smi::FromInt(120), isolate)), 2251 std::make_pair("unallocated = 100;" 2252 "function f() { unallocated -= 20; return unallocated; }", 2253 Handle<Object>(Smi::FromInt(80), isolate)), 2254 }; 2255 2256 for (size_t i = 0; i < arraysize(compound_expr); i++) { 2257 InterpreterTester tester(handles.main_isolate(), compound_expr[i].first); 2258 auto callable = tester.GetCallable<>(); 2259 2260 Handle<i::Object> return_value = callable().ToHandleChecked(); 2261 CHECK(return_value->SameValue(*compound_expr[i].second)); 2262 } 2263 } 2264 2265 2266 TEST(InterpreterCreateArguments) { 2267 HandleAndZoneScope handles; 2268 i::Isolate* isolate = handles.main_isolate(); 2269 i::Factory* factory = isolate->factory(); 2270 2271 std::pair<const char*, int> create_args[] = { 2272 std::make_pair("function f() { return arguments[0]; }", 0), 2273 std::make_pair("function f(a) { return arguments[0]; }", 0), 2274 std::make_pair("function f() { return arguments[2]; }", 2), 2275 std::make_pair("function f(a) { return arguments[2]; }", 2), 2276 std::make_pair("function f(a, b, c, d) { return arguments[2]; }", 2), 2277 std::make_pair("function f(a) {" 2278 "'use strict'; return arguments[0]; }", 2279 0), 2280 std::make_pair("function f(a, b, c, d) {" 2281 "'use strict'; return arguments[2]; }", 2282 2), 2283 // Check arguments are mapped in sloppy mode and unmapped in strict. 2284 std::make_pair("function f(a, b, c, d) {" 2285 " c = b; return arguments[2]; }", 2286 1), 2287 std::make_pair("function f(a, b, c, d) {" 2288 " 'use strict'; c = b; return arguments[2]; }", 2289 2), 2290 // Check arguments for duplicate parameters in sloppy mode. 2291 std::make_pair("function f(a, a, b) { return arguments[1]; }", 1), 2292 // check rest parameters 2293 std::make_pair("function f(...restArray) { return restArray[0]; }", 0), 2294 std::make_pair("function f(a, ...restArray) { return restArray[0]; }", 1), 2295 std::make_pair("function f(a, ...restArray) { return arguments[0]; }", 0), 2296 std::make_pair("function f(a, ...restArray) { return arguments[1]; }", 1), 2297 std::make_pair("function f(a, ...restArray) { return restArray[1]; }", 2), 2298 std::make_pair("function f(a, ...arguments) { return arguments[0]; }", 1), 2299 std::make_pair("function f(a, b, ...restArray) { return restArray[0]; }", 2300 2), 2301 }; 2302 2303 // Test passing no arguments. 2304 for (size_t i = 0; i < arraysize(create_args); i++) { 2305 InterpreterTester tester(handles.main_isolate(), create_args[i].first); 2306 auto callable = tester.GetCallable<>(); 2307 Handle<Object> return_val = callable().ToHandleChecked(); 2308 CHECK(return_val.is_identical_to(factory->undefined_value())); 2309 } 2310 2311 // Test passing one argument. 2312 for (size_t i = 0; i < arraysize(create_args); i++) { 2313 InterpreterTester tester(handles.main_isolate(), create_args[i].first); 2314 auto callable = tester.GetCallable<Handle<Object>>(); 2315 Handle<Object> return_val = 2316 callable(handle(Smi::FromInt(40), isolate)).ToHandleChecked(); 2317 if (create_args[i].second == 0) { 2318 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(40)); 2319 } else { 2320 CHECK(return_val.is_identical_to(factory->undefined_value())); 2321 } 2322 } 2323 2324 // Test passing three argument. 2325 for (size_t i = 0; i < arraysize(create_args); i++) { 2326 Handle<Object> args[3] = { 2327 handle(Smi::FromInt(40), isolate), 2328 handle(Smi::FromInt(60), isolate), 2329 handle(Smi::FromInt(80), isolate), 2330 }; 2331 2332 InterpreterTester tester(handles.main_isolate(), create_args[i].first); 2333 auto callable = 2334 tester.GetCallable<Handle<Object>, Handle<Object>, Handle<Object>>(); 2335 Handle<Object> return_val = 2336 callable(args[0], args[1], args[2]).ToHandleChecked(); 2337 CHECK(return_val->SameValue(*args[create_args[i].second])); 2338 } 2339 } 2340 2341 2342 TEST(InterpreterConditional) { 2343 HandleAndZoneScope handles; 2344 i::Isolate* isolate = handles.main_isolate(); 2345 2346 std::pair<const char*, Handle<Object>> conditional[] = { 2347 std::make_pair("return true ? 2 : 3;", 2348 handle(Smi::FromInt(2), isolate)), 2349 std::make_pair("return false ? 2 : 3;", 2350 handle(Smi::FromInt(3), isolate)), 2351 std::make_pair("var a = 1; return a ? 20 : 30;", 2352 handle(Smi::FromInt(20), isolate)), 2353 std::make_pair("var a = 1; return a ? 20 : 30;", 2354 handle(Smi::FromInt(20), isolate)), 2355 std::make_pair("var a = 'string'; return a ? 20 : 30;", 2356 handle(Smi::FromInt(20), isolate)), 2357 std::make_pair("var a = undefined; return a ? 20 : 30;", 2358 handle(Smi::FromInt(30), isolate)), 2359 std::make_pair("return 1 ? 2 ? 3 : 4 : 5;", 2360 handle(Smi::FromInt(3), isolate)), 2361 std::make_pair("return 0 ? 2 ? 3 : 4 : 5;", 2362 handle(Smi::FromInt(5), isolate)), 2363 }; 2364 2365 for (size_t i = 0; i < arraysize(conditional); i++) { 2366 std::string source(InterpreterTester::SourceForBody(conditional[i].first)); 2367 InterpreterTester tester(handles.main_isolate(), source.c_str()); 2368 auto callable = tester.GetCallable<>(); 2369 2370 Handle<i::Object> return_value = callable().ToHandleChecked(); 2371 CHECK(return_value->SameValue(*conditional[i].second)); 2372 } 2373 } 2374 2375 2376 TEST(InterpreterDelete) { 2377 HandleAndZoneScope handles; 2378 i::Isolate* isolate = handles.main_isolate(); 2379 i::Factory* factory = isolate->factory(); 2380 2381 // Tests for delete for local variables that work both in strict 2382 // and sloppy modes 2383 std::pair<const char*, Handle<Object>> test_delete[] = { 2384 std::make_pair( 2385 "var a = { x:10, y:'abc', z:30.2}; delete a.x; return a.x;\n", 2386 factory->undefined_value()), 2387 std::make_pair( 2388 "var b = { x:10, y:'abc', z:30.2}; delete b.x; return b.y;\n", 2389 factory->NewStringFromStaticChars("abc")), 2390 std::make_pair("var c = { x:10, y:'abc', z:30.2}; var d = c; delete d.x; " 2391 "return c.x;\n", 2392 factory->undefined_value()), 2393 std::make_pair("var e = { x:10, y:'abc', z:30.2}; var g = e; delete g.x; " 2394 "return e.y;\n", 2395 factory->NewStringFromStaticChars("abc")), 2396 std::make_pair("var a = { x:10, y:'abc', z:30.2};\n" 2397 "var b = a;" 2398 "delete b.x;" 2399 "return b.x;\n", 2400 factory->undefined_value()), 2401 std::make_pair("var a = {1:10};\n" 2402 "(function f1() {return a;});" 2403 "return delete a[1];", 2404 factory->ToBoolean(true)), 2405 std::make_pair("return delete this;", factory->ToBoolean(true)), 2406 std::make_pair("return delete 'test';", factory->ToBoolean(true))}; 2407 2408 // Test delete in sloppy mode 2409 for (size_t i = 0; i < arraysize(test_delete); i++) { 2410 std::string source(InterpreterTester::SourceForBody(test_delete[i].first)); 2411 InterpreterTester tester(handles.main_isolate(), source.c_str()); 2412 auto callable = tester.GetCallable<>(); 2413 2414 Handle<i::Object> return_value = callable().ToHandleChecked(); 2415 CHECK(return_value->SameValue(*test_delete[i].second)); 2416 } 2417 2418 // Test delete in strict mode 2419 for (size_t i = 0; i < arraysize(test_delete); i++) { 2420 std::string strict_test = 2421 "'use strict'; " + std::string(test_delete[i].first); 2422 std::string source(InterpreterTester::SourceForBody(strict_test.c_str())); 2423 InterpreterTester tester(handles.main_isolate(), source.c_str()); 2424 auto callable = tester.GetCallable<>(); 2425 2426 Handle<i::Object> return_value = callable().ToHandleChecked(); 2427 CHECK(return_value->SameValue(*test_delete[i].second)); 2428 } 2429 } 2430 2431 2432 TEST(InterpreterDeleteSloppyUnqualifiedIdentifier) { 2433 HandleAndZoneScope handles; 2434 i::Isolate* isolate = handles.main_isolate(); 2435 i::Factory* factory = isolate->factory(); 2436 2437 // These tests generate a syntax error for strict mode. We don't 2438 // test for it here. 2439 std::pair<const char*, Handle<Object>> test_delete[] = { 2440 std::make_pair("var sloppy_a = { x:10, y:'abc'};\n" 2441 "var sloppy_b = delete sloppy_a;\n" 2442 "if (delete sloppy_a) {\n" 2443 " return undefined;\n" 2444 "} else {\n" 2445 " return sloppy_a.x;\n" 2446 "}\n", 2447 Handle<Object>(Smi::FromInt(10), isolate)), 2448 // TODO(mythria) When try-catch is implemented change the tests to check 2449 // if delete actually deletes 2450 std::make_pair("sloppy_a = { x:10, y:'abc'};\n" 2451 "var sloppy_b = delete sloppy_a;\n" 2452 // "try{return a.x;} catch(e) {return b;}\n" 2453 "return sloppy_b;", 2454 factory->ToBoolean(true)), 2455 std::make_pair("sloppy_a = { x:10, y:'abc'};\n" 2456 "var sloppy_b = delete sloppy_c;\n" 2457 "return sloppy_b;", 2458 factory->ToBoolean(true))}; 2459 2460 for (size_t i = 0; i < arraysize(test_delete); i++) { 2461 std::string source(InterpreterTester::SourceForBody(test_delete[i].first)); 2462 InterpreterTester tester(handles.main_isolate(), source.c_str()); 2463 auto callable = tester.GetCallable<>(); 2464 2465 Handle<i::Object> return_value = callable().ToHandleChecked(); 2466 CHECK(return_value->SameValue(*test_delete[i].second)); 2467 } 2468 } 2469 2470 2471 TEST(InterpreterGlobalDelete) { 2472 HandleAndZoneScope handles; 2473 i::Isolate* isolate = handles.main_isolate(); 2474 i::Factory* factory = isolate->factory(); 2475 2476 std::pair<const char*, Handle<Object>> test_global_delete[] = { 2477 std::make_pair("var a = { x:10, y:'abc', z:30.2 };\n" 2478 "function f() {\n" 2479 " delete a.x;\n" 2480 " return a.x;\n" 2481 "}\n" 2482 "f();\n", 2483 factory->undefined_value()), 2484 std::make_pair("var b = {1:10, 2:'abc', 3:30.2 };\n" 2485 "function f() {\n" 2486 " delete b[2];\n" 2487 " return b[1];\n" 2488 " }\n" 2489 "f();\n", 2490 Handle<Object>(Smi::FromInt(10), isolate)), 2491 std::make_pair("var c = { x:10, y:'abc', z:30.2 };\n" 2492 "function f() {\n" 2493 " var d = c;\n" 2494 " delete d.y;\n" 2495 " return d.x;\n" 2496 "}\n" 2497 "f();\n", 2498 Handle<Object>(Smi::FromInt(10), isolate)), 2499 std::make_pair("e = { x:10, y:'abc' };\n" 2500 "function f() {\n" 2501 " return delete e;\n" 2502 "}\n" 2503 "f();\n", 2504 factory->ToBoolean(true)), 2505 std::make_pair("var g = { x:10, y:'abc' };\n" 2506 "function f() {\n" 2507 " return delete g;\n" 2508 "}\n" 2509 "f();\n", 2510 factory->ToBoolean(false)), 2511 std::make_pair("function f() {\n" 2512 " var obj = {h:10, f1() {return delete this;}};\n" 2513 " return obj.f1();\n" 2514 "}\n" 2515 "f();", 2516 factory->ToBoolean(true)), 2517 std::make_pair("function f() {\n" 2518 " var obj = {h:10,\n" 2519 " f1() {\n" 2520 " 'use strict';\n" 2521 " return delete this.h;}};\n" 2522 " return obj.f1();\n" 2523 "}\n" 2524 "f();", 2525 factory->ToBoolean(true))}; 2526 2527 for (size_t i = 0; i < arraysize(test_global_delete); i++) { 2528 InterpreterTester tester(handles.main_isolate(), 2529 test_global_delete[i].first); 2530 auto callable = tester.GetCallable<>(); 2531 2532 Handle<i::Object> return_value = callable().ToHandleChecked(); 2533 CHECK(return_value->SameValue(*test_global_delete[i].second)); 2534 } 2535 } 2536 2537 2538 TEST(InterpreterBasicLoops) { 2539 HandleAndZoneScope handles; 2540 i::Isolate* isolate = handles.main_isolate(); 2541 i::Factory* factory = isolate->factory(); 2542 2543 std::pair<const char*, Handle<Object>> loops[] = { 2544 std::make_pair("var a = 10; var b = 1;\n" 2545 "while (a) {\n" 2546 " b = b * 2;\n" 2547 " a = a - 1;\n" 2548 "};\n" 2549 "return b;\n", 2550 factory->NewHeapNumber(1024)), 2551 std::make_pair("var a = 1; var b = 1;\n" 2552 "do {\n" 2553 " b = b * 2;\n" 2554 " --a;\n" 2555 "} while(a);\n" 2556 "return b;\n", 2557 handle(Smi::FromInt(2), isolate)), 2558 std::make_pair("var b = 1;\n" 2559 "for ( var a = 10; a; a--) {\n" 2560 " b *= 2;\n" 2561 "}\n" 2562 "return b;", 2563 factory->NewHeapNumber(1024)), 2564 std::make_pair("var a = 10; var b = 1;\n" 2565 "while (a > 0) {\n" 2566 " b = b * 2;\n" 2567 " a = a - 1;\n" 2568 "};\n" 2569 "return b;\n", 2570 factory->NewHeapNumber(1024)), 2571 std::make_pair("var a = 1; var b = 1;\n" 2572 "do {\n" 2573 " b = b * 2;\n" 2574 " --a;\n" 2575 "} while(a);\n" 2576 "return b;\n", 2577 handle(Smi::FromInt(2), isolate)), 2578 std::make_pair("var b = 1;\n" 2579 "for ( var a = 10; a > 0; a--) {\n" 2580 " b *= 2;\n" 2581 "}\n" 2582 "return b;", 2583 factory->NewHeapNumber(1024)), 2584 std::make_pair("var a = 10; var b = 1;\n" 2585 "while (false) {\n" 2586 " b = b * 2;\n" 2587 " a = a - 1;\n" 2588 "}\n" 2589 "return b;\n", 2590 Handle<Object>(Smi::FromInt(1), isolate)), 2591 std::make_pair("var a = 10; var b = 1;\n" 2592 "while (true) {\n" 2593 " b = b * 2;\n" 2594 " a = a - 1;\n" 2595 " if (a == 0) break;" 2596 " continue;" 2597 "}\n" 2598 "return b;\n", 2599 factory->NewHeapNumber(1024)), 2600 std::make_pair("var a = 10; var b = 1;\n" 2601 "do {\n" 2602 " b = b * 2;\n" 2603 " a = a - 1;\n" 2604 " if (a == 0) break;" 2605 "} while(true);\n" 2606 "return b;\n", 2607 factory->NewHeapNumber(1024)), 2608 std::make_pair("var a = 10; var b = 1;\n" 2609 "do {\n" 2610 " b = b * 2;\n" 2611 " a = a - 1;\n" 2612 " if (a == 0) break;" 2613 "} while(false);\n" 2614 "return b;\n", 2615 Handle<Object>(Smi::FromInt(2), isolate)), 2616 std::make_pair("var a = 10; var b = 1;\n" 2617 "for ( a = 1, b = 30; false; ) {\n" 2618 " b = b * 2;\n" 2619 "}\n" 2620 "return b;\n", 2621 Handle<Object>(Smi::FromInt(30), isolate))}; 2622 2623 for (size_t i = 0; i < arraysize(loops); i++) { 2624 std::string source(InterpreterTester::SourceForBody(loops[i].first)); 2625 InterpreterTester tester(handles.main_isolate(), source.c_str()); 2626 auto callable = tester.GetCallable<>(); 2627 2628 Handle<i::Object> return_value = callable().ToHandleChecked(); 2629 CHECK(return_value->SameValue(*loops[i].second)); 2630 } 2631 } 2632 2633 2634 TEST(InterpreterForIn) { 2635 std::pair<const char*, int> for_in_samples[] = { 2636 {"var r = -1;\n" 2637 "for (var a in null) { r = a; }\n" 2638 "return r;\n", 2639 -1}, 2640 {"var r = -1;\n" 2641 "for (var a in undefined) { r = a; }\n" 2642 "return r;\n", 2643 -1}, 2644 {"var r = 0;\n" 2645 "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n" 2646 "return r;\n", 2647 0xf}, 2648 {"var r = 0;\n" 2649 "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n" 2650 "var r = 0;\n" 2651 "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n" 2652 "return r;\n", 2653 0xf}, 2654 {"var r = 0;\n" 2655 "for (var a in 'foobar') { r = r + (1 << a); }\n" 2656 "return r;\n", 2657 0x3f}, 2658 {"var r = 0;\n" 2659 "for (var a in {1:0, 10:1, 100:2, 1000:3}) {\n" 2660 " r = r + Number(a);\n" 2661 " }\n" 2662 " return r;\n", 2663 1111}, 2664 {"var r = 0;\n" 2665 "var data = {1:0, 10:1, 100:2, 1000:3};\n" 2666 "for (var a in data) {\n" 2667 " if (a == 1) delete data[1];\n" 2668 " r = r + Number(a);\n" 2669 " }\n" 2670 " return r;\n", 2671 1111}, 2672 {"var r = 0;\n" 2673 "var data = {1:0, 10:1, 100:2, 1000:3};\n" 2674 "for (var a in data) {\n" 2675 " if (a == 10) delete data[100];\n" 2676 " r = r + Number(a);\n" 2677 " }\n" 2678 " return r;\n", 2679 1011}, 2680 {"var r = 0;\n" 2681 "var data = {1:0, 10:1, 100:2, 1000:3};\n" 2682 "for (var a in data) {\n" 2683 " if (a == 10) data[10000] = 4;\n" 2684 " r = r + Number(a);\n" 2685 " }\n" 2686 " return r;\n", 2687 1111}, 2688 {"var r = 0;\n" 2689 "var input = 'foobar';\n" 2690 "for (var a in input) {\n" 2691 " if (input[a] == 'b') break;\n" 2692 " r = r + (1 << a);\n" 2693 "}\n" 2694 "return r;\n", 2695 0x7}, 2696 {"var r = 0;\n" 2697 "var input = 'foobar';\n" 2698 "for (var a in input) {\n" 2699 " if (input[a] == 'b') continue;\n" 2700 " r = r + (1 << a);\n" 2701 "}\n" 2702 "return r;\n", 2703 0x37}, 2704 {"var r = 0;\n" 2705 "var data = {1:0, 10:1, 100:2, 1000:3};\n" 2706 "for (var a in data) {\n" 2707 " if (a == 10) {\n" 2708 " data[10000] = 4;\n" 2709 " }\n" 2710 " r = r + Number(a);\n" 2711 "}\n" 2712 "return r;\n", 2713 1111}, 2714 {"var r = [ 3 ];\n" 2715 "var data = {1:0, 10:1, 100:2, 1000:3};\n" 2716 "for (r[10] in data) {\n" 2717 "}\n" 2718 "return Number(r[10]);\n", 2719 1000}, 2720 {"var r = [ 3 ];\n" 2721 "var data = {1:0, 10:1, 100:2, 1000:3};\n" 2722 "for (r['100'] in data) {\n" 2723 "}\n" 2724 "return Number(r['100']);\n", 2725 1000}, 2726 {"var obj = {}\n" 2727 "var descObj = new Boolean(false);\n" 2728 "var accessed = 0;\n" 2729 "descObj.enumerable = true;\n" 2730 "Object.defineProperties(obj, { prop:descObj });\n" 2731 "for (var p in obj) {\n" 2732 " if (p === 'prop') { accessed = 1; }\n" 2733 "}\n" 2734 "return accessed;", 2735 1}, 2736 {"var appointment = {};\n" 2737 "Object.defineProperty(appointment, 'startTime', {\n" 2738 " value: 1001,\n" 2739 " writable: false,\n" 2740 " enumerable: false,\n" 2741 " configurable: true\n" 2742 "});\n" 2743 "Object.defineProperty(appointment, 'name', {\n" 2744 " value: 'NAME',\n" 2745 " writable: false,\n" 2746 " enumerable: false,\n" 2747 " configurable: true\n" 2748 "});\n" 2749 "var meeting = Object.create(appointment);\n" 2750 "Object.defineProperty(meeting, 'conferenceCall', {\n" 2751 " value: 'In-person meeting',\n" 2752 " writable: false,\n" 2753 " enumerable: false,\n" 2754 " configurable: true\n" 2755 "});\n" 2756 "\n" 2757 "var teamMeeting = Object.create(meeting);\n" 2758 "\n" 2759 "var flags = 0;\n" 2760 "for (var p in teamMeeting) {\n" 2761 " if (p === 'startTime') {\n" 2762 " flags |= 1;\n" 2763 " }\n" 2764 " if (p === 'name') {\n" 2765 " flags |= 2;\n" 2766 " }\n" 2767 " if (p === 'conferenceCall') {\n" 2768 " flags |= 4;\n" 2769 " }\n" 2770 "}\n" 2771 "\n" 2772 "var hasOwnProperty = !teamMeeting.hasOwnProperty('name') &&\n" 2773 " !teamMeeting.hasOwnProperty('startTime') &&\n" 2774 " !teamMeeting.hasOwnProperty('conferenceCall');\n" 2775 "if (!hasOwnProperty) {\n" 2776 " flags |= 8;\n" 2777 "}\n" 2778 "return flags;\n", 2779 0}, 2780 {"var data = {x:23, y:34};\n" 2781 " var result = 0;\n" 2782 "var o = {};\n" 2783 "var arr = [o];\n" 2784 "for (arr[0].p in data)\n" // This is to test if value is loaded 2785 " result += data[arr[0].p];\n" // back from accumulator before storing 2786 "return result;\n", // named properties. 2787 57}, 2788 {"var data = {x:23, y:34};\n" 2789 "var result = 0;\n" 2790 "var o = {};\n" 2791 "var i = 0;\n" 2792 "for (o[i++] in data)\n" // This is to test if value is loaded 2793 " result += data[o[i-1]];\n" // back from accumulator before 2794 "return result;\n", // storing keyed properties. 2795 57}}; 2796 2797 // Two passes are made for this test. On the first, 8-bit register 2798 // operands are employed, and on the 16-bit register operands are 2799 // used. 2800 for (int pass = 0; pass < 2; pass++) { 2801 HandleAndZoneScope handles; 2802 std::ostringstream wide_os; 2803 if (pass == 1) { 2804 for (int i = 0; i < 200; i++) { 2805 wide_os << "var local" << i << " = 0;\n"; 2806 } 2807 } 2808 2809 for (size_t i = 0; i < arraysize(for_in_samples); i++) { 2810 std::ostringstream body_os; 2811 body_os << wide_os.str() << for_in_samples[i].first; 2812 std::string body(body_os.str()); 2813 std::string function = InterpreterTester::SourceForBody(body.c_str()); 2814 InterpreterTester tester(handles.main_isolate(), function.c_str()); 2815 auto callable = tester.GetCallable<>(); 2816 Handle<Object> return_val = callable().ToHandleChecked(); 2817 CHECK_EQ(Handle<Smi>::cast(return_val)->value(), 2818 for_in_samples[i].second); 2819 } 2820 } 2821 } 2822 2823 2824 TEST(InterpreterForOf) { 2825 HandleAndZoneScope handles; 2826 i::Isolate* isolate = handles.main_isolate(); 2827 i::Factory* factory = isolate->factory(); 2828 2829 std::pair<const char*, Handle<Object>> for_of[] = { 2830 {"function f() {\n" 2831 " var r = 0;\n" 2832 " for (var a of [0,6,7,9]) { r += a; }\n" 2833 " return r;\n" 2834 "}", 2835 handle(Smi::FromInt(22), isolate)}, 2836 {"function f() {\n" 2837 " var r = '';\n" 2838 " for (var a of 'foobar') { r = a + r; }\n" 2839 " return r;\n" 2840 "}", 2841 factory->NewStringFromStaticChars("raboof")}, 2842 {"function f() {\n" 2843 " var a = [1, 2, 3];\n" 2844 " a.name = 4;\n" 2845 " var r = 0;\n" 2846 " for (var x of a) { r += x; }\n" 2847 " return r;\n" 2848 "}", 2849 handle(Smi::FromInt(6), isolate)}, 2850 {"function f() {\n" 2851 " var r = '';\n" 2852 " var data = [1, 2, 3]; \n" 2853 " for (a of data) { delete data[0]; r += a; } return r; }", 2854 factory->NewStringFromStaticChars("123")}, 2855 {"function f() {\n" 2856 " var r = '';\n" 2857 " var data = [1, 2, 3]; \n" 2858 " for (a of data) { delete data[2]; r += a; } return r; }", 2859 factory->NewStringFromStaticChars("12undefined")}, 2860 {"function f() {\n" 2861 " var r = '';\n" 2862 " var data = [1, 2, 3]; \n" 2863 " for (a of data) { delete data; r += a; } return r; }", 2864 factory->NewStringFromStaticChars("123")}, 2865 {"function f() {\n" 2866 " var r = '';\n" 2867 " var input = 'foobar';\n" 2868 " for (var a of input) {\n" 2869 " if (a == 'b') break;\n" 2870 " r += a;\n" 2871 " }\n" 2872 " return r;\n" 2873 "}", 2874 factory->NewStringFromStaticChars("foo")}, 2875 {"function f() {\n" 2876 " var r = '';\n" 2877 " var input = 'foobar';\n" 2878 " for (var a of input) {\n" 2879 " if (a == 'b') continue;\n" 2880 " r += a;\n" 2881 " }\n" 2882 " return r;\n" 2883 "}", 2884 factory->NewStringFromStaticChars("fooar")}, 2885 {"function f() {\n" 2886 " var r = '';\n" 2887 " var data = [1, 2, 3, 4]; \n" 2888 " for (a of data) { data[2] = 567; r += a; }\n" 2889 " return r;\n" 2890 "}", 2891 factory->NewStringFromStaticChars("125674")}, 2892 {"function f() {\n" 2893 " var r = '';\n" 2894 " var data = [1, 2, 3, 4]; \n" 2895 " for (a of data) { data[4] = 567; r += a; }\n" 2896 " return r;\n" 2897 "}", 2898 factory->NewStringFromStaticChars("1234567")}, 2899 {"function f() {\n" 2900 " var r = '';\n" 2901 " var data = [1, 2, 3, 4]; \n" 2902 " for (a of data) { data[5] = 567; r += a; }\n" 2903 " return r;\n" 2904 "}", 2905 factory->NewStringFromStaticChars("1234undefined567")}, 2906 {"function f() {\n" 2907 " var r = '';\n" 2908 " var obj = new Object();\n" 2909 " obj[Symbol.iterator] = function() { return {\n" 2910 " index: 3,\n" 2911 " data: ['a', 'b', 'c', 'd']," 2912 " next: function() {" 2913 " return {" 2914 " done: this.index == -1,\n" 2915 " value: this.index < 0 ? undefined : this.data[this.index--]\n" 2916 " }\n" 2917 " }\n" 2918 " }}\n" 2919 " for (a of obj) { r += a }\n" 2920 " return r;\n" 2921 "}", 2922 factory->NewStringFromStaticChars("dcba")}, 2923 }; 2924 2925 for (size_t i = 0; i < arraysize(for_of); i++) { 2926 InterpreterTester tester(handles.main_isolate(), for_of[i].first); 2927 auto callable = tester.GetCallable<>(); 2928 Handle<Object> return_val = callable().ToHandleChecked(); 2929 CHECK(return_val->SameValue(*for_of[i].second)); 2930 } 2931 } 2932 2933 2934 TEST(InterpreterSwitch) { 2935 HandleAndZoneScope handles; 2936 i::Isolate* isolate = handles.main_isolate(); 2937 i::Factory* factory = isolate->factory(); 2938 2939 std::pair<const char*, Handle<Object>> switch_ops[] = { 2940 std::make_pair("var a = 1;\n" 2941 "switch(a) {\n" 2942 " case 1: return 2;\n" 2943 " case 2: return 3;\n" 2944 "}\n", 2945 handle(Smi::FromInt(2), isolate)), 2946 std::make_pair("var a = 1;\n" 2947 "switch(a) {\n" 2948 " case 2: a = 2; break;\n" 2949 " case 1: a = 3; break;\n" 2950 "}\n" 2951 "return a;", 2952 handle(Smi::FromInt(3), isolate)), 2953 std::make_pair("var a = 1;\n" 2954 "switch(a) {\n" 2955 " case 1: a = 2; // fall-through\n" 2956 " case 2: a = 3; break;\n" 2957 "}\n" 2958 "return a;", 2959 handle(Smi::FromInt(3), isolate)), 2960 std::make_pair("var a = 100;\n" 2961 "switch(a) {\n" 2962 " case 1: return 100;\n" 2963 " case 2: return 200;\n" 2964 "}\n" 2965 "return undefined;", 2966 factory->undefined_value()), 2967 std::make_pair("var a = 100;\n" 2968 "switch(a) {\n" 2969 " case 1: return 100;\n" 2970 " case 2: return 200;\n" 2971 " default: return 300;\n" 2972 "}\n" 2973 "return undefined;", 2974 handle(Smi::FromInt(300), isolate)), 2975 std::make_pair("var a = 100;\n" 2976 "switch(typeof(a)) {\n" 2977 " case 'string': return 1;\n" 2978 " case 'number': return 2;\n" 2979 " default: return 3;\n" 2980 "}\n", 2981 handle(Smi::FromInt(2), isolate)), 2982 std::make_pair("var a = 100;\n" 2983 "switch(a) {\n" 2984 " case a += 20: return 1;\n" 2985 " case a -= 10: return 2;\n" 2986 " case a -= 10: return 3;\n" 2987 " default: return 3;\n" 2988 "}\n", 2989 handle(Smi::FromInt(3), isolate)), 2990 std::make_pair("var a = 1;\n" 2991 "switch(a) {\n" 2992 " case 1: \n" 2993 " switch(a + 1) {\n" 2994 " case 2 : a += 1; break;\n" 2995 " default : a += 2; break;\n" 2996 " } // fall-through\n" 2997 " case 2: a += 3;\n" 2998 "}\n" 2999 "return a;", 3000 handle(Smi::FromInt(5), isolate)), 3001 }; 3002 3003 for (size_t i = 0; i < arraysize(switch_ops); i++) { 3004 std::string source(InterpreterTester::SourceForBody(switch_ops[i].first)); 3005 InterpreterTester tester(handles.main_isolate(), source.c_str()); 3006 auto callable = tester.GetCallable<>(); 3007 3008 Handle<i::Object> return_value = callable().ToHandleChecked(); 3009 CHECK(return_value->SameValue(*switch_ops[i].second)); 3010 } 3011 } 3012 3013 3014 TEST(InterpreterSloppyThis) { 3015 HandleAndZoneScope handles; 3016 i::Isolate* isolate = handles.main_isolate(); 3017 i::Factory* factory = isolate->factory(); 3018 3019 std::pair<const char*, Handle<Object>> sloppy_this[] = { 3020 std::make_pair("var global_val = 100;\n" 3021 "function f() { return this.global_val; }\n", 3022 handle(Smi::FromInt(100), isolate)), 3023 std::make_pair("var global_val = 110;\n" 3024 "function g() { return this.global_val; };" 3025 "function f() { return g(); }\n", 3026 handle(Smi::FromInt(110), isolate)), 3027 std::make_pair("var global_val = 110;\n" 3028 "function g() { return this.global_val };" 3029 "function f() { 'use strict'; return g(); }\n", 3030 handle(Smi::FromInt(110), isolate)), 3031 std::make_pair("function f() { 'use strict'; return this; }\n", 3032 factory->undefined_value()), 3033 std::make_pair("function g() { 'use strict'; return this; };" 3034 "function f() { return g(); }\n", 3035 factory->undefined_value()), 3036 }; 3037 3038 for (size_t i = 0; i < arraysize(sloppy_this); i++) { 3039 InterpreterTester tester(handles.main_isolate(), sloppy_this[i].first); 3040 auto callable = tester.GetCallable<>(); 3041 3042 Handle<i::Object> return_value = callable().ToHandleChecked(); 3043 CHECK(return_value->SameValue(*sloppy_this[i].second)); 3044 } 3045 } 3046 3047 3048 TEST(InterpreterThisFunction) { 3049 HandleAndZoneScope handles; 3050 i::Isolate* isolate = handles.main_isolate(); 3051 i::Factory* factory = isolate->factory(); 3052 3053 InterpreterTester tester(handles.main_isolate(), 3054 "var f;\n f = function f() { return f.name; }"); 3055 auto callable = tester.GetCallable<>(); 3056 3057 Handle<i::Object> return_value = callable().ToHandleChecked(); 3058 CHECK(return_value->SameValue(*factory->NewStringFromStaticChars("f"))); 3059 } 3060 3061 3062 TEST(InterpreterNewTarget) { 3063 HandleAndZoneScope handles; 3064 i::Isolate* isolate = handles.main_isolate(); 3065 i::Factory* factory = isolate->factory(); 3066 3067 // TODO(rmcilroy): Add tests that we get the original constructor for 3068 // superclass constructors once we have class support. 3069 InterpreterTester tester(handles.main_isolate(), 3070 "function f() { this.a = new.target; }"); 3071 auto callable = tester.GetCallable<>(); 3072 callable().ToHandleChecked(); 3073 3074 Handle<Object> new_target_name = v8::Utils::OpenHandle( 3075 *CompileRun("(function() { return (new f()).a.name; })();")); 3076 CHECK(new_target_name->SameValue(*factory->NewStringFromStaticChars("f"))); 3077 } 3078 3079 3080 TEST(InterpreterAssignmentInExpressions) { 3081 HandleAndZoneScope handles; 3082 3083 std::pair<const char*, int> samples[] = { 3084 {"function f() {\n" 3085 " var x = 7;\n" 3086 " var y = x + (x = 1) + (x = 2);\n" 3087 " return y;\n" 3088 "}", 3089 10}, 3090 {"function f() {\n" 3091 " var x = 7;\n" 3092 " var y = x + (x = 1) + (x = 2);\n" 3093 " return x;\n" 3094 "}", 3095 2}, 3096 {"function f() {\n" 3097 " var x = 55;\n" 3098 " x = x + (x = 100) + (x = 101);\n" 3099 " return x;\n" 3100 "}", 3101 256}, 3102 {"function f() {\n" 3103 " var x = 7;\n" 3104 " return ++x + x + x++;\n" 3105 "}", 3106 24}, 3107 {"function f() {\n" 3108 " var x = 7;\n" 3109 " var y = 1 + ++x + x + x++;\n" 3110 " return x;\n" 3111 "}", 3112 9}, 3113 {"function f() {\n" 3114 " var x = 7;\n" 3115 " var y = ++x + x + x++;\n" 3116 " return x;\n" 3117 "}", 3118 9}, 3119 {"function f() {\n" 3120 " var x = 7, y = 100, z = 1000;\n" 3121 " return x + (x += 3) + y + (y *= 10) + (z *= 7) + z;\n" 3122 "}", 3123 15117}, 3124 {"function f() {\n" 3125 " var inner = function (x) { return x + (x = 2) + (x = 4) + x; };\n" 3126 " return inner(1);\n" 3127 "}", 3128 11}, 3129 {"function f() {\n" 3130 " var x = 1, y = 2;\n" 3131 " x = x + (x = 3) + y + (y = 4), y = y + (y = 5) + y + x;\n" 3132 " return x + y;\n" 3133 "}", 3134 10 + 24}, 3135 {"function f() {\n" 3136 " var x = 0;\n" 3137 " var y = x | (x = 1) | (x = 2);\n" 3138 " return x;\n" 3139 "}", 3140 2}, 3141 {"function f() {\n" 3142 " var x = 0;\n" 3143 " var y = x || (x = 1);\n" 3144 " return x;\n" 3145 "}", 3146 1}, 3147 {"function f() {\n" 3148 " var x = 1;\n" 3149 " var y = x && (x = 2) && (x = 3);\n" 3150 " return x;\n" 3151 "}", 3152 3}, 3153 {"function f() {\n" 3154 " var x = 1;\n" 3155 " var y = x || (x = 2);\n" 3156 " return x;\n" 3157 "}", 3158 1}, 3159 {"function f() {\n" 3160 " var x = 1;\n" 3161 " x = (x << (x = 3)) | (x = 16);\n" 3162 " return x;\n" 3163 "}", 3164 24}, 3165 {"function f() {\n" 3166 " var r = 7;\n" 3167 " var s = 11;\n" 3168 " var t = 13;\n" 3169 " var u = r + s + t + (r = 10) + (s = 20) +" 3170 " (t = (r + s)) + r + s + t;\n" 3171 " return r + s + t + u;\n" 3172 "}", 3173 211}, 3174 {"function f() {\n" 3175 " var r = 7;\n" 3176 " var s = 11;\n" 3177 " var t = 13;\n" 3178 " return r > (3 * s * (s = 1)) ? (t + (t += 1)) : (r + (r = 4));\n" 3179 "}", 3180 11}, 3181 {"function f() {\n" 3182 " var r = 7;\n" 3183 " var s = 11;\n" 3184 " var t = 13;\n" 3185 " return r > (3 * s * (s = 0)) ? (t + (t += 1)) : (r + (r = 4));\n" 3186 "}", 3187 27}, 3188 {"function f() {\n" 3189 " var r = 7;\n" 3190 " var s = 11;\n" 3191 " var t = 13;\n" 3192 " return (r + (r = 5)) > s ? r : t;\n" 3193 "}", 3194 5}, 3195 {"function f(a) {\n" 3196 " return a + (arguments[0] = 10);\n" 3197 "}", 3198 50}, 3199 {"function f(a) {\n" 3200 " return a + (arguments[0] = 10) + a;\n" 3201 "}", 3202 60}, 3203 {"function f(a) {\n" 3204 " return a + (arguments[0] = 10) + arguments[0];\n" 3205 "}", 3206 60}, 3207 }; 3208 3209 const int arg_value = 40; 3210 for (size_t i = 0; i < arraysize(samples); i++) { 3211 InterpreterTester tester(handles.main_isolate(), samples[i].first); 3212 auto callable = tester.GetCallable<Handle<Object>>(); 3213 Handle<Object> return_val = 3214 callable(handle(Smi::FromInt(arg_value), handles.main_isolate())) 3215 .ToHandleChecked(); 3216 CHECK_EQ(Handle<Smi>::cast(return_val)->value(), samples[i].second); 3217 } 3218 } 3219 3220 3221 TEST(InterpreterToName) { 3222 HandleAndZoneScope handles; 3223 i::Isolate* isolate = handles.main_isolate(); 3224 i::Factory* factory = isolate->factory(); 3225 3226 std::pair<const char*, Handle<Object>> to_name_tests[] = { 3227 {"var a = 'val'; var obj = {[a] : 10}; return obj.val;", 3228 factory->NewNumberFromInt(10)}, 3229 {"var a = 20; var obj = {[a] : 10}; return obj['20'];", 3230 factory->NewNumberFromInt(10)}, 3231 {"var a = 20; var obj = {[a] : 10}; return obj[20];", 3232 factory->NewNumberFromInt(10)}, 3233 {"var a = {val:23}; var obj = {[a] : 10}; return obj[a];", 3234 factory->NewNumberFromInt(10)}, 3235 {"var a = {val:23}; var obj = {[a] : 10};\n" 3236 "return obj['[object Object]'];", 3237 factory->NewNumberFromInt(10)}, 3238 {"var a = {toString : function() { return 'x'}};\n" 3239 "var obj = {[a] : 10};\n" 3240 "return obj.x;", 3241 factory->NewNumberFromInt(10)}, 3242 {"var a = {valueOf : function() { return 'x'}};\n" 3243 "var obj = {[a] : 10};\n" 3244 "return obj.x;", 3245 factory->undefined_value()}, 3246 {"var a = {[Symbol.toPrimitive] : function() { return 'x'}};\n" 3247 "var obj = {[a] : 10};\n" 3248 "return obj.x;", 3249 factory->NewNumberFromInt(10)}, 3250 }; 3251 3252 for (size_t i = 0; i < arraysize(to_name_tests); i++) { 3253 std::string source( 3254 InterpreterTester::SourceForBody(to_name_tests[i].first)); 3255 InterpreterTester tester(handles.main_isolate(), source.c_str()); 3256 auto callable = tester.GetCallable<>(); 3257 3258 Handle<i::Object> return_value = callable().ToHandleChecked(); 3259 CHECK(return_value->SameValue(*to_name_tests[i].second)); 3260 } 3261 } 3262 3263 3264 TEST(TemporaryRegisterAllocation) { 3265 HandleAndZoneScope handles; 3266 i::Isolate* isolate = handles.main_isolate(); 3267 i::Factory* factory = isolate->factory(); 3268 3269 std::pair<const char*, Handle<Object>> reg_tests[] = { 3270 {"function add(a, b, c) {" 3271 " return a + b + c;" 3272 "}" 3273 "function f() {" 3274 " var a = 10, b = 10;" 3275 " return add(a, b++, b);" 3276 "}", 3277 factory->NewNumberFromInt(31)}, 3278 {"function add(a, b, c, d) {" 3279 " return a + b + c + d;" 3280 "}" 3281 "function f() {" 3282 " var x = 10, y = 20, z = 30;" 3283 " return x + add(x, (y= x++), x, z);" 3284 "}", 3285 factory->NewNumberFromInt(71)}, 3286 }; 3287 3288 for (size_t i = 0; i < arraysize(reg_tests); i++) { 3289 InterpreterTester tester(handles.main_isolate(), reg_tests[i].first); 3290 auto callable = tester.GetCallable<>(); 3291 3292 Handle<i::Object> return_value = callable().ToHandleChecked(); 3293 CHECK(return_value->SameValue(*reg_tests[i].second)); 3294 } 3295 } 3296 3297 3298 TEST(InterpreterLookupSlot) { 3299 HandleAndZoneScope handles; 3300 i::Isolate* isolate = handles.main_isolate(); 3301 i::Factory* factory = isolate->factory(); 3302 3303 // TODO(mythria): Add more tests when we have support for eval/with. 3304 const char* function_prologue = "var f;" 3305 "var x = 1;" 3306 "function f1() {" 3307 " eval(\"function t() {"; 3308 const char* function_epilogue = " }; f = t;\");" 3309 "}" 3310 "f1();"; 3311 3312 3313 std::pair<const char*, Handle<Object>> lookup_slot[] = { 3314 {"return x;", handle(Smi::FromInt(1), isolate)}, 3315 {"return typeof x;", factory->NewStringFromStaticChars("number")}, 3316 {"return typeof dummy;", factory->NewStringFromStaticChars("undefined")}, 3317 {"x = 10; return x;", handle(Smi::FromInt(10), isolate)}, 3318 {"'use strict'; x = 20; return x;", handle(Smi::FromInt(20), isolate)}, 3319 }; 3320 3321 for (size_t i = 0; i < arraysize(lookup_slot); i++) { 3322 std::string script = std::string(function_prologue) + 3323 std::string(lookup_slot[i].first) + 3324 std::string(function_epilogue); 3325 3326 InterpreterTester tester(handles.main_isolate(), script.c_str(), "t"); 3327 auto callable = tester.GetCallable<>(); 3328 3329 Handle<i::Object> return_value = callable().ToHandleChecked(); 3330 CHECK(return_value->SameValue(*lookup_slot[i].second)); 3331 } 3332 } 3333 3334 3335 TEST(InterpreterCallLookupSlot) { 3336 HandleAndZoneScope handles; 3337 i::Isolate* isolate = handles.main_isolate(); 3338 3339 std::pair<const char*, Handle<Object>> call_lookup[] = { 3340 {"g = function(){ return 2 }; eval(''); return g();", 3341 handle(Smi::FromInt(2), isolate)}, 3342 {"g = function(){ return 2 }; eval('g = function() {return 3}');\n" 3343 "return g();", 3344 handle(Smi::FromInt(3), isolate)}, 3345 {"g = { x: function(){ return this.y }, y: 20 };\n" 3346 "eval('g = { x: g.x, y: 30 }');\n" 3347 "return g.x();", 3348 handle(Smi::FromInt(30), isolate)}, 3349 }; 3350 3351 for (size_t i = 0; i < arraysize(call_lookup); i++) { 3352 std::string source(InterpreterTester::SourceForBody(call_lookup[i].first)); 3353 InterpreterTester tester(handles.main_isolate(), source.c_str()); 3354 auto callable = tester.GetCallable<>(); 3355 3356 Handle<i::Object> return_value = callable().ToHandleChecked(); 3357 CHECK(return_value->SameValue(*call_lookup[i].second)); 3358 } 3359 } 3360 3361 3362 TEST(InterpreterLookupSlotWide) { 3363 HandleAndZoneScope handles; 3364 i::Isolate* isolate = handles.main_isolate(); 3365 i::Factory* factory = isolate->factory(); 3366 3367 const char* function_prologue = 3368 "var f;" 3369 "var x = 1;" 3370 "function f1() {" 3371 " eval(\"function t() {"; 3372 const char* function_epilogue = 3373 " }; f = t;\");" 3374 "}" 3375 "f1();"; 3376 std::ostringstream str; 3377 str << "var y = 2.3;"; 3378 for (int i = 1; i < 256; i++) { 3379 str << "y = " << 2.3 + i << ";"; 3380 } 3381 std::string init_function_body = str.str(); 3382 3383 std::pair<std::string, Handle<Object>> lookup_slot[] = { 3384 {init_function_body + "return x;", handle(Smi::FromInt(1), isolate)}, 3385 {init_function_body + "return typeof x;", 3386 factory->NewStringFromStaticChars("number")}, 3387 {init_function_body + "return x = 10;", 3388 handle(Smi::FromInt(10), isolate)}, 3389 {"'use strict';" + init_function_body + "x = 20; return x;", 3390 handle(Smi::FromInt(20), isolate)}, 3391 }; 3392 3393 for (size_t i = 0; i < arraysize(lookup_slot); i++) { 3394 std::string script = std::string(function_prologue) + lookup_slot[i].first + 3395 std::string(function_epilogue); 3396 3397 InterpreterTester tester(handles.main_isolate(), script.c_str(), "t"); 3398 auto callable = tester.GetCallable<>(); 3399 3400 Handle<i::Object> return_value = callable().ToHandleChecked(); 3401 CHECK(return_value->SameValue(*lookup_slot[i].second)); 3402 } 3403 } 3404 3405 3406 TEST(InterpreterDeleteLookupSlot) { 3407 HandleAndZoneScope handles; 3408 i::Isolate* isolate = handles.main_isolate(); 3409 i::Factory* factory = isolate->factory(); 3410 3411 // TODO(mythria): Add more tests when we have support for eval/with. 3412 const char* function_prologue = "var f;" 3413 "var x = 1;" 3414 "y = 10;" 3415 "var obj = {val:10};" 3416 "var z = 30;" 3417 "function f1() {" 3418 " var z = 20;" 3419 " eval(\"function t() {"; 3420 const char* function_epilogue = " }; f = t;\");" 3421 "}" 3422 "f1();"; 3423 3424 3425 std::pair<const char*, Handle<Object>> delete_lookup_slot[] = { 3426 {"return delete x;", factory->false_value()}, 3427 {"return delete y;", factory->true_value()}, 3428 {"return delete z;", factory->false_value()}, 3429 {"return delete obj.val;", factory->true_value()}, 3430 {"'use strict'; return delete obj.val;", factory->true_value()}, 3431 }; 3432 3433 for (size_t i = 0; i < arraysize(delete_lookup_slot); i++) { 3434 std::string script = std::string(function_prologue) + 3435 std::string(delete_lookup_slot[i].first) + 3436 std::string(function_epilogue); 3437 3438 InterpreterTester tester(handles.main_isolate(), script.c_str(), "t"); 3439 auto callable = tester.GetCallable<>(); 3440 3441 Handle<i::Object> return_value = callable().ToHandleChecked(); 3442 CHECK(return_value->SameValue(*delete_lookup_slot[i].second)); 3443 } 3444 } 3445 3446 3447 TEST(JumpWithConstantsAndWideConstants) { 3448 HandleAndZoneScope handles; 3449 const int kStep = 13; 3450 for (int constants = 11; constants < 256 + 3 * kStep; constants += kStep) { 3451 auto isolate = handles.main_isolate(); 3452 auto factory = isolate->factory(); 3453 std::ostringstream filler_os; 3454 // Generate a string that consumes constant pool entries and 3455 // spread out branch distances in script below. 3456 for (int i = 0; i < constants; i++) { 3457 filler_os << "var x_ = 'x_" << i << "';\n"; 3458 } 3459 std::string filler(filler_os.str()); 3460 std::ostringstream script_os; 3461 script_os << "function " << InterpreterTester::function_name() << "(a) {\n"; 3462 script_os << " " << filler; 3463 script_os << " for (var i = a; i < 2; i++) {\n"; 3464 script_os << " " << filler; 3465 script_os << " if (i == 0) { " << filler << "i = 10; continue; }\n"; 3466 script_os << " else if (i == a) { " << filler << "i = 12; break; }\n"; 3467 script_os << " else { " << filler << " }\n"; 3468 script_os << " }\n"; 3469 script_os << " return i;\n"; 3470 script_os << "}\n"; 3471 std::string script(script_os.str()); 3472 for (int a = 0; a < 3; a++) { 3473 InterpreterTester tester(handles.main_isolate(), script.c_str()); 3474 auto callable = tester.GetCallable<Handle<Object>>(); 3475 Handle<Object> argument = factory->NewNumberFromInt(a); 3476 Handle<Object> return_val = callable(argument).ToHandleChecked(); 3477 static const int results[] = {11, 12, 2}; 3478 CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]); 3479 } 3480 } 3481 } 3482 3483 3484 TEST(InterpreterEval) { 3485 HandleAndZoneScope handles; 3486 i::Isolate* isolate = handles.main_isolate(); 3487 i::Factory* factory = isolate->factory(); 3488 3489 std::pair<const char*, Handle<Object>> eval[] = { 3490 {"return eval('1;');", handle(Smi::FromInt(1), isolate)}, 3491 {"return eval('100 * 20;');", handle(Smi::FromInt(2000), isolate)}, 3492 {"var x = 10; return eval('x + 20;');", 3493 handle(Smi::FromInt(30), isolate)}, 3494 {"var x = 10; eval('x = 33;'); return x;", 3495 handle(Smi::FromInt(33), isolate)}, 3496 {"'use strict'; var x = 20; var z = 0;\n" 3497 "eval('var x = 33; z = x;'); return x + z;", 3498 handle(Smi::FromInt(53), isolate)}, 3499 {"eval('var x = 33;'); eval('var y = x + 20'); return x + y;", 3500 handle(Smi::FromInt(86), isolate)}, 3501 {"var x = 1; eval('for(i = 0; i < 10; i++) x = x + 1;'); return x", 3502 handle(Smi::FromInt(11), isolate)}, 3503 {"var x = 10; eval('var x = 20;'); return x;", 3504 handle(Smi::FromInt(20), isolate)}, 3505 {"var x = 1; eval('\"use strict\"; var x = 2;'); return x;", 3506 handle(Smi::FromInt(1), isolate)}, 3507 {"'use strict'; var x = 1; eval('var x = 2;'); return x;", 3508 handle(Smi::FromInt(1), isolate)}, 3509 {"var x = 10; eval('x + 20;'); return typeof x;", 3510 factory->NewStringFromStaticChars("number")}, 3511 {"eval('var y = 10;'); return typeof unallocated;", 3512 factory->NewStringFromStaticChars("undefined")}, 3513 {"'use strict'; eval('var y = 10;'); return typeof unallocated;", 3514 factory->NewStringFromStaticChars("undefined")}, 3515 {"eval('var x = 10;'); return typeof x;", 3516 factory->NewStringFromStaticChars("number")}, 3517 {"var x = {}; eval('var x = 10;'); return typeof x;", 3518 factory->NewStringFromStaticChars("number")}, 3519 {"'use strict'; var x = {}; eval('var x = 10;'); return typeof x;", 3520 factory->NewStringFromStaticChars("object")}, 3521 }; 3522 3523 for (size_t i = 0; i < arraysize(eval); i++) { 3524 std::string source(InterpreterTester::SourceForBody(eval[i].first)); 3525 InterpreterTester tester(handles.main_isolate(), source.c_str()); 3526 auto callable = tester.GetCallable<>(); 3527 Handle<i::Object> return_value = callable().ToHandleChecked(); 3528 CHECK(return_value->SameValue(*eval[i].second)); 3529 } 3530 } 3531 3532 3533 TEST(InterpreterEvalParams) { 3534 HandleAndZoneScope handles; 3535 i::Isolate* isolate = handles.main_isolate(); 3536 3537 std::pair<const char*, Handle<Object>> eval_params[] = { 3538 {"var x = 10; return eval('x + p1;');", 3539 handle(Smi::FromInt(30), isolate)}, 3540 {"var x = 10; eval('p1 = x;'); return p1;", 3541 handle(Smi::FromInt(10), isolate)}, 3542 {"var a = 10;" 3543 "function inner() { return eval('a + p1;');}" 3544 "return inner();", 3545 handle(Smi::FromInt(30), isolate)}, 3546 }; 3547 3548 for (size_t i = 0; i < arraysize(eval_params); i++) { 3549 std::string source = "function " + InterpreterTester::function_name() + 3550 "(p1) {" + eval_params[i].first + "}"; 3551 InterpreterTester tester(handles.main_isolate(), source.c_str()); 3552 auto callable = tester.GetCallable<Handle<Object>>(); 3553 3554 Handle<i::Object> return_value = 3555 callable(handle(Smi::FromInt(20), isolate)).ToHandleChecked(); 3556 CHECK(return_value->SameValue(*eval_params[i].second)); 3557 } 3558 } 3559 3560 3561 TEST(InterpreterEvalGlobal) { 3562 HandleAndZoneScope handles; 3563 i::Isolate* isolate = handles.main_isolate(); 3564 i::Factory* factory = isolate->factory(); 3565 3566 std::pair<const char*, Handle<Object>> eval_global[] = { 3567 {"function add_global() { eval('function test() { z = 33; }; test()'); };" 3568 "function f() { add_global(); return z; }; f();", 3569 handle(Smi::FromInt(33), isolate)}, 3570 {"function add_global() {\n" 3571 " eval('\"use strict\"; function test() { y = 33; };" 3572 " try { test() } catch(e) {}');\n" 3573 "}\n" 3574 "function f() { add_global(); return typeof y; } f();", 3575 factory->NewStringFromStaticChars("undefined")}, 3576 }; 3577 3578 for (size_t i = 0; i < arraysize(eval_global); i++) { 3579 InterpreterTester tester(handles.main_isolate(), eval_global[i].first, 3580 "test"); 3581 auto callable = tester.GetCallable<>(); 3582 3583 Handle<i::Object> return_value = callable().ToHandleChecked(); 3584 CHECK(return_value->SameValue(*eval_global[i].second)); 3585 } 3586 } 3587 3588 3589 TEST(InterpreterEvalVariableDecl) { 3590 HandleAndZoneScope handles; 3591 i::Isolate* isolate = handles.main_isolate(); 3592 i::Factory* factory = isolate->factory(); 3593 3594 std::pair<const char*, Handle<Object>> eval_global[] = { 3595 {"function f() { eval('var x = 10; x++;'); return x; }", 3596 handle(Smi::FromInt(11), isolate)}, 3597 {"function f() { var x = 20; eval('var x = 10; x++;'); return x; }", 3598 handle(Smi::FromInt(11), isolate)}, 3599 {"function f() {" 3600 " var x = 20;" 3601 " eval('\"use strict\"; var x = 10; x++;');" 3602 " return x; }", 3603 handle(Smi::FromInt(20), isolate)}, 3604 {"function f() {" 3605 " var y = 30;" 3606 " eval('var x = {1:20}; x[2]=y;');" 3607 " return x[2]; }", 3608 handle(Smi::FromInt(30), isolate)}, 3609 {"function f() {" 3610 " eval('var x = {name:\"test\"};');" 3611 " return x.name; }", 3612 factory->NewStringFromStaticChars("test")}, 3613 {"function f() {" 3614 " eval('var x = [{name:\"test\"}, {type:\"cc\"}];');" 3615 " return x[1].type+x[0].name; }", 3616 factory->NewStringFromStaticChars("cctest")}, 3617 {"function f() {\n" 3618 " var x = 3;\n" 3619 " var get_eval_x;\n" 3620 " eval('\"use strict\"; " 3621 " var x = 20; " 3622 " get_eval_x = function func() {return x;};');\n" 3623 " return get_eval_x() + x;\n" 3624 "}", 3625 handle(Smi::FromInt(23), isolate)}, 3626 // TODO(mythria): Add tests with const declarations. 3627 }; 3628 3629 for (size_t i = 0; i < arraysize(eval_global); i++) { 3630 InterpreterTester tester(handles.main_isolate(), eval_global[i].first, "*"); 3631 auto callable = tester.GetCallable<>(); 3632 3633 Handle<i::Object> return_value = callable().ToHandleChecked(); 3634 CHECK(return_value->SameValue(*eval_global[i].second)); 3635 } 3636 } 3637 3638 3639 TEST(InterpreterEvalFunctionDecl) { 3640 HandleAndZoneScope handles; 3641 i::Isolate* isolate = handles.main_isolate(); 3642 3643 std::pair<const char*, Handle<Object>> eval_func_decl[] = { 3644 {"function f() {\n" 3645 " var x = 3;\n" 3646 " eval('var x = 20;" 3647 " function get_x() {return x;};');\n" 3648 " return get_x() + x;\n" 3649 "}", 3650 handle(Smi::FromInt(40), isolate)}, 3651 }; 3652 3653 for (size_t i = 0; i < arraysize(eval_func_decl); i++) { 3654 InterpreterTester tester(handles.main_isolate(), eval_func_decl[i].first, 3655 "*"); 3656 auto callable = tester.GetCallable<>(); 3657 3658 Handle<i::Object> return_value = callable().ToHandleChecked(); 3659 CHECK(return_value->SameValue(*eval_func_decl[i].second)); 3660 } 3661 } 3662 3663 TEST(InterpreterWideRegisterArithmetic) { 3664 HandleAndZoneScope handles; 3665 i::Isolate* isolate = handles.main_isolate(); 3666 3667 static const size_t kMaxRegisterForTest = 150; 3668 std::ostringstream os; 3669 os << "function " << InterpreterTester::function_name() << "(arg) {\n"; 3670 os << " var retval = -77;\n"; 3671 for (size_t i = 0; i < kMaxRegisterForTest; i++) { 3672 os << " var x" << i << " = " << i << ";\n"; 3673 } 3674 for (size_t i = 0; i < kMaxRegisterForTest / 2; i++) { 3675 size_t j = kMaxRegisterForTest - i - 1; 3676 os << " var tmp = x" << j << ";\n"; 3677 os << " var x" << j << " = x" << i << ";\n"; 3678 os << " var x" << i << " = tmp;\n"; 3679 } 3680 for (size_t i = 0; i < kMaxRegisterForTest / 2; i++) { 3681 size_t j = kMaxRegisterForTest - i - 1; 3682 os << " var tmp = x" << j << ";\n"; 3683 os << " var x" << j << " = x" << i << ";\n"; 3684 os << " var x" << i << " = tmp;\n"; 3685 } 3686 for (size_t i = 0; i < kMaxRegisterForTest; i++) { 3687 os << " if (arg == " << i << ") {\n" // 3688 << " retval = x" << i << ";\n" // 3689 << " }\n"; // 3690 } 3691 os << " return retval;\n"; 3692 os << "}\n"; 3693 3694 std::string source = os.str(); 3695 InterpreterTester tester(handles.main_isolate(), source.c_str()); 3696 auto callable = tester.GetCallable<Handle<Object>>(); 3697 for (size_t i = 0; i < kMaxRegisterForTest; i++) { 3698 Handle<Object> arg = handle(Smi::FromInt(static_cast<int>(i)), isolate); 3699 Handle<Object> return_value = callable(arg).ToHandleChecked(); 3700 CHECK(return_value->SameValue(*arg)); 3701 } 3702 } 3703 3704 TEST(InterpreterCallWideRegisters) { 3705 static const int kPeriod = 25; 3706 static const int kLength = 512; 3707 static const int kStartChar = 65; 3708 3709 for (int pass = 0; pass < 3; pass += 1) { 3710 std::ostringstream os; 3711 for (int i = 0; i < pass * 97; i += 1) { 3712 os << "var x" << i << " = " << i << "\n"; 3713 } 3714 os << "return String.fromCharCode("; 3715 os << kStartChar; 3716 for (int i = 1; i < kLength; i += 1) { 3717 os << "," << kStartChar + (i % kPeriod); 3718 } 3719 os << ");"; 3720 std::string source = InterpreterTester::SourceForBody(os.str().c_str()); 3721 HandleAndZoneScope handles; 3722 InterpreterTester tester(handles.main_isolate(), source.c_str()); 3723 auto callable = tester.GetCallable(); 3724 Handle<Object> return_val = callable().ToHandleChecked(); 3725 Handle<String> return_string = Handle<String>::cast(return_val); 3726 CHECK_EQ(return_string->length(), kLength); 3727 for (int i = 0; i < kLength; i += 1) { 3728 CHECK_EQ(return_string->Get(i), 65 + (i % kPeriod)); 3729 } 3730 } 3731 } 3732 3733 TEST(InterpreterWideParametersPickOne) { 3734 static const int kParameterCount = 130; 3735 for (int parameter = 0; parameter < 10; parameter++) { 3736 HandleAndZoneScope handles; 3737 i::Isolate* isolate = handles.main_isolate(); 3738 std::ostringstream os; 3739 os << "function " << InterpreterTester::function_name() << "(arg) {\n"; 3740 os << " function selector(i"; 3741 for (int i = 0; i < kParameterCount; i++) { 3742 os << "," 3743 << "a" << i; 3744 } 3745 os << ") {\n"; 3746 os << " return a" << parameter << ";\n"; 3747 os << " };\n"; 3748 os << " return selector(arg"; 3749 for (int i = 0; i < kParameterCount; i++) { 3750 os << "," << i; 3751 } 3752 os << ");"; 3753 os << "}\n"; 3754 3755 std::string source = os.str(); 3756 InterpreterTester tester(handles.main_isolate(), source.c_str(), "*"); 3757 auto callable = tester.GetCallable<Handle<Object>>(); 3758 Handle<Object> arg = handle(Smi::FromInt(0xaa55), isolate); 3759 Handle<Object> return_value = callable(arg).ToHandleChecked(); 3760 Handle<Smi> actual = Handle<Smi>::cast(return_value); 3761 CHECK_EQ(actual->value(), parameter); 3762 } 3763 } 3764 3765 TEST(InterpreterWideParametersSummation) { 3766 static int kParameterCount = 200; 3767 static int kBaseValue = 17000; 3768 HandleAndZoneScope handles; 3769 i::Isolate* isolate = handles.main_isolate(); 3770 std::ostringstream os; 3771 os << "function " << InterpreterTester::function_name() << "(arg) {\n"; 3772 os << " function summation(i"; 3773 for (int i = 0; i < kParameterCount; i++) { 3774 os << "," 3775 << "a" << i; 3776 } 3777 os << ") {\n"; 3778 os << " var sum = " << kBaseValue << ";\n"; 3779 os << " switch(i) {\n"; 3780 for (int i = 0; i < kParameterCount; i++) { 3781 int j = kParameterCount - i - 1; 3782 os << " case " << j << ": sum += a" << j << ";\n"; 3783 } 3784 os << " }\n"; 3785 os << " return sum;\n"; 3786 os << " };\n"; 3787 os << " return summation(arg"; 3788 for (int i = 0; i < kParameterCount; i++) { 3789 os << "," << i; 3790 } 3791 os << ");"; 3792 os << "}\n"; 3793 3794 std::string source = os.str(); 3795 InterpreterTester tester(handles.main_isolate(), source.c_str(), "*"); 3796 auto callable = tester.GetCallable<Handle<Object>>(); 3797 for (int i = 0; i < kParameterCount; i++) { 3798 Handle<Object> arg = handle(Smi::FromInt(i), isolate); 3799 Handle<Object> return_value = callable(arg).ToHandleChecked(); 3800 int expected = kBaseValue + i * (i + 1) / 2; 3801 Handle<Smi> actual = Handle<Smi>::cast(return_value); 3802 CHECK_EQ(actual->value(), expected); 3803 } 3804 } 3805 3806 TEST(InterpreterDoExpression) { 3807 bool old_flag = FLAG_harmony_do_expressions; 3808 FLAG_harmony_do_expressions = true; 3809 3810 HandleAndZoneScope handles; 3811 i::Isolate* isolate = handles.main_isolate(); 3812 Factory* factory = isolate->factory(); 3813 3814 std::pair<const char*, Handle<Object>> do_expr[] = { 3815 {"var a = do {}; return a;", factory->undefined_value()}, 3816 {"var a = do { var x = 100; }; return a;", factory->undefined_value()}, 3817 {"var a = do { var x = 100; }; return a;", factory->undefined_value()}, 3818 {"var a = do { var x = 100; x++; }; return a;", 3819 handle(Smi::FromInt(100), isolate)}, 3820 {"var i = 0; for (; i < 5;) { i = do { if (i == 3) { break; }; i + 1; }};" 3821 "return i;", 3822 handle(Smi::FromInt(3), isolate)}, 3823 }; 3824 3825 for (size_t i = 0; i < arraysize(do_expr); i++) { 3826 std::string source(InterpreterTester::SourceForBody(do_expr[i].first)); 3827 InterpreterTester tester(handles.main_isolate(), source.c_str()); 3828 auto callable = tester.GetCallable<>(); 3829 3830 Handle<i::Object> return_value = callable().ToHandleChecked(); 3831 CHECK(return_value->SameValue(*do_expr[i].second)); 3832 } 3833 3834 FLAG_harmony_do_expressions = old_flag; 3835 } 3836 3837 TEST(InterpreterWithStatement) { 3838 HandleAndZoneScope handles; 3839 i::Isolate* isolate = handles.main_isolate(); 3840 3841 std::pair<const char*, Handle<Object>> with_stmt[] = { 3842 {"with({x:42}) return x;", handle(Smi::FromInt(42), isolate)}, 3843 {"with({}) { var y = 10; return y;}", handle(Smi::FromInt(10), isolate)}, 3844 {"var y = {x:42};" 3845 " function inner() {" 3846 " var x = 20;" 3847 " with(y) return x;" 3848 "}" 3849 "return inner();", 3850 handle(Smi::FromInt(42), isolate)}, 3851 {"var y = {x:42};" 3852 " function inner(o) {" 3853 " var x = 20;" 3854 " with(o) return x;" 3855 "}" 3856 "return inner(y);", 3857 handle(Smi::FromInt(42), isolate)}, 3858 }; 3859 3860 for (size_t i = 0; i < arraysize(with_stmt); i++) { 3861 std::string source(InterpreterTester::SourceForBody(with_stmt[i].first)); 3862 InterpreterTester tester(handles.main_isolate(), source.c_str()); 3863 auto callable = tester.GetCallable<>(); 3864 3865 Handle<i::Object> return_value = callable().ToHandleChecked(); 3866 CHECK(return_value->SameValue(*with_stmt[i].second)); 3867 } 3868 } 3869 3870 TEST(InterpreterClassLiterals) { 3871 HandleAndZoneScope handles; 3872 i::Isolate* isolate = handles.main_isolate(); 3873 std::pair<const char*, Handle<Object>> examples[] = { 3874 {"class C {\n" 3875 " constructor(x) { this.x_ = x; }\n" 3876 " method() { return this.x_; }\n" 3877 "}\n" 3878 "return new C(99).method();", 3879 handle(Smi::FromInt(99), isolate)}, 3880 {"class C {\n" 3881 " constructor(x) { this.x_ = x; }\n" 3882 " static static_method(x) { return x; }\n" 3883 "}\n" 3884 "return C.static_method(101);", 3885 handle(Smi::FromInt(101), isolate)}, 3886 {"class C {\n" 3887 " get x() { return 102; }\n" 3888 "}\n" 3889 "return new C().x", 3890 handle(Smi::FromInt(102), isolate)}, 3891 {"class C {\n" 3892 " static get x() { return 103; }\n" 3893 "}\n" 3894 "return C.x", 3895 handle(Smi::FromInt(103), isolate)}, 3896 {"class C {\n" 3897 " constructor() { this.x_ = 0; }" 3898 " set x(value) { this.x_ = value; }\n" 3899 " get x() { return this.x_; }\n" 3900 "}\n" 3901 "var c = new C();" 3902 "c.x = 104;" 3903 "return c.x;", 3904 handle(Smi::FromInt(104), isolate)}, 3905 {"var x = 0;" 3906 "class C {\n" 3907 " static set x(value) { x = value; }\n" 3908 " static get x() { return x; }\n" 3909 "}\n" 3910 "C.x = 105;" 3911 "return C.x;", 3912 handle(Smi::FromInt(105), isolate)}, 3913 {"var method = 'f';" 3914 "class C {\n" 3915 " [method]() { return 106; }\n" 3916 "}\n" 3917 "return new C().f();", 3918 handle(Smi::FromInt(106), isolate)}, 3919 }; 3920 3921 for (size_t i = 0; i < arraysize(examples); ++i) { 3922 std::string source(InterpreterTester::SourceForBody(examples[i].first)); 3923 InterpreterTester tester(handles.main_isolate(), source.c_str(), "*"); 3924 auto callable = tester.GetCallable<>(); 3925 3926 Handle<i::Object> return_value = callable().ToHandleChecked(); 3927 CHECK(return_value->SameValue(*examples[i].second)); 3928 } 3929 } 3930 3931 TEST(InterpreterClassAndSuperClass) { 3932 HandleAndZoneScope handles; 3933 i::Isolate* isolate = handles.main_isolate(); 3934 std::pair<const char*, Handle<Object>> examples[] = { 3935 {"class A {\n" 3936 " constructor(x) { this.x_ = x; }\n" 3937 " method() { return this.x_; }\n" 3938 "}\n" 3939 "class B extends A {\n" 3940 " constructor(x, y) { super(x); this.y_ = y; }\n" 3941 " method() { return super.method() + 1; }\n" 3942 "}\n" 3943 "return new B(998, 0).method();\n", 3944 handle(Smi::FromInt(999), isolate)}, 3945 {"class A {\n" 3946 " constructor() { this.x_ = 2; this.y_ = 3; }\n" 3947 "}\n" 3948 "class B extends A {\n" 3949 " constructor() { super(); }" 3950 " method() { this.x_++; this.y_++; return this.x_ + this.y_; }\n" 3951 "}\n" 3952 "return new B().method();\n", 3953 handle(Smi::FromInt(7), isolate)}, 3954 {"var calls = 0;\n" 3955 "class B {}\n" 3956 "B.prototype.x = 42;\n" 3957 "class C extends B {\n" 3958 " constructor() {\n" 3959 " super();\n" 3960 " calls++;\n" 3961 " }\n" 3962 "}\n" 3963 "new C;\n" 3964 "return calls;\n", 3965 handle(Smi::FromInt(1), isolate)}, 3966 {"class A {\n" 3967 " method() { return 1; }\n" 3968 " get x() { return 2; }\n" 3969 "}\n" 3970 "class B extends A {\n" 3971 " method() { return super.x === 2 ? super.method() : -1; }\n" 3972 "}\n" 3973 "return new B().method();\n", 3974 handle(Smi::FromInt(1), isolate)}, 3975 {"var object = { setY(v) { super.y = v; }};\n" 3976 "object.setY(10);\n" 3977 "return object.y;\n", 3978 handle(Smi::FromInt(10), isolate)}, 3979 }; 3980 3981 for (size_t i = 0; i < arraysize(examples); ++i) { 3982 std::string source(InterpreterTester::SourceForBody(examples[i].first)); 3983 InterpreterTester tester(handles.main_isolate(), source.c_str(), "*"); 3984 auto callable = tester.GetCallable<>(); 3985 Handle<i::Object> return_value = callable().ToHandleChecked(); 3986 CHECK(return_value->SameValue(*examples[i].second)); 3987 } 3988 } 3989 3990 TEST(InterpreterConstDeclaration) { 3991 HandleAndZoneScope handles; 3992 i::Isolate* isolate = handles.main_isolate(); 3993 i::Factory* factory = isolate->factory(); 3994 3995 std::pair<const char*, Handle<Object>> const_decl[] = { 3996 {"const x = 3; return x;", handle(Smi::FromInt(3), isolate)}, 3997 {"let x = 10; x = x + 20; return x;", handle(Smi::FromInt(30), isolate)}, 3998 {"let x = 10; x = 20; return x;", handle(Smi::FromInt(20), isolate)}, 3999 {"let x; x = 20; return x;", handle(Smi::FromInt(20), isolate)}, 4000 {"let x; return x;", factory->undefined_value()}, 4001 {"var x = 10; { let x = 30; } return x;", 4002 handle(Smi::FromInt(10), isolate)}, 4003 {"let x = 10; { let x = 20; } return x;", 4004 handle(Smi::FromInt(10), isolate)}, 4005 {"var x = 10; eval('let x = 20;'); return x;", 4006 handle(Smi::FromInt(10), isolate)}, 4007 {"var x = 10; eval('const x = 20;'); return x;", 4008 handle(Smi::FromInt(10), isolate)}, 4009 {"var x = 10; { const x = 20; } return x;", 4010 handle(Smi::FromInt(10), isolate)}, 4011 {"var x = 10; { const x = 20; return x;} return -1;", 4012 handle(Smi::FromInt(20), isolate)}, 4013 {"var a = 10;\n" 4014 "for (var i = 0; i < 10; ++i) {\n" 4015 " const x = i;\n" // const declarations are block scoped. 4016 " a = a + x;\n" 4017 "}\n" 4018 "return a;\n", 4019 handle(Smi::FromInt(55), isolate)}, 4020 }; 4021 4022 // Tests for sloppy mode. 4023 for (size_t i = 0; i < arraysize(const_decl); i++) { 4024 std::string source(InterpreterTester::SourceForBody(const_decl[i].first)); 4025 InterpreterTester tester(handles.main_isolate(), source.c_str()); 4026 auto callable = tester.GetCallable<>(); 4027 4028 Handle<i::Object> return_value = callable().ToHandleChecked(); 4029 CHECK(return_value->SameValue(*const_decl[i].second)); 4030 } 4031 4032 // Tests for strict mode. 4033 for (size_t i = 0; i < arraysize(const_decl); i++) { 4034 std::string strict_body = 4035 "'use strict'; " + std::string(const_decl[i].first); 4036 std::string source(InterpreterTester::SourceForBody(strict_body.c_str())); 4037 InterpreterTester tester(handles.main_isolate(), source.c_str()); 4038 auto callable = tester.GetCallable<>(); 4039 4040 Handle<i::Object> return_value = callable().ToHandleChecked(); 4041 CHECK(return_value->SameValue(*const_decl[i].second)); 4042 } 4043 } 4044 4045 TEST(InterpreterConstDeclarationLookupSlots) { 4046 HandleAndZoneScope handles; 4047 i::Isolate* isolate = handles.main_isolate(); 4048 i::Factory* factory = isolate->factory(); 4049 4050 std::pair<const char*, Handle<Object>> const_decl[] = { 4051 {"const x = 3; function f1() {return x;}; return x;", 4052 handle(Smi::FromInt(3), isolate)}, 4053 {"let x = 10; x = x + 20; function f1() {return x;}; return x;", 4054 handle(Smi::FromInt(30), isolate)}, 4055 {"let x; x = 20; function f1() {return x;}; return x;", 4056 handle(Smi::FromInt(20), isolate)}, 4057 {"let x; function f1() {return x;}; return x;", 4058 factory->undefined_value()}, 4059 }; 4060 4061 // Tests for sloppy mode. 4062 for (size_t i = 0; i < arraysize(const_decl); i++) { 4063 std::string source(InterpreterTester::SourceForBody(const_decl[i].first)); 4064 InterpreterTester tester(handles.main_isolate(), source.c_str()); 4065 auto callable = tester.GetCallable<>(); 4066 4067 Handle<i::Object> return_value = callable().ToHandleChecked(); 4068 CHECK(return_value->SameValue(*const_decl[i].second)); 4069 } 4070 4071 // Tests for strict mode. 4072 for (size_t i = 0; i < arraysize(const_decl); i++) { 4073 std::string strict_body = 4074 "'use strict'; " + std::string(const_decl[i].first); 4075 std::string source(InterpreterTester::SourceForBody(strict_body.c_str())); 4076 InterpreterTester tester(handles.main_isolate(), source.c_str()); 4077 auto callable = tester.GetCallable<>(); 4078 4079 Handle<i::Object> return_value = callable().ToHandleChecked(); 4080 CHECK(return_value->SameValue(*const_decl[i].second)); 4081 } 4082 } 4083 4084 TEST(InterpreterConstInLookupContextChain) { 4085 HandleAndZoneScope handles; 4086 i::Isolate* isolate = handles.main_isolate(); 4087 4088 const char* prologue = 4089 "function OuterMost() {\n" 4090 " const outerConst = 10;\n" 4091 " let outerLet = 20;\n" 4092 " function Outer() {\n" 4093 " function Inner() {\n" 4094 " this.innerFunc = function() { "; 4095 const char* epilogue = 4096 " }\n" 4097 " }\n" 4098 " this.getInnerFunc =" 4099 " function() {return new Inner().innerFunc;}\n" 4100 " }\n" 4101 " this.getOuterFunc =" 4102 " function() {return new Outer().getInnerFunc();}" 4103 "}\n" 4104 "var f = new OuterMost().getOuterFunc();\n" 4105 "f();\n"; 4106 std::pair<const char*, Handle<Object>> const_decl[] = { 4107 {"return outerConst;", handle(Smi::FromInt(10), isolate)}, 4108 {"return outerLet;", handle(Smi::FromInt(20), isolate)}, 4109 {"outerLet = 30; return outerLet;", handle(Smi::FromInt(30), isolate)}, 4110 {"var outerLet = 40; return outerLet;", 4111 handle(Smi::FromInt(40), isolate)}, 4112 {"var outerConst = 50; return outerConst;", 4113 handle(Smi::FromInt(50), isolate)}, 4114 {"try { outerConst = 30 } catch(e) { return -1; }", 4115 handle(Smi::FromInt(-1), isolate)}}; 4116 4117 for (size_t i = 0; i < arraysize(const_decl); i++) { 4118 std::string script = std::string(prologue) + 4119 std::string(const_decl[i].first) + 4120 std::string(epilogue); 4121 InterpreterTester tester(handles.main_isolate(), script.c_str(), "*"); 4122 auto callable = tester.GetCallable<>(); 4123 4124 Handle<i::Object> return_value = callable().ToHandleChecked(); 4125 CHECK(return_value->SameValue(*const_decl[i].second)); 4126 } 4127 } 4128 4129 TEST(InterpreterIllegalConstDeclaration) { 4130 HandleAndZoneScope handles; 4131 4132 std::pair<const char*, const char*> const_decl[] = { 4133 {"const x = x = 10 + 3; return x;", 4134 "Uncaught ReferenceError: x is not defined"}, 4135 {"const x = 10; x = 20; return x;", 4136 "Uncaught TypeError: Assignment to constant variable."}, 4137 {"const x = 10; { x = 20; } return x;", 4138 "Uncaught TypeError: Assignment to constant variable."}, 4139 {"const x = 10; eval('x = 20;'); return x;", 4140 "Uncaught TypeError: Assignment to constant variable."}, 4141 {"let x = x + 10; return x;", 4142 "Uncaught ReferenceError: x is not defined"}, 4143 {"'use strict'; (function f1() { f1 = 123; })() ", 4144 "Uncaught TypeError: Assignment to constant variable."}, 4145 }; 4146 4147 // Tests for sloppy mode. 4148 for (size_t i = 0; i < arraysize(const_decl); i++) { 4149 std::string source(InterpreterTester::SourceForBody(const_decl[i].first)); 4150 InterpreterTester tester(handles.main_isolate(), source.c_str()); 4151 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get(); 4152 v8::Local<v8::String> expected_string = v8_str(const_decl[i].second); 4153 CHECK( 4154 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string) 4155 .FromJust()); 4156 } 4157 4158 // Tests for strict mode. 4159 for (size_t i = 0; i < arraysize(const_decl); i++) { 4160 std::string strict_body = 4161 "'use strict'; " + std::string(const_decl[i].first); 4162 std::string source(InterpreterTester::SourceForBody(strict_body.c_str())); 4163 InterpreterTester tester(handles.main_isolate(), source.c_str()); 4164 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get(); 4165 v8::Local<v8::String> expected_string = v8_str(const_decl[i].second); 4166 CHECK( 4167 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string) 4168 .FromJust()); 4169 } 4170 } 4171 4172 TEST(InterpreterGenerators) { 4173 bool old_flag = FLAG_ignition_generators; 4174 FLAG_ignition_generators = true; 4175 4176 HandleAndZoneScope handles; 4177 i::Isolate* isolate = handles.main_isolate(); 4178 i::Factory* factory = isolate->factory(); 4179 4180 std::pair<const char*, Handle<Object>> tests[] = { 4181 {"function* f() { }; return f().next().value", 4182 factory->undefined_value()}, 4183 {"function* f() { yield 42 }; return f().next().value", 4184 factory->NewNumberFromInt(42)}, 4185 {"function* f() { for (let x of [42]) yield x}; return f().next().value", 4186 factory->NewNumberFromInt(42)}, 4187 }; 4188 4189 for (size_t i = 0; i < arraysize(tests); i++) { 4190 std::string source(InterpreterTester::SourceForBody(tests[i].first)); 4191 InterpreterTester tester(handles.main_isolate(), source.c_str()); 4192 auto callable = tester.GetCallable<>(); 4193 4194 Handle<i::Object> return_value = callable().ToHandleChecked(); 4195 CHECK(return_value->SameValue(*tests[i].second)); 4196 } 4197 4198 FLAG_ignition_generators = old_flag; 4199 } 4200 4201 } // namespace interpreter 4202 } // namespace internal 4203 } // namespace v8 4204