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