| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 using ::v8::Value; | 73 using ::v8::Value; |
| 74 | 74 |
| 75 | 75 |
| 76 static void ExpectString(const char* code, const char* expected) { | 76 static void ExpectString(const char* code, const char* expected) { |
| 77 Local<Value> result = CompileRun(code); | 77 Local<Value> result = CompileRun(code); |
| 78 CHECK(result->IsString()); | 78 CHECK(result->IsString()); |
| 79 String::AsciiValue ascii(result); | 79 String::AsciiValue ascii(result); |
| 80 CHECK_EQ(expected, *ascii); | 80 CHECK_EQ(expected, *ascii); |
| 81 } | 81 } |
| 82 | 82 |
| 83 static void ExpectInt32(const char* code, int expected) { |
| 84 Local<Value> result = CompileRun(code); |
| 85 CHECK(result->IsInt32()); |
| 86 CHECK_EQ(expected, result->Int32Value()); |
| 87 } |
| 83 | 88 |
| 84 static void ExpectBoolean(const char* code, bool expected) { | 89 static void ExpectBoolean(const char* code, bool expected) { |
| 85 Local<Value> result = CompileRun(code); | 90 Local<Value> result = CompileRun(code); |
| 86 CHECK(result->IsBoolean()); | 91 CHECK(result->IsBoolean()); |
| 87 CHECK_EQ(expected, result->BooleanValue()); | 92 CHECK_EQ(expected, result->BooleanValue()); |
| 88 } | 93 } |
| 89 | 94 |
| 90 | 95 |
| 91 static void ExpectTrue(const char* code) { | 96 static void ExpectTrue(const char* code) { |
| 92 ExpectBoolean(code, true); | 97 ExpectBoolean(code, true); |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 LocalContext env; | 391 LocalContext env; |
| 387 TestResource* resource = new TestResource(two_byte_source, &dispose_count); | 392 TestResource* resource = new TestResource(two_byte_source, &dispose_count); |
| 388 Local<String> source = String::NewExternal(resource); | 393 Local<String> source = String::NewExternal(resource); |
| 389 Local<Script> script = Script::Compile(source); | 394 Local<Script> script = Script::Compile(source); |
| 390 Local<Value> value = script->Run(); | 395 Local<Value> value = script->Run(); |
| 391 CHECK(value->IsNumber()); | 396 CHECK(value->IsNumber()); |
| 392 CHECK_EQ(7, value->Int32Value()); | 397 CHECK_EQ(7, value->Int32Value()); |
| 393 CHECK(source->IsExternal()); | 398 CHECK(source->IsExternal()); |
| 394 CHECK_EQ(resource, | 399 CHECK_EQ(resource, |
| 395 static_cast<TestResource*>(source->GetExternalStringResource())); | 400 static_cast<TestResource*>(source->GetExternalStringResource())); |
| 396 HEAP->CollectAllGarbage(false); | 401 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 397 CHECK_EQ(0, dispose_count); | 402 CHECK_EQ(0, dispose_count); |
| 398 } | 403 } |
| 399 v8::internal::Isolate::Current()->compilation_cache()->Clear(); | 404 v8::internal::Isolate::Current()->compilation_cache()->Clear(); |
| 400 HEAP->CollectAllGarbage(false); | 405 HEAP->CollectAllAvailableGarbage(); |
| 401 CHECK_EQ(1, dispose_count); | 406 CHECK_EQ(1, dispose_count); |
| 402 } | 407 } |
| 403 | 408 |
| 404 | 409 |
| 405 THREADED_TEST(ScriptUsingAsciiStringResource) { | 410 THREADED_TEST(ScriptUsingAsciiStringResource) { |
| 406 int dispose_count = 0; | 411 int dispose_count = 0; |
| 407 const char* c_source = "1 + 2 * 3"; | 412 const char* c_source = "1 + 2 * 3"; |
| 408 { | 413 { |
| 409 v8::HandleScope scope; | 414 v8::HandleScope scope; |
| 410 LocalContext env; | 415 LocalContext env; |
| 411 Local<String> source = | 416 Local<String> source = |
| 412 String::NewExternal(new TestAsciiResource(i::StrDup(c_source), | 417 String::NewExternal(new TestAsciiResource(i::StrDup(c_source), |
| 413 &dispose_count)); | 418 &dispose_count)); |
| 414 Local<Script> script = Script::Compile(source); | 419 Local<Script> script = Script::Compile(source); |
| 415 Local<Value> value = script->Run(); | 420 Local<Value> value = script->Run(); |
| 416 CHECK(value->IsNumber()); | 421 CHECK(value->IsNumber()); |
| 417 CHECK_EQ(7, value->Int32Value()); | 422 CHECK_EQ(7, value->Int32Value()); |
| 418 HEAP->CollectAllGarbage(false); | 423 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 419 CHECK_EQ(0, dispose_count); | 424 CHECK_EQ(0, dispose_count); |
| 420 } | 425 } |
| 421 i::Isolate::Current()->compilation_cache()->Clear(); | 426 i::Isolate::Current()->compilation_cache()->Clear(); |
| 422 HEAP->CollectAllGarbage(false); | 427 HEAP->CollectAllAvailableGarbage(); |
| 423 CHECK_EQ(1, dispose_count); | 428 CHECK_EQ(1, dispose_count); |
| 424 } | 429 } |
| 425 | 430 |
| 426 | 431 |
| 427 THREADED_TEST(ScriptMakingExternalString) { | 432 THREADED_TEST(ScriptMakingExternalString) { |
| 428 int dispose_count = 0; | 433 int dispose_count = 0; |
| 429 uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3"); | 434 uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3"); |
| 430 { | 435 { |
| 431 v8::HandleScope scope; | 436 v8::HandleScope scope; |
| 432 LocalContext env; | 437 LocalContext env; |
| 433 Local<String> source = String::New(two_byte_source); | 438 Local<String> source = String::New(two_byte_source); |
| 434 // Trigger GCs so that the newly allocated string moves to old gen. | 439 // Trigger GCs so that the newly allocated string moves to old gen. |
| 435 HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now | 440 HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now |
| 436 HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now | 441 HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now |
| 437 bool success = source->MakeExternal(new TestResource(two_byte_source, | 442 bool success = source->MakeExternal(new TestResource(two_byte_source, |
| 438 &dispose_count)); | 443 &dispose_count)); |
| 439 CHECK(success); | 444 CHECK(success); |
| 440 Local<Script> script = Script::Compile(source); | 445 Local<Script> script = Script::Compile(source); |
| 441 Local<Value> value = script->Run(); | 446 Local<Value> value = script->Run(); |
| 442 CHECK(value->IsNumber()); | 447 CHECK(value->IsNumber()); |
| 443 CHECK_EQ(7, value->Int32Value()); | 448 CHECK_EQ(7, value->Int32Value()); |
| 444 HEAP->CollectAllGarbage(false); | 449 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 445 CHECK_EQ(0, dispose_count); | 450 CHECK_EQ(0, dispose_count); |
| 446 } | 451 } |
| 447 i::Isolate::Current()->compilation_cache()->Clear(); | 452 i::Isolate::Current()->compilation_cache()->Clear(); |
| 448 HEAP->CollectAllGarbage(false); | 453 // TODO(1608): This should use kAbortIncrementalMarking. |
| 454 HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); |
| 449 CHECK_EQ(1, dispose_count); | 455 CHECK_EQ(1, dispose_count); |
| 450 } | 456 } |
| 451 | 457 |
| 452 | 458 |
| 453 THREADED_TEST(ScriptMakingExternalAsciiString) { | 459 THREADED_TEST(ScriptMakingExternalAsciiString) { |
| 454 int dispose_count = 0; | 460 int dispose_count = 0; |
| 455 const char* c_source = "1 + 2 * 3"; | 461 const char* c_source = "1 + 2 * 3"; |
| 456 { | 462 { |
| 457 v8::HandleScope scope; | 463 v8::HandleScope scope; |
| 458 LocalContext env; | 464 LocalContext env; |
| 459 Local<String> source = v8_str(c_source); | 465 Local<String> source = v8_str(c_source); |
| 460 // Trigger GCs so that the newly allocated string moves to old gen. | 466 // Trigger GCs so that the newly allocated string moves to old gen. |
| 461 HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now | 467 HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now |
| 462 HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now | 468 HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now |
| 463 bool success = source->MakeExternal( | 469 bool success = source->MakeExternal( |
| 464 new TestAsciiResource(i::StrDup(c_source), &dispose_count)); | 470 new TestAsciiResource(i::StrDup(c_source), &dispose_count)); |
| 465 CHECK(success); | 471 CHECK(success); |
| 466 Local<Script> script = Script::Compile(source); | 472 Local<Script> script = Script::Compile(source); |
| 467 Local<Value> value = script->Run(); | 473 Local<Value> value = script->Run(); |
| 468 CHECK(value->IsNumber()); | 474 CHECK(value->IsNumber()); |
| 469 CHECK_EQ(7, value->Int32Value()); | 475 CHECK_EQ(7, value->Int32Value()); |
| 470 HEAP->CollectAllGarbage(false); | 476 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 471 CHECK_EQ(0, dispose_count); | 477 CHECK_EQ(0, dispose_count); |
| 472 } | 478 } |
| 473 i::Isolate::Current()->compilation_cache()->Clear(); | 479 i::Isolate::Current()->compilation_cache()->Clear(); |
| 474 HEAP->CollectAllGarbage(false); | 480 // TODO(1608): This should use kAbortIncrementalMarking. |
| 481 HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); |
| 475 CHECK_EQ(1, dispose_count); | 482 CHECK_EQ(1, dispose_count); |
| 476 } | 483 } |
| 477 | 484 |
| 478 | 485 |
| 479 TEST(MakingExternalStringConditions) { | 486 TEST(MakingExternalStringConditions) { |
| 480 v8::HandleScope scope; | 487 v8::HandleScope scope; |
| 481 LocalContext env; | 488 LocalContext env; |
| 482 | 489 |
| 483 // Free some space in the new space so that we can check freshness. | 490 // Free some space in the new space so that we can check freshness. |
| 484 HEAP->CollectGarbage(i::NEW_SPACE); | 491 HEAP->CollectGarbage(i::NEW_SPACE); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 uint16_t* two_byte_string = AsciiToTwoByteString("test string"); | 572 uint16_t* two_byte_string = AsciiToTwoByteString("test string"); |
| 566 Local<String> string = | 573 Local<String> string = |
| 567 String::NewExternal(new TestResource(two_byte_string)); | 574 String::NewExternal(new TestResource(two_byte_string)); |
| 568 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); | 575 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); |
| 569 // Trigger GCs so that the newly allocated string moves to old gen. | 576 // Trigger GCs so that the newly allocated string moves to old gen. |
| 570 HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now | 577 HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now |
| 571 HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now | 578 HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now |
| 572 i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring); | 579 i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring); |
| 573 CHECK(isymbol->IsSymbol()); | 580 CHECK(isymbol->IsSymbol()); |
| 574 } | 581 } |
| 575 HEAP->CollectAllGarbage(false); | 582 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 576 HEAP->CollectAllGarbage(false); | 583 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 577 } | 584 } |
| 578 | 585 |
| 579 | 586 |
| 580 THREADED_TEST(UsingExternalAsciiString) { | 587 THREADED_TEST(UsingExternalAsciiString) { |
| 581 { | 588 { |
| 582 v8::HandleScope scope; | 589 v8::HandleScope scope; |
| 583 const char* one_byte_string = "test string"; | 590 const char* one_byte_string = "test string"; |
| 584 Local<String> string = String::NewExternal( | 591 Local<String> string = String::NewExternal( |
| 585 new TestAsciiResource(i::StrDup(one_byte_string))); | 592 new TestAsciiResource(i::StrDup(one_byte_string))); |
| 586 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); | 593 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); |
| 587 // Trigger GCs so that the newly allocated string moves to old gen. | 594 // Trigger GCs so that the newly allocated string moves to old gen. |
| 588 HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now | 595 HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now |
| 589 HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now | 596 HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now |
| 590 i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring); | 597 i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring); |
| 591 CHECK(isymbol->IsSymbol()); | 598 CHECK(isymbol->IsSymbol()); |
| 592 } | 599 } |
| 593 HEAP->CollectAllGarbage(false); | 600 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 594 HEAP->CollectAllGarbage(false); | 601 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 595 } | 602 } |
| 596 | 603 |
| 597 | 604 |
| 598 THREADED_TEST(ScavengeExternalString) { | 605 THREADED_TEST(ScavengeExternalString) { |
| 599 int dispose_count = 0; | 606 int dispose_count = 0; |
| 600 bool in_new_space = false; | 607 bool in_new_space = false; |
| 601 { | 608 { |
| 602 v8::HandleScope scope; | 609 v8::HandleScope scope; |
| 603 uint16_t* two_byte_string = AsciiToTwoByteString("test string"); | 610 uint16_t* two_byte_string = AsciiToTwoByteString("test string"); |
| 604 Local<String> string = | 611 Local<String> string = |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 TestAsciiResourceWithDisposeControl::dispose_calls = 0; | 672 TestAsciiResourceWithDisposeControl::dispose_calls = 0; |
| 666 TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false); | 673 TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false); |
| 667 { | 674 { |
| 668 v8::HandleScope scope; | 675 v8::HandleScope scope; |
| 669 LocalContext env; | 676 LocalContext env; |
| 670 Local<String> source = String::NewExternal(&res_stack); | 677 Local<String> source = String::NewExternal(&res_stack); |
| 671 Local<Script> script = Script::Compile(source); | 678 Local<Script> script = Script::Compile(source); |
| 672 Local<Value> value = script->Run(); | 679 Local<Value> value = script->Run(); |
| 673 CHECK(value->IsNumber()); | 680 CHECK(value->IsNumber()); |
| 674 CHECK_EQ(7, value->Int32Value()); | 681 CHECK_EQ(7, value->Int32Value()); |
| 675 HEAP->CollectAllGarbage(false); | 682 HEAP->CollectAllAvailableGarbage(); |
| 676 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count); | 683 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count); |
| 677 } | 684 } |
| 678 i::Isolate::Current()->compilation_cache()->Clear(); | 685 i::Isolate::Current()->compilation_cache()->Clear(); |
| 679 HEAP->CollectAllGarbage(false); | 686 HEAP->CollectAllAvailableGarbage(); |
| 680 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls); | 687 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls); |
| 681 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count); | 688 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count); |
| 682 | 689 |
| 683 // Use a heap allocated external string resource allocated object. | 690 // Use a heap allocated external string resource allocated object. |
| 684 TestAsciiResourceWithDisposeControl::dispose_count = 0; | 691 TestAsciiResourceWithDisposeControl::dispose_count = 0; |
| 685 TestAsciiResourceWithDisposeControl::dispose_calls = 0; | 692 TestAsciiResourceWithDisposeControl::dispose_calls = 0; |
| 686 TestAsciiResource* res_heap = | 693 TestAsciiResource* res_heap = |
| 687 new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true); | 694 new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true); |
| 688 { | 695 { |
| 689 v8::HandleScope scope; | 696 v8::HandleScope scope; |
| 690 LocalContext env; | 697 LocalContext env; |
| 691 Local<String> source = String::NewExternal(res_heap); | 698 Local<String> source = String::NewExternal(res_heap); |
| 692 Local<Script> script = Script::Compile(source); | 699 Local<Script> script = Script::Compile(source); |
| 693 Local<Value> value = script->Run(); | 700 Local<Value> value = script->Run(); |
| 694 CHECK(value->IsNumber()); | 701 CHECK(value->IsNumber()); |
| 695 CHECK_EQ(7, value->Int32Value()); | 702 CHECK_EQ(7, value->Int32Value()); |
| 696 HEAP->CollectAllGarbage(false); | 703 HEAP->CollectAllAvailableGarbage(); |
| 697 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count); | 704 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count); |
| 698 } | 705 } |
| 699 i::Isolate::Current()->compilation_cache()->Clear(); | 706 i::Isolate::Current()->compilation_cache()->Clear(); |
| 700 HEAP->CollectAllGarbage(false); | 707 HEAP->CollectAllAvailableGarbage(); |
| 701 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls); | 708 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls); |
| 702 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count); | 709 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count); |
| 703 } | 710 } |
| 704 | 711 |
| 705 | 712 |
| 706 THREADED_TEST(StringConcat) { | 713 THREADED_TEST(StringConcat) { |
| 707 { | 714 { |
| 708 v8::HandleScope scope; | 715 v8::HandleScope scope; |
| 709 LocalContext env; | 716 LocalContext env; |
| 710 const char* one_byte_string_1 = "function a_times_t"; | 717 const char* one_byte_string_1 = "function a_times_t"; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 737 source = String::Concat(source, right); | 744 source = String::Concat(source, right); |
| 738 right = String::NewExternal( | 745 right = String::NewExternal( |
| 739 new TestResource(AsciiToTwoByteString(two_byte_extern_2))); | 746 new TestResource(AsciiToTwoByteString(two_byte_extern_2))); |
| 740 source = String::Concat(source, right); | 747 source = String::Concat(source, right); |
| 741 Local<Script> script = Script::Compile(source); | 748 Local<Script> script = Script::Compile(source); |
| 742 Local<Value> value = script->Run(); | 749 Local<Value> value = script->Run(); |
| 743 CHECK(value->IsNumber()); | 750 CHECK(value->IsNumber()); |
| 744 CHECK_EQ(68, value->Int32Value()); | 751 CHECK_EQ(68, value->Int32Value()); |
| 745 } | 752 } |
| 746 i::Isolate::Current()->compilation_cache()->Clear(); | 753 i::Isolate::Current()->compilation_cache()->Clear(); |
| 747 HEAP->CollectAllGarbage(false); | 754 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 748 HEAP->CollectAllGarbage(false); | 755 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 749 } | 756 } |
| 750 | 757 |
| 751 | 758 |
| 752 THREADED_TEST(GlobalProperties) { | 759 THREADED_TEST(GlobalProperties) { |
| 753 v8::HandleScope scope; | 760 v8::HandleScope scope; |
| 754 LocalContext env; | 761 LocalContext env; |
| 755 v8::Handle<v8::Object> global = env->Global(); | 762 v8::Handle<v8::Object> global = env->Global(); |
| 756 global->Set(v8_str("pi"), v8_num(3.1415926)); | 763 global->Set(v8_str("pi"), v8_num(3.1415926)); |
| 757 Local<Value> pi = global->Get(v8_str("pi")); | 764 Local<Value> pi = global->Get(v8_str("pi")); |
| 758 CHECK_EQ(3.1415926, pi->NumberValue()); | 765 CHECK_EQ(3.1415926, pi->NumberValue()); |
| (...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1287 | 1294 |
| 1288 | 1295 |
| 1289 static v8::Handle<Value> EchoNamedProperty(Local<String> name, | 1296 static v8::Handle<Value> EchoNamedProperty(Local<String> name, |
| 1290 const AccessorInfo& info) { | 1297 const AccessorInfo& info) { |
| 1291 ApiTestFuzzer::Fuzz(); | 1298 ApiTestFuzzer::Fuzz(); |
| 1292 CHECK_EQ(v8_str("data"), info.Data()); | 1299 CHECK_EQ(v8_str("data"), info.Data()); |
| 1293 echo_named_call_count++; | 1300 echo_named_call_count++; |
| 1294 return name; | 1301 return name; |
| 1295 } | 1302 } |
| 1296 | 1303 |
| 1304 // Helper functions for Interceptor/Accessor interaction tests |
| 1305 |
| 1306 Handle<Value> SimpleAccessorGetter(Local<String> name, |
| 1307 const AccessorInfo& info) { |
| 1308 Handle<Object> self = info.This(); |
| 1309 return self->Get(String::Concat(v8_str("accessor_"), name)); |
| 1310 } |
| 1311 |
| 1312 void SimpleAccessorSetter(Local<String> name, Local<Value> value, |
| 1313 const AccessorInfo& info) { |
| 1314 Handle<Object> self = info.This(); |
| 1315 self->Set(String::Concat(v8_str("accessor_"), name), value); |
| 1316 } |
| 1317 |
| 1318 Handle<Value> EmptyInterceptorGetter(Local<String> name, |
| 1319 const AccessorInfo& info) { |
| 1320 return Handle<Value>(); |
| 1321 } |
| 1322 |
| 1323 Handle<Value> EmptyInterceptorSetter(Local<String> name, |
| 1324 Local<Value> value, |
| 1325 const AccessorInfo& info) { |
| 1326 return Handle<Value>(); |
| 1327 } |
| 1328 |
| 1329 Handle<Value> InterceptorGetter(Local<String> name, |
| 1330 const AccessorInfo& info) { |
| 1331 // Intercept names that start with 'interceptor_'. |
| 1332 String::AsciiValue ascii(name); |
| 1333 char* name_str = *ascii; |
| 1334 char prefix[] = "interceptor_"; |
| 1335 int i; |
| 1336 for (i = 0; name_str[i] && prefix[i]; ++i) { |
| 1337 if (name_str[i] != prefix[i]) return Handle<Value>(); |
| 1338 } |
| 1339 Handle<Object> self = info.This(); |
| 1340 return self->GetHiddenValue(v8_str(name_str + i)); |
| 1341 } |
| 1342 |
| 1343 Handle<Value> InterceptorSetter(Local<String> name, |
| 1344 Local<Value> value, |
| 1345 const AccessorInfo& info) { |
| 1346 // Intercept accesses that set certain integer values. |
| 1347 if (value->IsInt32() && value->Int32Value() < 10000) { |
| 1348 Handle<Object> self = info.This(); |
| 1349 self->SetHiddenValue(name, value); |
| 1350 return value; |
| 1351 } |
| 1352 return Handle<Value>(); |
| 1353 } |
| 1354 |
| 1355 void AddAccessor(Handle<FunctionTemplate> templ, |
| 1356 Handle<String> name, |
| 1357 v8::AccessorGetter getter, |
| 1358 v8::AccessorSetter setter) { |
| 1359 templ->PrototypeTemplate()->SetAccessor(name, getter, setter); |
| 1360 } |
| 1361 |
| 1362 void AddInterceptor(Handle<FunctionTemplate> templ, |
| 1363 v8::NamedPropertyGetter getter, |
| 1364 v8::NamedPropertySetter setter) { |
| 1365 templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter); |
| 1366 } |
| 1367 |
| 1368 THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) { |
| 1369 v8::HandleScope scope; |
| 1370 Handle<FunctionTemplate> parent = FunctionTemplate::New(); |
| 1371 Handle<FunctionTemplate> child = FunctionTemplate::New(); |
| 1372 child->Inherit(parent); |
| 1373 AddAccessor(parent, v8_str("age"), |
| 1374 SimpleAccessorGetter, SimpleAccessorSetter); |
| 1375 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter); |
| 1376 LocalContext env; |
| 1377 env->Global()->Set(v8_str("Child"), child->GetFunction()); |
| 1378 CompileRun("var child = new Child;" |
| 1379 "child.age = 10;"); |
| 1380 ExpectBoolean("child.hasOwnProperty('age')", false); |
| 1381 ExpectInt32("child.age", 10); |
| 1382 ExpectInt32("child.accessor_age", 10); |
| 1383 } |
| 1384 |
| 1385 THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) { |
| 1386 v8::HandleScope scope; |
| 1387 Handle<FunctionTemplate> parent = FunctionTemplate::New(); |
| 1388 Handle<FunctionTemplate> child = FunctionTemplate::New(); |
| 1389 child->Inherit(parent); |
| 1390 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter); |
| 1391 LocalContext env; |
| 1392 env->Global()->Set(v8_str("Child"), child->GetFunction()); |
| 1393 CompileRun("var child = new Child;" |
| 1394 "var parent = child.__proto__;" |
| 1395 "Object.defineProperty(parent, 'age', " |
| 1396 " {get: function(){ return this.accessor_age; }, " |
| 1397 " set: function(v){ this.accessor_age = v; }, " |
| 1398 " enumerable: true, configurable: true});" |
| 1399 "child.age = 10;"); |
| 1400 ExpectBoolean("child.hasOwnProperty('age')", false); |
| 1401 ExpectInt32("child.age", 10); |
| 1402 ExpectInt32("child.accessor_age", 10); |
| 1403 } |
| 1404 |
| 1405 THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) { |
| 1406 v8::HandleScope scope; |
| 1407 Handle<FunctionTemplate> parent = FunctionTemplate::New(); |
| 1408 Handle<FunctionTemplate> child = FunctionTemplate::New(); |
| 1409 child->Inherit(parent); |
| 1410 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter); |
| 1411 LocalContext env; |
| 1412 env->Global()->Set(v8_str("Child"), child->GetFunction()); |
| 1413 CompileRun("var child = new Child;" |
| 1414 "var parent = child.__proto__;" |
| 1415 "parent.name = 'Alice';"); |
| 1416 ExpectBoolean("child.hasOwnProperty('name')", false); |
| 1417 ExpectString("child.name", "Alice"); |
| 1418 CompileRun("child.name = 'Bob';"); |
| 1419 ExpectString("child.name", "Bob"); |
| 1420 ExpectBoolean("child.hasOwnProperty('name')", true); |
| 1421 ExpectString("parent.name", "Alice"); |
| 1422 } |
| 1423 |
| 1424 THREADED_TEST(SwitchFromInterceptorToAccessor) { |
| 1425 v8::HandleScope scope; |
| 1426 Handle<FunctionTemplate> parent = FunctionTemplate::New(); |
| 1427 Handle<FunctionTemplate> child = FunctionTemplate::New(); |
| 1428 child->Inherit(parent); |
| 1429 AddAccessor(parent, v8_str("age"), |
| 1430 SimpleAccessorGetter, SimpleAccessorSetter); |
| 1431 AddInterceptor(child, InterceptorGetter, InterceptorSetter); |
| 1432 LocalContext env; |
| 1433 env->Global()->Set(v8_str("Child"), child->GetFunction()); |
| 1434 CompileRun("var child = new Child;" |
| 1435 "function setAge(i){ child.age = i; };" |
| 1436 "for(var i = 0; i <= 10000; i++) setAge(i);"); |
| 1437 // All i < 10000 go to the interceptor. |
| 1438 ExpectInt32("child.interceptor_age", 9999); |
| 1439 // The last i goes to the accessor. |
| 1440 ExpectInt32("child.accessor_age", 10000); |
| 1441 } |
| 1442 |
| 1443 THREADED_TEST(SwitchFromAccessorToInterceptor) { |
| 1444 v8::HandleScope scope; |
| 1445 Handle<FunctionTemplate> parent = FunctionTemplate::New(); |
| 1446 Handle<FunctionTemplate> child = FunctionTemplate::New(); |
| 1447 child->Inherit(parent); |
| 1448 AddAccessor(parent, v8_str("age"), |
| 1449 SimpleAccessorGetter, SimpleAccessorSetter); |
| 1450 AddInterceptor(child, InterceptorGetter, InterceptorSetter); |
| 1451 LocalContext env; |
| 1452 env->Global()->Set(v8_str("Child"), child->GetFunction()); |
| 1453 CompileRun("var child = new Child;" |
| 1454 "function setAge(i){ child.age = i; };" |
| 1455 "for(var i = 20000; i >= 9999; i--) setAge(i);"); |
| 1456 // All i >= 10000 go to the accessor. |
| 1457 ExpectInt32("child.accessor_age", 10000); |
| 1458 // The last i goes to the interceptor. |
| 1459 ExpectInt32("child.interceptor_age", 9999); |
| 1460 } |
| 1461 |
| 1462 THREADED_TEST(SwitchFromInterceptorToProperty) { |
| 1463 v8::HandleScope scope; |
| 1464 Handle<FunctionTemplate> parent = FunctionTemplate::New(); |
| 1465 Handle<FunctionTemplate> child = FunctionTemplate::New(); |
| 1466 child->Inherit(parent); |
| 1467 AddInterceptor(child, InterceptorGetter, InterceptorSetter); |
| 1468 LocalContext env; |
| 1469 env->Global()->Set(v8_str("Child"), child->GetFunction()); |
| 1470 CompileRun("var child = new Child;" |
| 1471 "function setAge(i){ child.age = i; };" |
| 1472 "for(var i = 0; i <= 10000; i++) setAge(i);"); |
| 1473 // All i < 10000 go to the interceptor. |
| 1474 ExpectInt32("child.interceptor_age", 9999); |
| 1475 // The last i goes to child's own property. |
| 1476 ExpectInt32("child.age", 10000); |
| 1477 } |
| 1478 |
| 1479 THREADED_TEST(SwitchFromPropertyToInterceptor) { |
| 1480 v8::HandleScope scope; |
| 1481 Handle<FunctionTemplate> parent = FunctionTemplate::New(); |
| 1482 Handle<FunctionTemplate> child = FunctionTemplate::New(); |
| 1483 child->Inherit(parent); |
| 1484 AddInterceptor(child, InterceptorGetter, InterceptorSetter); |
| 1485 LocalContext env; |
| 1486 env->Global()->Set(v8_str("Child"), child->GetFunction()); |
| 1487 CompileRun("var child = new Child;" |
| 1488 "function setAge(i){ child.age = i; };" |
| 1489 "for(var i = 20000; i >= 9999; i--) setAge(i);"); |
| 1490 // All i >= 10000 go to child's own property. |
| 1491 ExpectInt32("child.age", 10000); |
| 1492 // The last i goes to the interceptor. |
| 1493 ExpectInt32("child.interceptor_age", 9999); |
| 1494 } |
| 1297 | 1495 |
| 1298 THREADED_TEST(NamedPropertyHandlerGetter) { | 1496 THREADED_TEST(NamedPropertyHandlerGetter) { |
| 1299 echo_named_call_count = 0; | 1497 echo_named_call_count = 0; |
| 1300 v8::HandleScope scope; | 1498 v8::HandleScope scope; |
| 1301 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(); | 1499 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(); |
| 1302 templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty, | 1500 templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty, |
| 1303 0, 0, 0, 0, | 1501 0, 0, 0, 0, |
| 1304 v8_str("data")); | 1502 v8_str("data")); |
| 1305 LocalContext env; | 1503 LocalContext env; |
| 1306 env->Global()->Set(v8_str("obj"), | 1504 env->Global()->Set(v8_str("obj"), |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1659 | 1857 |
| 1660 char* data = new char[100]; | 1858 char* data = new char[100]; |
| 1661 | 1859 |
| 1662 void* aligned = data; | 1860 void* aligned = data; |
| 1663 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(aligned) & 0x1)); | 1861 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(aligned) & 0x1)); |
| 1664 void* unaligned = data + 1; | 1862 void* unaligned = data + 1; |
| 1665 CHECK_EQ(1, static_cast<int>(reinterpret_cast<uintptr_t>(unaligned) & 0x1)); | 1863 CHECK_EQ(1, static_cast<int>(reinterpret_cast<uintptr_t>(unaligned) & 0x1)); |
| 1666 | 1864 |
| 1667 // Check reading and writing aligned pointers. | 1865 // Check reading and writing aligned pointers. |
| 1668 obj->SetPointerInInternalField(0, aligned); | 1866 obj->SetPointerInInternalField(0, aligned); |
| 1669 HEAP->CollectAllGarbage(false); | 1867 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 1670 CHECK_EQ(aligned, obj->GetPointerFromInternalField(0)); | 1868 CHECK_EQ(aligned, obj->GetPointerFromInternalField(0)); |
| 1671 | 1869 |
| 1672 // Check reading and writing unaligned pointers. | 1870 // Check reading and writing unaligned pointers. |
| 1673 obj->SetPointerInInternalField(0, unaligned); | 1871 obj->SetPointerInInternalField(0, unaligned); |
| 1674 HEAP->CollectAllGarbage(false); | 1872 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 1675 CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0)); | 1873 CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0)); |
| 1676 | 1874 |
| 1677 delete[] data; | 1875 delete[] data; |
| 1678 } | 1876 } |
| 1679 | 1877 |
| 1680 | 1878 |
| 1681 THREADED_TEST(InternalFieldsNativePointersAndExternal) { | 1879 THREADED_TEST(InternalFieldsNativePointersAndExternal) { |
| 1682 v8::HandleScope scope; | 1880 v8::HandleScope scope; |
| 1683 LocalContext env; | 1881 LocalContext env; |
| 1684 | 1882 |
| 1685 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(); | 1883 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(); |
| 1686 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate(); | 1884 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate(); |
| 1687 instance_templ->SetInternalFieldCount(1); | 1885 instance_templ->SetInternalFieldCount(1); |
| 1688 Local<v8::Object> obj = templ->GetFunction()->NewInstance(); | 1886 Local<v8::Object> obj = templ->GetFunction()->NewInstance(); |
| 1689 CHECK_EQ(1, obj->InternalFieldCount()); | 1887 CHECK_EQ(1, obj->InternalFieldCount()); |
| 1690 CHECK(obj->GetPointerFromInternalField(0) == NULL); | 1888 CHECK(obj->GetPointerFromInternalField(0) == NULL); |
| 1691 | 1889 |
| 1692 char* data = new char[100]; | 1890 char* data = new char[100]; |
| 1693 | 1891 |
| 1694 void* aligned = data; | 1892 void* aligned = data; |
| 1695 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(aligned) & 0x1)); | 1893 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(aligned) & 0x1)); |
| 1696 void* unaligned = data + 1; | 1894 void* unaligned = data + 1; |
| 1697 CHECK_EQ(1, static_cast<int>(reinterpret_cast<uintptr_t>(unaligned) & 0x1)); | 1895 CHECK_EQ(1, static_cast<int>(reinterpret_cast<uintptr_t>(unaligned) & 0x1)); |
| 1698 | 1896 |
| 1699 obj->SetPointerInInternalField(0, aligned); | 1897 obj->SetPointerInInternalField(0, aligned); |
| 1700 HEAP->CollectAllGarbage(false); | 1898 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 1701 CHECK_EQ(aligned, v8::External::Unwrap(obj->GetInternalField(0))); | 1899 CHECK_EQ(aligned, v8::External::Unwrap(obj->GetInternalField(0))); |
| 1702 | 1900 |
| 1703 obj->SetPointerInInternalField(0, unaligned); | 1901 obj->SetPointerInInternalField(0, unaligned); |
| 1704 HEAP->CollectAllGarbage(false); | 1902 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 1705 CHECK_EQ(unaligned, v8::External::Unwrap(obj->GetInternalField(0))); | 1903 CHECK_EQ(unaligned, v8::External::Unwrap(obj->GetInternalField(0))); |
| 1706 | 1904 |
| 1707 obj->SetInternalField(0, v8::External::Wrap(aligned)); | 1905 obj->SetInternalField(0, v8::External::Wrap(aligned)); |
| 1708 HEAP->CollectAllGarbage(false); | 1906 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 1709 CHECK_EQ(aligned, obj->GetPointerFromInternalField(0)); | 1907 CHECK_EQ(aligned, obj->GetPointerFromInternalField(0)); |
| 1710 | 1908 |
| 1711 obj->SetInternalField(0, v8::External::Wrap(unaligned)); | 1909 obj->SetInternalField(0, v8::External::Wrap(unaligned)); |
| 1712 HEAP->CollectAllGarbage(false); | 1910 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 1713 CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0)); | 1911 CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0)); |
| 1714 | 1912 |
| 1715 delete[] data; | 1913 delete[] data; |
| 1716 } | 1914 } |
| 1717 | 1915 |
| 1718 | 1916 |
| 1719 THREADED_TEST(IdentityHash) { | 1917 THREADED_TEST(IdentityHash) { |
| 1720 v8::HandleScope scope; | 1918 v8::HandleScope scope; |
| 1721 LocalContext env; | 1919 LocalContext env; |
| 1722 | 1920 |
| 1723 // Ensure that the test starts with an fresh heap to test whether the hash | 1921 // Ensure that the test starts with an fresh heap to test whether the hash |
| 1724 // code is based on the address. | 1922 // code is based on the address. |
| 1725 HEAP->CollectAllGarbage(false); | 1923 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 1726 Local<v8::Object> obj = v8::Object::New(); | 1924 Local<v8::Object> obj = v8::Object::New(); |
| 1727 int hash = obj->GetIdentityHash(); | 1925 int hash = obj->GetIdentityHash(); |
| 1728 int hash1 = obj->GetIdentityHash(); | 1926 int hash1 = obj->GetIdentityHash(); |
| 1729 CHECK_EQ(hash, hash1); | 1927 CHECK_EQ(hash, hash1); |
| 1730 int hash2 = v8::Object::New()->GetIdentityHash(); | 1928 int hash2 = v8::Object::New()->GetIdentityHash(); |
| 1731 // Since the identity hash is essentially a random number two consecutive | 1929 // Since the identity hash is essentially a random number two consecutive |
| 1732 // objects should not be assigned the same hash code. If the test below fails | 1930 // objects should not be assigned the same hash code. If the test below fails |
| 1733 // the random number generator should be evaluated. | 1931 // the random number generator should be evaluated. |
| 1734 CHECK_NE(hash, hash2); | 1932 CHECK_NE(hash, hash2); |
| 1735 HEAP->CollectAllGarbage(false); | 1933 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 1736 int hash3 = v8::Object::New()->GetIdentityHash(); | 1934 int hash3 = v8::Object::New()->GetIdentityHash(); |
| 1737 // Make sure that the identity hash is not based on the initial address of | 1935 // Make sure that the identity hash is not based on the initial address of |
| 1738 // the object alone. If the test below fails the random number generator | 1936 // the object alone. If the test below fails the random number generator |
| 1739 // should be evaluated. | 1937 // should be evaluated. |
| 1740 CHECK_NE(hash, hash3); | 1938 CHECK_NE(hash, hash3); |
| 1741 int hash4 = obj->GetIdentityHash(); | 1939 int hash4 = obj->GetIdentityHash(); |
| 1742 CHECK_EQ(hash, hash4); | 1940 CHECK_EQ(hash, hash4); |
| 1743 | 1941 |
| 1744 // Check identity hashes behaviour in the presence of JS accessors. | 1942 // Check identity hashes behaviour in the presence of JS accessors. |
| 1745 // Put a getter for 'v8::IdentityHash' on the Object's prototype: | 1943 // Put a getter for 'v8::IdentityHash' on the Object's prototype: |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1762 | 1960 |
| 1763 THREADED_TEST(HiddenProperties) { | 1961 THREADED_TEST(HiddenProperties) { |
| 1764 v8::HandleScope scope; | 1962 v8::HandleScope scope; |
| 1765 LocalContext env; | 1963 LocalContext env; |
| 1766 | 1964 |
| 1767 v8::Local<v8::Object> obj = v8::Object::New(); | 1965 v8::Local<v8::Object> obj = v8::Object::New(); |
| 1768 v8::Local<v8::String> key = v8_str("api-test::hidden-key"); | 1966 v8::Local<v8::String> key = v8_str("api-test::hidden-key"); |
| 1769 v8::Local<v8::String> empty = v8_str(""); | 1967 v8::Local<v8::String> empty = v8_str(""); |
| 1770 v8::Local<v8::String> prop_name = v8_str("prop_name"); | 1968 v8::Local<v8::String> prop_name = v8_str("prop_name"); |
| 1771 | 1969 |
| 1772 HEAP->CollectAllGarbage(false); | 1970 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 1773 | 1971 |
| 1774 // Make sure delete of a non-existent hidden value works | 1972 // Make sure delete of a non-existent hidden value works |
| 1775 CHECK(obj->DeleteHiddenValue(key)); | 1973 CHECK(obj->DeleteHiddenValue(key)); |
| 1776 | 1974 |
| 1777 CHECK(obj->SetHiddenValue(key, v8::Integer::New(1503))); | 1975 CHECK(obj->SetHiddenValue(key, v8::Integer::New(1503))); |
| 1778 CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value()); | 1976 CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value()); |
| 1779 CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002))); | 1977 CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002))); |
| 1780 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); | 1978 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); |
| 1781 | 1979 |
| 1782 HEAP->CollectAllGarbage(false); | 1980 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 1783 | 1981 |
| 1784 // Make sure we do not find the hidden property. | 1982 // Make sure we do not find the hidden property. |
| 1785 CHECK(!obj->Has(empty)); | 1983 CHECK(!obj->Has(empty)); |
| 1786 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); | 1984 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); |
| 1787 CHECK(obj->Get(empty)->IsUndefined()); | 1985 CHECK(obj->Get(empty)->IsUndefined()); |
| 1788 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); | 1986 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); |
| 1789 CHECK(obj->Set(empty, v8::Integer::New(2003))); | 1987 CHECK(obj->Set(empty, v8::Integer::New(2003))); |
| 1790 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); | 1988 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); |
| 1791 CHECK_EQ(2003, obj->Get(empty)->Int32Value()); | 1989 CHECK_EQ(2003, obj->Get(empty)->Int32Value()); |
| 1792 | 1990 |
| 1793 HEAP->CollectAllGarbage(false); | 1991 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 1794 | 1992 |
| 1795 // Add another property and delete it afterwards to force the object in | 1993 // Add another property and delete it afterwards to force the object in |
| 1796 // slow case. | 1994 // slow case. |
| 1797 CHECK(obj->Set(prop_name, v8::Integer::New(2008))); | 1995 CHECK(obj->Set(prop_name, v8::Integer::New(2008))); |
| 1798 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); | 1996 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); |
| 1799 CHECK_EQ(2008, obj->Get(prop_name)->Int32Value()); | 1997 CHECK_EQ(2008, obj->Get(prop_name)->Int32Value()); |
| 1800 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); | 1998 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); |
| 1801 CHECK(obj->Delete(prop_name)); | 1999 CHECK(obj->Delete(prop_name)); |
| 1802 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); | 2000 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value()); |
| 1803 | 2001 |
| 1804 HEAP->CollectAllGarbage(false); | 2002 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 1805 | 2003 |
| 1806 CHECK(obj->DeleteHiddenValue(key)); | 2004 CHECK(obj->DeleteHiddenValue(key)); |
| 1807 CHECK(obj->GetHiddenValue(key).IsEmpty()); | 2005 CHECK(obj->GetHiddenValue(key).IsEmpty()); |
| 1808 } | 2006 } |
| 1809 | 2007 |
| 1810 | 2008 |
| 1811 THREADED_TEST(Regress97784) { | 2009 THREADED_TEST(Regress97784) { |
| 1812 // Regression test for crbug.com/97784 | 2010 // Regression test for crbug.com/97784 |
| 1813 // Messing with the Object.prototype should not have effect on | 2011 // Messing with the Object.prototype should not have effect on |
| 1814 // hidden properties. | 2012 // hidden properties. |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1901 { | 2099 { |
| 1902 v8::HandleScope scope; | 2100 v8::HandleScope scope; |
| 1903 Local<String> str = v8_str("str"); | 2101 Local<String> str = v8_str("str"); |
| 1904 global = v8::Persistent<String>::New(str); | 2102 global = v8::Persistent<String>::New(str); |
| 1905 } | 2103 } |
| 1906 CHECK_EQ(global->Length(), 3); | 2104 CHECK_EQ(global->Length(), 3); |
| 1907 global.Dispose(); | 2105 global.Dispose(); |
| 1908 } | 2106 } |
| 1909 | 2107 |
| 1910 | 2108 |
| 1911 static int NumberOfWeakCalls = 0; | 2109 class WeakCallCounter { |
| 2110 public: |
| 2111 explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { } |
| 2112 int id() { return id_; } |
| 2113 void increment() { number_of_weak_calls_++; } |
| 2114 int NumberOfWeakCalls() { return number_of_weak_calls_; } |
| 2115 private: |
| 2116 int id_; |
| 2117 int number_of_weak_calls_; |
| 2118 }; |
| 2119 |
| 2120 |
| 1912 static void WeakPointerCallback(Persistent<Value> handle, void* id) { | 2121 static void WeakPointerCallback(Persistent<Value> handle, void* id) { |
| 1913 CHECK_EQ(reinterpret_cast<void*>(1234), id); | 2122 WeakCallCounter* counter = reinterpret_cast<WeakCallCounter*>(id); |
| 1914 NumberOfWeakCalls++; | 2123 CHECK_EQ(1234, counter->id()); |
| 2124 counter->increment(); |
| 1915 handle.Dispose(); | 2125 handle.Dispose(); |
| 1916 } | 2126 } |
| 1917 | 2127 |
| 2128 |
| 1918 THREADED_TEST(ApiObjectGroups) { | 2129 THREADED_TEST(ApiObjectGroups) { |
| 1919 HandleScope scope; | 2130 HandleScope scope; |
| 1920 LocalContext env; | 2131 LocalContext env; |
| 1921 | 2132 |
| 1922 NumberOfWeakCalls = 0; | |
| 1923 | |
| 1924 Persistent<Object> g1s1; | 2133 Persistent<Object> g1s1; |
| 1925 Persistent<Object> g1s2; | 2134 Persistent<Object> g1s2; |
| 1926 Persistent<Object> g1c1; | 2135 Persistent<Object> g1c1; |
| 1927 Persistent<Object> g2s1; | 2136 Persistent<Object> g2s1; |
| 1928 Persistent<Object> g2s2; | 2137 Persistent<Object> g2s2; |
| 1929 Persistent<Object> g2c1; | 2138 Persistent<Object> g2c1; |
| 1930 | 2139 |
| 2140 WeakCallCounter counter(1234); |
| 2141 |
| 1931 { | 2142 { |
| 1932 HandleScope scope; | 2143 HandleScope scope; |
| 1933 g1s1 = Persistent<Object>::New(Object::New()); | 2144 g1s1 = Persistent<Object>::New(Object::New()); |
| 1934 g1s2 = Persistent<Object>::New(Object::New()); | 2145 g1s2 = Persistent<Object>::New(Object::New()); |
| 1935 g1c1 = Persistent<Object>::New(Object::New()); | 2146 g1c1 = Persistent<Object>::New(Object::New()); |
| 1936 g1s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); | 2147 g1s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
| 1937 g1s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); | 2148 g1s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
| 1938 g1c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); | 2149 g1c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
| 1939 | 2150 |
| 1940 g2s1 = Persistent<Object>::New(Object::New()); | 2151 g2s1 = Persistent<Object>::New(Object::New()); |
| 1941 g2s2 = Persistent<Object>::New(Object::New()); | 2152 g2s2 = Persistent<Object>::New(Object::New()); |
| 1942 g2c1 = Persistent<Object>::New(Object::New()); | 2153 g2c1 = Persistent<Object>::New(Object::New()); |
| 1943 g2s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); | 2154 g2s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
| 1944 g2s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); | 2155 g2s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
| 1945 g2c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); | 2156 g2c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
| 1946 } | 2157 } |
| 1947 | 2158 |
| 1948 Persistent<Object> root = Persistent<Object>::New(g1s1); // make a root. | 2159 Persistent<Object> root = Persistent<Object>::New(g1s1); // make a root. |
| 1949 | 2160 |
| 1950 // Connect group 1 and 2, make a cycle. | 2161 // Connect group 1 and 2, make a cycle. |
| 1951 CHECK(g1s2->Set(0, g2s2)); | 2162 CHECK(g1s2->Set(0, g2s2)); |
| 1952 CHECK(g2s1->Set(0, g1s1)); | 2163 CHECK(g2s1->Set(0, g1s1)); |
| 1953 | 2164 |
| 1954 { | 2165 { |
| 1955 Persistent<Value> g1_objects[] = { g1s1, g1s2 }; | 2166 Persistent<Value> g1_objects[] = { g1s1, g1s2 }; |
| 1956 Persistent<Value> g1_children[] = { g1c1 }; | 2167 Persistent<Value> g1_children[] = { g1c1 }; |
| 1957 Persistent<Value> g2_objects[] = { g2s1, g2s2 }; | 2168 Persistent<Value> g2_objects[] = { g2s1, g2s2 }; |
| 1958 Persistent<Value> g2_children[] = { g2c1 }; | 2169 Persistent<Value> g2_children[] = { g2c1 }; |
| 1959 V8::AddObjectGroup(g1_objects, 2); | 2170 V8::AddObjectGroup(g1_objects, 2); |
| 1960 V8::AddImplicitReferences(g1s1, g1_children, 1); | 2171 V8::AddImplicitReferences(g1s1, g1_children, 1); |
| 1961 V8::AddObjectGroup(g2_objects, 2); | 2172 V8::AddObjectGroup(g2_objects, 2); |
| 1962 V8::AddImplicitReferences(g2s2, g2_children, 1); | 2173 V8::AddImplicitReferences(g2s2, g2_children, 1); |
| 1963 } | 2174 } |
| 1964 // Do a full GC | 2175 // Do a single full GC. Use kMakeHeapIterableMask to ensure that |
| 1965 HEAP->CollectGarbage(i::OLD_POINTER_SPACE); | 2176 // incremental garbage collection is stopped. |
| 2177 HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); |
| 1966 | 2178 |
| 1967 // All object should be alive. | 2179 // All object should be alive. |
| 1968 CHECK_EQ(0, NumberOfWeakCalls); | 2180 CHECK_EQ(0, counter.NumberOfWeakCalls()); |
| 1969 | 2181 |
| 1970 // Weaken the root. | 2182 // Weaken the root. |
| 1971 root.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); | 2183 root.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
| 1972 // But make children strong roots---all the objects (except for children) | 2184 // But make children strong roots---all the objects (except for children) |
| 1973 // should be collectable now. | 2185 // should be collectable now. |
| 1974 g1c1.ClearWeak(); | 2186 g1c1.ClearWeak(); |
| 1975 g2c1.ClearWeak(); | 2187 g2c1.ClearWeak(); |
| 1976 | 2188 |
| 1977 // Groups are deleted, rebuild groups. | 2189 // Groups are deleted, rebuild groups. |
| 1978 { | 2190 { |
| 1979 Persistent<Value> g1_objects[] = { g1s1, g1s2 }; | 2191 Persistent<Value> g1_objects[] = { g1s1, g1s2 }; |
| 1980 Persistent<Value> g1_children[] = { g1c1 }; | 2192 Persistent<Value> g1_children[] = { g1c1 }; |
| 1981 Persistent<Value> g2_objects[] = { g2s1, g2s2 }; | 2193 Persistent<Value> g2_objects[] = { g2s1, g2s2 }; |
| 1982 Persistent<Value> g2_children[] = { g2c1 }; | 2194 Persistent<Value> g2_children[] = { g2c1 }; |
| 1983 V8::AddObjectGroup(g1_objects, 2); | 2195 V8::AddObjectGroup(g1_objects, 2); |
| 1984 V8::AddImplicitReferences(g1s1, g1_children, 1); | 2196 V8::AddImplicitReferences(g1s1, g1_children, 1); |
| 1985 V8::AddObjectGroup(g2_objects, 2); | 2197 V8::AddObjectGroup(g2_objects, 2); |
| 1986 V8::AddImplicitReferences(g2s2, g2_children, 1); | 2198 V8::AddImplicitReferences(g2s2, g2_children, 1); |
| 1987 } | 2199 } |
| 1988 | 2200 |
| 1989 HEAP->CollectGarbage(i::OLD_POINTER_SPACE); | 2201 HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); |
| 1990 | 2202 |
| 1991 // All objects should be gone. 5 global handles in total. | 2203 // All objects should be gone. 5 global handles in total. |
| 1992 CHECK_EQ(5, NumberOfWeakCalls); | 2204 CHECK_EQ(5, counter.NumberOfWeakCalls()); |
| 1993 | 2205 |
| 1994 // And now make children weak again and collect them. | 2206 // And now make children weak again and collect them. |
| 1995 g1c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); | 2207 g1c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
| 1996 g2c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); | 2208 g2c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
| 1997 | 2209 |
| 1998 HEAP->CollectGarbage(i::OLD_POINTER_SPACE); | 2210 HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); |
| 1999 CHECK_EQ(7, NumberOfWeakCalls); | 2211 CHECK_EQ(7, counter.NumberOfWeakCalls()); |
| 2000 } | 2212 } |
| 2001 | 2213 |
| 2002 | 2214 |
| 2003 THREADED_TEST(ApiObjectGroupsCycle) { | 2215 THREADED_TEST(ApiObjectGroupsCycle) { |
| 2004 HandleScope scope; | 2216 HandleScope scope; |
| 2005 LocalContext env; | 2217 LocalContext env; |
| 2006 | 2218 |
| 2007 NumberOfWeakCalls = 0; | 2219 WeakCallCounter counter(1234); |
| 2008 | 2220 |
| 2009 Persistent<Object> g1s1; | 2221 Persistent<Object> g1s1; |
| 2010 Persistent<Object> g1s2; | 2222 Persistent<Object> g1s2; |
| 2011 Persistent<Object> g2s1; | 2223 Persistent<Object> g2s1; |
| 2012 Persistent<Object> g2s2; | 2224 Persistent<Object> g2s2; |
| 2013 Persistent<Object> g3s1; | 2225 Persistent<Object> g3s1; |
| 2014 Persistent<Object> g3s2; | 2226 Persistent<Object> g3s2; |
| 2015 | 2227 |
| 2016 { | 2228 { |
| 2017 HandleScope scope; | 2229 HandleScope scope; |
| 2018 g1s1 = Persistent<Object>::New(Object::New()); | 2230 g1s1 = Persistent<Object>::New(Object::New()); |
| 2019 g1s2 = Persistent<Object>::New(Object::New()); | 2231 g1s2 = Persistent<Object>::New(Object::New()); |
| 2020 g1s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); | 2232 g1s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
| 2021 g1s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); | 2233 g1s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
| 2022 | 2234 |
| 2023 g2s1 = Persistent<Object>::New(Object::New()); | 2235 g2s1 = Persistent<Object>::New(Object::New()); |
| 2024 g2s2 = Persistent<Object>::New(Object::New()); | 2236 g2s2 = Persistent<Object>::New(Object::New()); |
| 2025 g2s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); | 2237 g2s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
| 2026 g2s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); | 2238 g2s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
| 2027 | 2239 |
| 2028 g3s1 = Persistent<Object>::New(Object::New()); | 2240 g3s1 = Persistent<Object>::New(Object::New()); |
| 2029 g3s2 = Persistent<Object>::New(Object::New()); | 2241 g3s2 = Persistent<Object>::New(Object::New()); |
| 2030 g3s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); | 2242 g3s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
| 2031 g3s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); | 2243 g3s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
| 2032 } | 2244 } |
| 2033 | 2245 |
| 2034 Persistent<Object> root = Persistent<Object>::New(g1s1); // make a root. | 2246 Persistent<Object> root = Persistent<Object>::New(g1s1); // make a root. |
| 2035 | 2247 |
| 2036 // Connect groups. We're building the following cycle: | 2248 // Connect groups. We're building the following cycle: |
| 2037 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other | 2249 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other |
| 2038 // groups. | 2250 // groups. |
| 2039 { | 2251 { |
| 2040 Persistent<Value> g1_objects[] = { g1s1, g1s2 }; | 2252 Persistent<Value> g1_objects[] = { g1s1, g1s2 }; |
| 2041 Persistent<Value> g1_children[] = { g2s1 }; | 2253 Persistent<Value> g1_children[] = { g2s1 }; |
| 2042 Persistent<Value> g2_objects[] = { g2s1, g2s2 }; | 2254 Persistent<Value> g2_objects[] = { g2s1, g2s2 }; |
| 2043 Persistent<Value> g2_children[] = { g3s1 }; | 2255 Persistent<Value> g2_children[] = { g3s1 }; |
| 2044 Persistent<Value> g3_objects[] = { g3s1, g3s2 }; | 2256 Persistent<Value> g3_objects[] = { g3s1, g3s2 }; |
| 2045 Persistent<Value> g3_children[] = { g1s1 }; | 2257 Persistent<Value> g3_children[] = { g1s1 }; |
| 2046 V8::AddObjectGroup(g1_objects, 2); | 2258 V8::AddObjectGroup(g1_objects, 2); |
| 2047 V8::AddImplicitReferences(g1s1, g1_children, 1); | 2259 V8::AddImplicitReferences(g1s1, g1_children, 1); |
| 2048 V8::AddObjectGroup(g2_objects, 2); | 2260 V8::AddObjectGroup(g2_objects, 2); |
| 2049 V8::AddImplicitReferences(g2s1, g2_children, 1); | 2261 V8::AddImplicitReferences(g2s1, g2_children, 1); |
| 2050 V8::AddObjectGroup(g3_objects, 2); | 2262 V8::AddObjectGroup(g3_objects, 2); |
| 2051 V8::AddImplicitReferences(g3s1, g3_children, 1); | 2263 V8::AddImplicitReferences(g3s1, g3_children, 1); |
| 2052 } | 2264 } |
| 2053 // Do a full GC | 2265 // Do a single full GC |
| 2054 HEAP->CollectGarbage(i::OLD_POINTER_SPACE); | 2266 HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); |
| 2055 | 2267 |
| 2056 // All object should be alive. | 2268 // All object should be alive. |
| 2057 CHECK_EQ(0, NumberOfWeakCalls); | 2269 CHECK_EQ(0, counter.NumberOfWeakCalls()); |
| 2058 | 2270 |
| 2059 // Weaken the root. | 2271 // Weaken the root. |
| 2060 root.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback); | 2272 root.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback); |
| 2061 | 2273 |
| 2062 // Groups are deleted, rebuild groups. | 2274 // Groups are deleted, rebuild groups. |
| 2063 { | 2275 { |
| 2064 Persistent<Value> g1_objects[] = { g1s1, g1s2 }; | 2276 Persistent<Value> g1_objects[] = { g1s1, g1s2 }; |
| 2065 Persistent<Value> g1_children[] = { g2s1 }; | 2277 Persistent<Value> g1_children[] = { g2s1 }; |
| 2066 Persistent<Value> g2_objects[] = { g2s1, g2s2 }; | 2278 Persistent<Value> g2_objects[] = { g2s1, g2s2 }; |
| 2067 Persistent<Value> g2_children[] = { g3s1 }; | 2279 Persistent<Value> g2_children[] = { g3s1 }; |
| 2068 Persistent<Value> g3_objects[] = { g3s1, g3s2 }; | 2280 Persistent<Value> g3_objects[] = { g3s1, g3s2 }; |
| 2069 Persistent<Value> g3_children[] = { g1s1 }; | 2281 Persistent<Value> g3_children[] = { g1s1 }; |
| 2070 V8::AddObjectGroup(g1_objects, 2); | 2282 V8::AddObjectGroup(g1_objects, 2); |
| 2071 V8::AddImplicitReferences(g1s1, g1_children, 1); | 2283 V8::AddImplicitReferences(g1s1, g1_children, 1); |
| 2072 V8::AddObjectGroup(g2_objects, 2); | 2284 V8::AddObjectGroup(g2_objects, 2); |
| 2073 V8::AddImplicitReferences(g2s1, g2_children, 1); | 2285 V8::AddImplicitReferences(g2s1, g2_children, 1); |
| 2074 V8::AddObjectGroup(g3_objects, 2); | 2286 V8::AddObjectGroup(g3_objects, 2); |
| 2075 V8::AddImplicitReferences(g3s1, g3_children, 1); | 2287 V8::AddImplicitReferences(g3s1, g3_children, 1); |
| 2076 } | 2288 } |
| 2077 | 2289 |
| 2078 HEAP->CollectGarbage(i::OLD_POINTER_SPACE); | 2290 HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); |
| 2079 | 2291 |
| 2080 // All objects should be gone. 7 global handles in total. | 2292 // All objects should be gone. 7 global handles in total. |
| 2081 CHECK_EQ(7, NumberOfWeakCalls); | 2293 CHECK_EQ(7, counter.NumberOfWeakCalls()); |
| 2082 } | 2294 } |
| 2083 | 2295 |
| 2084 | 2296 |
| 2085 THREADED_TEST(ScriptException) { | 2297 THREADED_TEST(ScriptException) { |
| 2086 v8::HandleScope scope; | 2298 v8::HandleScope scope; |
| 2087 LocalContext env; | 2299 LocalContext env; |
| 2088 Local<Script> script = Script::Compile(v8_str("throw 'panama!';")); | 2300 Local<Script> script = Script::Compile(v8_str("throw 'panama!';")); |
| 2089 v8::TryCatch try_catch; | 2301 v8::TryCatch try_catch; |
| 2090 Local<Value> result = script->Run(); | 2302 Local<Value> result = script->Run(); |
| 2091 CHECK(result.IsEmpty()); | 2303 CHECK(result.IsEmpty()); |
| (...skipping 2206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4298 v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource)); | 4510 v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource)); |
| 4299 const char* extension_names[] = { "simpletest" }; | 4511 const char* extension_names[] = { "simpletest" }; |
| 4300 v8::ExtensionConfiguration extensions(1, extension_names); | 4512 v8::ExtensionConfiguration extensions(1, extension_names); |
| 4301 v8::Handle<Context> context = Context::New(&extensions); | 4513 v8::Handle<Context> context = Context::New(&extensions); |
| 4302 Context::Scope lock(context); | 4514 Context::Scope lock(context); |
| 4303 v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run(); | 4515 v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run(); |
| 4304 CHECK_EQ(result, v8::Integer::New(4)); | 4516 CHECK_EQ(result, v8::Integer::New(4)); |
| 4305 } | 4517 } |
| 4306 | 4518 |
| 4307 | 4519 |
| 4520 static const char* kEmbeddedExtensionSource = |
| 4521 "function Ret54321(){return 54321;}~~@@$" |
| 4522 "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS."; |
| 4523 static const int kEmbeddedExtensionSourceValidLen = 34; |
| 4524 |
| 4525 |
| 4526 THREADED_TEST(ExtensionMissingSourceLength) { |
| 4527 v8::HandleScope handle_scope; |
| 4528 v8::RegisterExtension(new Extension("srclentest_fail", |
| 4529 kEmbeddedExtensionSource)); |
| 4530 const char* extension_names[] = { "srclentest_fail" }; |
| 4531 v8::ExtensionConfiguration extensions(1, extension_names); |
| 4532 v8::Handle<Context> context = Context::New(&extensions); |
| 4533 CHECK_EQ(0, *context); |
| 4534 } |
| 4535 |
| 4536 |
| 4537 THREADED_TEST(ExtensionWithSourceLength) { |
| 4538 for (int source_len = kEmbeddedExtensionSourceValidLen - 1; |
| 4539 source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) { |
| 4540 v8::HandleScope handle_scope; |
| 4541 i::ScopedVector<char> extension_name(32); |
| 4542 i::OS::SNPrintF(extension_name, "ext #%d", source_len); |
| 4543 v8::RegisterExtension(new Extension(extension_name.start(), |
| 4544 kEmbeddedExtensionSource, 0, 0, |
| 4545 source_len)); |
| 4546 const char* extension_names[1] = { extension_name.start() }; |
| 4547 v8::ExtensionConfiguration extensions(1, extension_names); |
| 4548 v8::Handle<Context> context = Context::New(&extensions); |
| 4549 if (source_len == kEmbeddedExtensionSourceValidLen) { |
| 4550 Context::Scope lock(context); |
| 4551 v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run(); |
| 4552 CHECK_EQ(v8::Integer::New(54321), result); |
| 4553 } else { |
| 4554 // Anything but exactly the right length should fail to compile. |
| 4555 CHECK_EQ(0, *context); |
| 4556 } |
| 4557 } |
| 4558 } |
| 4559 |
| 4560 |
| 4308 static const char* kEvalExtensionSource1 = | 4561 static const char* kEvalExtensionSource1 = |
| 4309 "function UseEval1() {" | 4562 "function UseEval1() {" |
| 4310 " var x = 42;" | 4563 " var x = 42;" |
| 4311 " return eval('x');" | 4564 " return eval('x');" |
| 4312 "}"; | 4565 "}"; |
| 4313 | 4566 |
| 4314 | 4567 |
| 4315 static const char* kEvalExtensionSource2 = | 4568 static const char* kEvalExtensionSource2 = |
| 4316 "(function() {" | 4569 "(function() {" |
| 4317 " var x = 42;" | 4570 " var x = 42;" |
| (...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4798 CHECK(object_a_disposed); | 5051 CHECK(object_a_disposed); |
| 4799 } | 5052 } |
| 4800 | 5053 |
| 4801 | 5054 |
| 4802 static void InvokeScavenge() { | 5055 static void InvokeScavenge() { |
| 4803 HEAP->PerformScavenge(); | 5056 HEAP->PerformScavenge(); |
| 4804 } | 5057 } |
| 4805 | 5058 |
| 4806 | 5059 |
| 4807 static void InvokeMarkSweep() { | 5060 static void InvokeMarkSweep() { |
| 4808 HEAP->CollectAllGarbage(false); | 5061 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 4809 } | 5062 } |
| 4810 | 5063 |
| 4811 | 5064 |
| 4812 static void ForceScavenge(v8::Persistent<v8::Value> obj, void* data) { | 5065 static void ForceScavenge(v8::Persistent<v8::Value> obj, void* data) { |
| 4813 obj.Dispose(); | 5066 obj.Dispose(); |
| 4814 obj.Clear(); | 5067 obj.Clear(); |
| 4815 *(reinterpret_cast<bool*>(data)) = true; | 5068 *(reinterpret_cast<bool*>(data)) = true; |
| 4816 InvokeScavenge(); | 5069 InvokeScavenge(); |
| 4817 } | 5070 } |
| 4818 | 5071 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4891 | 5144 |
| 4892 static v8::Handle<Value> ArgumentsTestCallback(const v8::Arguments& args) { | 5145 static v8::Handle<Value> ArgumentsTestCallback(const v8::Arguments& args) { |
| 4893 ApiTestFuzzer::Fuzz(); | 5146 ApiTestFuzzer::Fuzz(); |
| 4894 CHECK_EQ(args_fun, args.Callee()); | 5147 CHECK_EQ(args_fun, args.Callee()); |
| 4895 CHECK_EQ(3, args.Length()); | 5148 CHECK_EQ(3, args.Length()); |
| 4896 CHECK_EQ(v8::Integer::New(1), args[0]); | 5149 CHECK_EQ(v8::Integer::New(1), args[0]); |
| 4897 CHECK_EQ(v8::Integer::New(2), args[1]); | 5150 CHECK_EQ(v8::Integer::New(2), args[1]); |
| 4898 CHECK_EQ(v8::Integer::New(3), args[2]); | 5151 CHECK_EQ(v8::Integer::New(3), args[2]); |
| 4899 CHECK_EQ(v8::Undefined(), args[3]); | 5152 CHECK_EQ(v8::Undefined(), args[3]); |
| 4900 v8::HandleScope scope; | 5153 v8::HandleScope scope; |
| 4901 HEAP->CollectAllGarbage(false); | 5154 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 4902 return v8::Undefined(); | 5155 return v8::Undefined(); |
| 4903 } | 5156 } |
| 4904 | 5157 |
| 4905 | 5158 |
| 4906 THREADED_TEST(Arguments) { | 5159 THREADED_TEST(Arguments) { |
| 4907 v8::HandleScope scope; | 5160 v8::HandleScope scope; |
| 4908 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(); | 5161 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(); |
| 4909 global->Set(v8_str("f"), v8::FunctionTemplate::New(ArgumentsTestCallback)); | 5162 global->Set(v8_str("f"), v8::FunctionTemplate::New(ArgumentsTestCallback)); |
| 4910 LocalContext context(NULL, global); | 5163 LocalContext context(NULL, global); |
| 4911 args_fun = context->Global()->Get(v8_str("f")).As<Function>(); | 5164 args_fun = context->Global()->Get(v8_str("f")).As<Function>(); |
| (...skipping 2964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7876 "var p = new constructor();" | 8129 "var p = new constructor();" |
| 7877 "p.hasOwnProperty('ostehaps');"); | 8130 "p.hasOwnProperty('ostehaps');"); |
| 7878 CHECK_EQ(false, value->BooleanValue()); | 8131 CHECK_EQ(false, value->BooleanValue()); |
| 7879 } | 8132 } |
| 7880 | 8133 |
| 7881 | 8134 |
| 7882 static v8::Handle<Value> InterceptorHasOwnPropertyGetterGC( | 8135 static v8::Handle<Value> InterceptorHasOwnPropertyGetterGC( |
| 7883 Local<String> name, | 8136 Local<String> name, |
| 7884 const AccessorInfo& info) { | 8137 const AccessorInfo& info) { |
| 7885 ApiTestFuzzer::Fuzz(); | 8138 ApiTestFuzzer::Fuzz(); |
| 7886 HEAP->CollectAllGarbage(false); | 8139 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 7887 return v8::Handle<Value>(); | 8140 return v8::Handle<Value>(); |
| 7888 } | 8141 } |
| 7889 | 8142 |
| 7890 | 8143 |
| 7891 THREADED_TEST(InterceptorHasOwnPropertyCausingGC) { | 8144 THREADED_TEST(InterceptorHasOwnPropertyCausingGC) { |
| 7892 v8::HandleScope scope; | 8145 v8::HandleScope scope; |
| 7893 LocalContext context; | 8146 LocalContext context; |
| 7894 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(); | 8147 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(); |
| 7895 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate(); | 8148 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate(); |
| 7896 instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC); | 8149 instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC); |
| (...skipping 709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8606 "};"); | 8859 "};"); |
| 8607 CHECK_EQ(239 * 10, value->Int32Value()); | 8860 CHECK_EQ(239 * 10, value->Int32Value()); |
| 8608 } | 8861 } |
| 8609 | 8862 |
| 8610 static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name, | 8863 static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name, |
| 8611 const AccessorInfo& info) { | 8864 const AccessorInfo& info) { |
| 8612 ApiTestFuzzer::Fuzz(); | 8865 ApiTestFuzzer::Fuzz(); |
| 8613 int* call_count = reinterpret_cast<int*>(v8::External::Unwrap(info.Data())); | 8866 int* call_count = reinterpret_cast<int*>(v8::External::Unwrap(info.Data())); |
| 8614 ++(*call_count); | 8867 ++(*call_count); |
| 8615 if ((*call_count) % 20 == 0) { | 8868 if ((*call_count) % 20 == 0) { |
| 8616 HEAP->CollectAllGarbage(true); | 8869 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 8617 } | 8870 } |
| 8618 return v8::Handle<Value>(); | 8871 return v8::Handle<Value>(); |
| 8619 } | 8872 } |
| 8620 | 8873 |
| 8621 static v8::Handle<Value> FastApiCallback_TrivialSignature( | 8874 static v8::Handle<Value> FastApiCallback_TrivialSignature( |
| 8622 const v8::Arguments& args) { | 8875 const v8::Arguments& args) { |
| 8623 ApiTestFuzzer::Fuzz(); | 8876 ApiTestFuzzer::Fuzz(); |
| 8624 CHECK_EQ(args.This(), args.Holder()); | 8877 CHECK_EQ(args.This(), args.Holder()); |
| 8625 CHECK(args.Data()->Equals(v8_str("method_data"))); | 8878 CHECK(args.Data()->Equals(v8_str("method_data"))); |
| 8626 return v8::Integer::New(args[0]->Int32Value() + 1); | 8879 return v8::Integer::New(args[0]->Int32Value() + 1); |
| (...skipping 1330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9957 Local<Script> script = v8_compile("(function () {" | 10210 Local<Script> script = v8_compile("(function () {" |
| 9958 " unlock_for_a_moment();" | 10211 " unlock_for_a_moment();" |
| 9959 " return 42;" | 10212 " return 42;" |
| 9960 "})();"); | 10213 "})();"); |
| 9961 CHECK_EQ(42, script->Run()->Int32Value()); | 10214 CHECK_EQ(42, script->Run()->Int32Value()); |
| 9962 } | 10215 } |
| 9963 } | 10216 } |
| 9964 | 10217 |
| 9965 | 10218 |
| 9966 static int GetGlobalObjectsCount() { | 10219 static int GetGlobalObjectsCount() { |
| 10220 i::Isolate::Current()->heap()->EnsureHeapIsIterable(); |
| 9967 int count = 0; | 10221 int count = 0; |
| 9968 i::HeapIterator it; | 10222 i::HeapIterator it; |
| 9969 for (i::HeapObject* object = it.next(); object != NULL; object = it.next()) | 10223 for (i::HeapObject* object = it.next(); object != NULL; object = it.next()) |
| 9970 if (object->IsJSGlobalObject()) count++; | 10224 if (object->IsJSGlobalObject()) count++; |
| 9971 return count; | 10225 return count; |
| 9972 } | 10226 } |
| 9973 | 10227 |
| 9974 | 10228 |
| 9975 static void CheckSurvivingGlobalObjectsCount(int expected) { | 10229 static void CheckSurvivingGlobalObjectsCount(int expected) { |
| 9976 // We need to collect all garbage twice to be sure that everything | 10230 // We need to collect all garbage twice to be sure that everything |
| 9977 // has been collected. This is because inline caches are cleared in | 10231 // has been collected. This is because inline caches are cleared in |
| 9978 // the first garbage collection but some of the maps have already | 10232 // the first garbage collection but some of the maps have already |
| 9979 // been marked at that point. Therefore some of the maps are not | 10233 // been marked at that point. Therefore some of the maps are not |
| 9980 // collected until the second garbage collection. | 10234 // collected until the second garbage collection. |
| 9981 HEAP->global_context_map(); | 10235 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 9982 HEAP->CollectAllGarbage(false); | 10236 HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); |
| 9983 HEAP->CollectAllGarbage(false); | |
| 9984 int count = GetGlobalObjectsCount(); | 10237 int count = GetGlobalObjectsCount(); |
| 9985 #ifdef DEBUG | 10238 #ifdef DEBUG |
| 9986 if (count != expected) HEAP->TracePathToGlobal(); | 10239 if (count != expected) HEAP->TracePathToGlobal(); |
| 9987 #endif | 10240 #endif |
| 9988 CHECK_EQ(expected, count); | 10241 CHECK_EQ(expected, count); |
| 9989 } | 10242 } |
| 9990 | 10243 |
| 9991 | 10244 |
| 9992 TEST(DontLeakGlobalObjects) { | 10245 TEST(DontLeakGlobalObjects) { |
| 9993 // Regression test for issues 1139850 and 1174891. | 10246 // Regression test for issues 1139850 and 1174891. |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10042 some_object = v8::Persistent<v8::Object>::New(v8::Object::New()); | 10295 some_object = v8::Persistent<v8::Object>::New(v8::Object::New()); |
| 10043 handle1 = v8::Persistent<v8::Object>::New(v8::Object::New()); | 10296 handle1 = v8::Persistent<v8::Object>::New(v8::Object::New()); |
| 10044 handle2 = v8::Persistent<v8::Object>::New(v8::Object::New()); | 10297 handle2 = v8::Persistent<v8::Object>::New(v8::Object::New()); |
| 10045 } | 10298 } |
| 10046 // Note: order is implementation dependent alas: currently | 10299 // Note: order is implementation dependent alas: currently |
| 10047 // global handle nodes are processed by PostGarbageCollectionProcessing | 10300 // global handle nodes are processed by PostGarbageCollectionProcessing |
| 10048 // in reverse allocation order, so if second allocated handle is deleted, | 10301 // in reverse allocation order, so if second allocated handle is deleted, |
| 10049 // weak callback of the first handle would be able to 'reallocate' it. | 10302 // weak callback of the first handle would be able to 'reallocate' it. |
| 10050 handle1.MakeWeak(NULL, NewPersistentHandleCallback); | 10303 handle1.MakeWeak(NULL, NewPersistentHandleCallback); |
| 10051 handle2.Dispose(); | 10304 handle2.Dispose(); |
| 10052 HEAP->CollectAllGarbage(false); | 10305 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 10053 } | 10306 } |
| 10054 | 10307 |
| 10055 | 10308 |
| 10056 v8::Persistent<v8::Object> to_be_disposed; | 10309 v8::Persistent<v8::Object> to_be_disposed; |
| 10057 | 10310 |
| 10058 void DisposeAndForceGcCallback(v8::Persistent<v8::Value> handle, void*) { | 10311 void DisposeAndForceGcCallback(v8::Persistent<v8::Value> handle, void*) { |
| 10059 to_be_disposed.Dispose(); | 10312 to_be_disposed.Dispose(); |
| 10060 HEAP->CollectAllGarbage(false); | 10313 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 10061 handle.Dispose(); | 10314 handle.Dispose(); |
| 10062 } | 10315 } |
| 10063 | 10316 |
| 10064 | 10317 |
| 10065 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) { | 10318 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) { |
| 10066 LocalContext context; | 10319 LocalContext context; |
| 10067 | 10320 |
| 10068 v8::Persistent<v8::Object> handle1, handle2; | 10321 v8::Persistent<v8::Object> handle1, handle2; |
| 10069 { | 10322 { |
| 10070 v8::HandleScope scope; | 10323 v8::HandleScope scope; |
| 10071 handle1 = v8::Persistent<v8::Object>::New(v8::Object::New()); | 10324 handle1 = v8::Persistent<v8::Object>::New(v8::Object::New()); |
| 10072 handle2 = v8::Persistent<v8::Object>::New(v8::Object::New()); | 10325 handle2 = v8::Persistent<v8::Object>::New(v8::Object::New()); |
| 10073 } | 10326 } |
| 10074 handle1.MakeWeak(NULL, DisposeAndForceGcCallback); | 10327 handle1.MakeWeak(NULL, DisposeAndForceGcCallback); |
| 10075 to_be_disposed = handle2; | 10328 to_be_disposed = handle2; |
| 10076 HEAP->CollectAllGarbage(false); | 10329 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 10077 } | 10330 } |
| 10078 | 10331 |
| 10079 void DisposingCallback(v8::Persistent<v8::Value> handle, void*) { | 10332 void DisposingCallback(v8::Persistent<v8::Value> handle, void*) { |
| 10080 handle.Dispose(); | 10333 handle.Dispose(); |
| 10081 } | 10334 } |
| 10082 | 10335 |
| 10083 void HandleCreatingCallback(v8::Persistent<v8::Value> handle, void*) { | 10336 void HandleCreatingCallback(v8::Persistent<v8::Value> handle, void*) { |
| 10084 v8::HandleScope scope; | 10337 v8::HandleScope scope; |
| 10085 v8::Persistent<v8::Object>::New(v8::Object::New()); | 10338 v8::Persistent<v8::Object>::New(v8::Object::New()); |
| 10086 handle.Dispose(); | 10339 handle.Dispose(); |
| 10087 } | 10340 } |
| 10088 | 10341 |
| 10089 | 10342 |
| 10090 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) { | 10343 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) { |
| 10091 LocalContext context; | 10344 LocalContext context; |
| 10092 | 10345 |
| 10093 v8::Persistent<v8::Object> handle1, handle2, handle3; | 10346 v8::Persistent<v8::Object> handle1, handle2, handle3; |
| 10094 { | 10347 { |
| 10095 v8::HandleScope scope; | 10348 v8::HandleScope scope; |
| 10096 handle3 = v8::Persistent<v8::Object>::New(v8::Object::New()); | 10349 handle3 = v8::Persistent<v8::Object>::New(v8::Object::New()); |
| 10097 handle2 = v8::Persistent<v8::Object>::New(v8::Object::New()); | 10350 handle2 = v8::Persistent<v8::Object>::New(v8::Object::New()); |
| 10098 handle1 = v8::Persistent<v8::Object>::New(v8::Object::New()); | 10351 handle1 = v8::Persistent<v8::Object>::New(v8::Object::New()); |
| 10099 } | 10352 } |
| 10100 handle2.MakeWeak(NULL, DisposingCallback); | 10353 handle2.MakeWeak(NULL, DisposingCallback); |
| 10101 handle3.MakeWeak(NULL, HandleCreatingCallback); | 10354 handle3.MakeWeak(NULL, HandleCreatingCallback); |
| 10102 HEAP->CollectAllGarbage(false); | 10355 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 10103 } | 10356 } |
| 10104 | 10357 |
| 10105 | 10358 |
| 10106 THREADED_TEST(CheckForCrossContextObjectLiterals) { | 10359 THREADED_TEST(CheckForCrossContextObjectLiterals) { |
| 10107 v8::V8::Initialize(); | 10360 v8::V8::Initialize(); |
| 10108 | 10361 |
| 10109 const int nof = 2; | 10362 const int nof = 2; |
| 10110 const char* sources[nof] = { | 10363 const char* sources[nof] = { |
| 10111 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }", | 10364 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }", |
| 10112 "Object()" | 10365 "Object()" |
| (...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10908 private: | 11161 private: |
| 10909 RegExpInterruptTest* test_; | 11162 RegExpInterruptTest* test_; |
| 10910 }; | 11163 }; |
| 10911 | 11164 |
| 10912 void CollectGarbage() { | 11165 void CollectGarbage() { |
| 10913 block_->Wait(); | 11166 block_->Wait(); |
| 10914 while (gc_during_regexp_ < kRequiredGCs) { | 11167 while (gc_during_regexp_ < kRequiredGCs) { |
| 10915 { | 11168 { |
| 10916 v8::Locker lock; | 11169 v8::Locker lock; |
| 10917 // TODO(lrn): Perhaps create some garbage before collecting. | 11170 // TODO(lrn): Perhaps create some garbage before collecting. |
| 10918 HEAP->CollectAllGarbage(false); | 11171 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 10919 gc_count_++; | 11172 gc_count_++; |
| 10920 } | 11173 } |
| 10921 i::OS::Sleep(1); | 11174 i::OS::Sleep(1); |
| 10922 } | 11175 } |
| 10923 gc_success_ = true; | 11176 gc_success_ = true; |
| 10924 } | 11177 } |
| 10925 | 11178 |
| 10926 void LongRunningRegExp() { | 11179 void LongRunningRegExp() { |
| 10927 block_->Signal(); // Enable garbage collection thread on next preemption. | 11180 block_->Signal(); // Enable garbage collection thread on next preemption. |
| 10928 int rounds = 0; | 11181 int rounds = 0; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11030 } | 11283 } |
| 11031 private: | 11284 private: |
| 11032 ApplyInterruptTest* test_; | 11285 ApplyInterruptTest* test_; |
| 11033 }; | 11286 }; |
| 11034 | 11287 |
| 11035 void CollectGarbage() { | 11288 void CollectGarbage() { |
| 11036 block_->Wait(); | 11289 block_->Wait(); |
| 11037 while (gc_during_apply_ < kRequiredGCs) { | 11290 while (gc_during_apply_ < kRequiredGCs) { |
| 11038 { | 11291 { |
| 11039 v8::Locker lock; | 11292 v8::Locker lock; |
| 11040 HEAP->CollectAllGarbage(false); | 11293 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 11041 gc_count_++; | 11294 gc_count_++; |
| 11042 } | 11295 } |
| 11043 i::OS::Sleep(1); | 11296 i::OS::Sleep(1); |
| 11044 } | 11297 } |
| 11045 gc_success_ = true; | 11298 gc_success_ = true; |
| 11046 } | 11299 } |
| 11047 | 11300 |
| 11048 void LongRunningApply() { | 11301 void LongRunningApply() { |
| 11049 block_->Signal(); | 11302 block_->Signal(); |
| 11050 int rounds = 0; | 11303 int rounds = 0; |
| (...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11746 | 11999 |
| 11747 | 12000 |
| 11748 THREADED_TEST(PixelArray) { | 12001 THREADED_TEST(PixelArray) { |
| 11749 v8::HandleScope scope; | 12002 v8::HandleScope scope; |
| 11750 LocalContext context; | 12003 LocalContext context; |
| 11751 const int kElementCount = 260; | 12004 const int kElementCount = 260; |
| 11752 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount)); | 12005 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount)); |
| 11753 i::Handle<i::ExternalPixelArray> pixels = | 12006 i::Handle<i::ExternalPixelArray> pixels = |
| 11754 i::Handle<i::ExternalPixelArray>::cast( | 12007 i::Handle<i::ExternalPixelArray>::cast( |
| 11755 FACTORY->NewExternalArray(kElementCount, | 12008 FACTORY->NewExternalArray(kElementCount, |
| 11756 v8::kExternalPixelArray, | 12009 v8::kExternalPixelArray, |
| 11757 pixel_data)); | 12010 pixel_data)); |
| 11758 HEAP->CollectAllGarbage(false); // Force GC to trigger verification. | 12011 // Force GC to trigger verification. |
| 12012 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 11759 for (int i = 0; i < kElementCount; i++) { | 12013 for (int i = 0; i < kElementCount; i++) { |
| 11760 pixels->set(i, i % 256); | 12014 pixels->set(i, i % 256); |
| 11761 } | 12015 } |
| 11762 HEAP->CollectAllGarbage(false); // Force GC to trigger verification. | 12016 // Force GC to trigger verification. |
| 12017 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 11763 for (int i = 0; i < kElementCount; i++) { | 12018 for (int i = 0; i < kElementCount; i++) { |
| 11764 CHECK_EQ(i % 256, pixels->get_scalar(i)); | 12019 CHECK_EQ(i % 256, pixels->get_scalar(i)); |
| 11765 CHECK_EQ(i % 256, pixel_data[i]); | 12020 CHECK_EQ(i % 256, pixel_data[i]); |
| 11766 } | 12021 } |
| 11767 | 12022 |
| 11768 v8::Handle<v8::Object> obj = v8::Object::New(); | 12023 v8::Handle<v8::Object> obj = v8::Object::New(); |
| 11769 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj); | 12024 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj); |
| 11770 // Set the elements to be the pixels. | 12025 // Set the elements to be the pixels. |
| 11771 // jsobj->set_elements(*pixels); | 12026 // jsobj->set_elements(*pixels); |
| 11772 obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount); | 12027 obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount); |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12228 int64_t high) { | 12483 int64_t high) { |
| 12229 v8::HandleScope scope; | 12484 v8::HandleScope scope; |
| 12230 LocalContext context; | 12485 LocalContext context; |
| 12231 const int kElementCount = 40; | 12486 const int kElementCount = 40; |
| 12232 int element_size = ExternalArrayElementSize(array_type); | 12487 int element_size = ExternalArrayElementSize(array_type); |
| 12233 ElementType* array_data = | 12488 ElementType* array_data = |
| 12234 static_cast<ElementType*>(malloc(kElementCount * element_size)); | 12489 static_cast<ElementType*>(malloc(kElementCount * element_size)); |
| 12235 i::Handle<ExternalArrayClass> array = | 12490 i::Handle<ExternalArrayClass> array = |
| 12236 i::Handle<ExternalArrayClass>::cast( | 12491 i::Handle<ExternalArrayClass>::cast( |
| 12237 FACTORY->NewExternalArray(kElementCount, array_type, array_data)); | 12492 FACTORY->NewExternalArray(kElementCount, array_type, array_data)); |
| 12238 HEAP->CollectAllGarbage(false); // Force GC to trigger verification. | 12493 // Force GC to trigger verification. |
| 12494 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 12239 for (int i = 0; i < kElementCount; i++) { | 12495 for (int i = 0; i < kElementCount; i++) { |
| 12240 array->set(i, static_cast<ElementType>(i)); | 12496 array->set(i, static_cast<ElementType>(i)); |
| 12241 } | 12497 } |
| 12242 HEAP->CollectAllGarbage(false); // Force GC to trigger verification. | 12498 // Force GC to trigger verification. |
| 12499 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 12243 for (int i = 0; i < kElementCount; i++) { | 12500 for (int i = 0; i < kElementCount; i++) { |
| 12244 CHECK_EQ(static_cast<int64_t>(i), | 12501 CHECK_EQ(static_cast<int64_t>(i), |
| 12245 static_cast<int64_t>(array->get_scalar(i))); | 12502 static_cast<int64_t>(array->get_scalar(i))); |
| 12246 CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i])); | 12503 CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i])); |
| 12247 } | 12504 } |
| 12248 | 12505 |
| 12249 v8::Handle<v8::Object> obj = v8::Object::New(); | 12506 v8::Handle<v8::Object> obj = v8::Object::New(); |
| 12250 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj); | 12507 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj); |
| 12251 // Set the elements to be the external array. | 12508 // Set the elements to be the external array. |
| 12252 obj->SetIndexedPropertiesToExternalArrayData(array_data, | 12509 obj->SetIndexedPropertiesToExternalArrayData(array_data, |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12350 result = CompileRun("var tmp_array = ext_array;" | 12607 result = CompileRun("var tmp_array = ext_array;" |
| 12351 "var sum = 0;" | 12608 "var sum = 0;" |
| 12352 "for (var i = 0; i < 8; i++) {" | 12609 "for (var i = 0; i < 8; i++) {" |
| 12353 " tmp_array[i] = i;" | 12610 " tmp_array[i] = i;" |
| 12354 " sum += tmp_array[i];" | 12611 " sum += tmp_array[i];" |
| 12355 " if (i == 4) {" | 12612 " if (i == 4) {" |
| 12356 " tmp_array = {};" | 12613 " tmp_array = {};" |
| 12357 " }" | 12614 " }" |
| 12358 "}" | 12615 "}" |
| 12359 "sum;"); | 12616 "sum;"); |
| 12360 HEAP->CollectAllGarbage(false); // Force GC to trigger verification. | 12617 // Force GC to trigger verification. |
| 12618 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 12361 CHECK_EQ(28, result->Int32Value()); | 12619 CHECK_EQ(28, result->Int32Value()); |
| 12362 | 12620 |
| 12363 // Make sure out-of-range loads do not throw. | 12621 // Make sure out-of-range loads do not throw. |
| 12364 i::OS::SNPrintF(test_buf, | 12622 i::OS::SNPrintF(test_buf, |
| 12365 "var caught_exception = false;" | 12623 "var caught_exception = false;" |
| 12366 "try {" | 12624 "try {" |
| 12367 " ext_array[%d];" | 12625 " ext_array[%d];" |
| 12368 "} catch (e) {" | 12626 "} catch (e) {" |
| 12369 " caught_exception = true;" | 12627 " caught_exception = true;" |
| 12370 "}" | 12628 "}" |
| (...skipping 959 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13330 Local<v8::String> obj = v8::String::New(""); | 13588 Local<v8::String> obj = v8::String::New(""); |
| 13331 context->SetData(obj); | 13589 context->SetData(obj); |
| 13332 CompileRun(source_simple); | 13590 CompileRun(source_simple); |
| 13333 context->Exit(); | 13591 context->Exit(); |
| 13334 } | 13592 } |
| 13335 context.Dispose(); | 13593 context.Dispose(); |
| 13336 for (gc_count = 1; gc_count < 10; gc_count++) { | 13594 for (gc_count = 1; gc_count < 10; gc_count++) { |
| 13337 other_context->Enter(); | 13595 other_context->Enter(); |
| 13338 CompileRun(source_simple); | 13596 CompileRun(source_simple); |
| 13339 other_context->Exit(); | 13597 other_context->Exit(); |
| 13340 HEAP->CollectAllGarbage(false); | 13598 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 13341 if (GetGlobalObjectsCount() == 1) break; | 13599 if (GetGlobalObjectsCount() == 1) break; |
| 13342 } | 13600 } |
| 13343 CHECK_GE(2, gc_count); | 13601 CHECK_GE(2, gc_count); |
| 13344 CHECK_EQ(1, GetGlobalObjectsCount()); | 13602 CHECK_EQ(1, GetGlobalObjectsCount()); |
| 13345 | 13603 |
| 13346 // Eval in a function creates reference from the compilation cache to the | 13604 // Eval in a function creates reference from the compilation cache to the |
| 13347 // global object. | 13605 // global object. |
| 13348 const char* source_eval = "function f(){eval('1')}; f()"; | 13606 const char* source_eval = "function f(){eval('1')}; f()"; |
| 13349 context = Context::New(); | 13607 context = Context::New(); |
| 13350 { | 13608 { |
| 13351 v8::HandleScope scope; | 13609 v8::HandleScope scope; |
| 13352 | 13610 |
| 13353 context->Enter(); | 13611 context->Enter(); |
| 13354 CompileRun(source_eval); | 13612 CompileRun(source_eval); |
| 13355 context->Exit(); | 13613 context->Exit(); |
| 13356 } | 13614 } |
| 13357 context.Dispose(); | 13615 context.Dispose(); |
| 13358 for (gc_count = 1; gc_count < 10; gc_count++) { | 13616 for (gc_count = 1; gc_count < 10; gc_count++) { |
| 13359 other_context->Enter(); | 13617 other_context->Enter(); |
| 13360 CompileRun(source_eval); | 13618 CompileRun(source_eval); |
| 13361 other_context->Exit(); | 13619 other_context->Exit(); |
| 13362 HEAP->CollectAllGarbage(false); | 13620 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 13363 if (GetGlobalObjectsCount() == 1) break; | 13621 if (GetGlobalObjectsCount() == 1) break; |
| 13364 } | 13622 } |
| 13365 CHECK_GE(2, gc_count); | 13623 CHECK_GE(2, gc_count); |
| 13366 CHECK_EQ(1, GetGlobalObjectsCount()); | 13624 CHECK_EQ(1, GetGlobalObjectsCount()); |
| 13367 | 13625 |
| 13368 // Looking up the line number for an exception creates reference from the | 13626 // Looking up the line number for an exception creates reference from the |
| 13369 // compilation cache to the global object. | 13627 // compilation cache to the global object. |
| 13370 const char* source_exception = "function f(){throw 1;} f()"; | 13628 const char* source_exception = "function f(){throw 1;} f()"; |
| 13371 context = Context::New(); | 13629 context = Context::New(); |
| 13372 { | 13630 { |
| 13373 v8::HandleScope scope; | 13631 v8::HandleScope scope; |
| 13374 | 13632 |
| 13375 context->Enter(); | 13633 context->Enter(); |
| 13376 v8::TryCatch try_catch; | 13634 v8::TryCatch try_catch; |
| 13377 CompileRun(source_exception); | 13635 CompileRun(source_exception); |
| 13378 CHECK(try_catch.HasCaught()); | 13636 CHECK(try_catch.HasCaught()); |
| 13379 v8::Handle<v8::Message> message = try_catch.Message(); | 13637 v8::Handle<v8::Message> message = try_catch.Message(); |
| 13380 CHECK(!message.IsEmpty()); | 13638 CHECK(!message.IsEmpty()); |
| 13381 CHECK_EQ(1, message->GetLineNumber()); | 13639 CHECK_EQ(1, message->GetLineNumber()); |
| 13382 context->Exit(); | 13640 context->Exit(); |
| 13383 } | 13641 } |
| 13384 context.Dispose(); | 13642 context.Dispose(); |
| 13385 for (gc_count = 1; gc_count < 10; gc_count++) { | 13643 for (gc_count = 1; gc_count < 10; gc_count++) { |
| 13386 other_context->Enter(); | 13644 other_context->Enter(); |
| 13387 CompileRun(source_exception); | 13645 CompileRun(source_exception); |
| 13388 other_context->Exit(); | 13646 other_context->Exit(); |
| 13389 HEAP->CollectAllGarbage(false); | 13647 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 13390 if (GetGlobalObjectsCount() == 1) break; | 13648 if (GetGlobalObjectsCount() == 1) break; |
| 13391 } | 13649 } |
| 13392 CHECK_GE(2, gc_count); | 13650 CHECK_GE(2, gc_count); |
| 13393 CHECK_EQ(1, GetGlobalObjectsCount()); | 13651 CHECK_EQ(1, GetGlobalObjectsCount()); |
| 13394 | 13652 |
| 13395 other_context.Dispose(); | 13653 other_context.Dispose(); |
| 13396 } | 13654 } |
| 13397 | 13655 |
| 13398 | 13656 |
| 13399 THREADED_TEST(ScriptOrigin) { | 13657 THREADED_TEST(ScriptOrigin) { |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13597 ++epilogue_call_count_second; | 13855 ++epilogue_call_count_second; |
| 13598 } | 13856 } |
| 13599 | 13857 |
| 13600 TEST(GCCallbacks) { | 13858 TEST(GCCallbacks) { |
| 13601 LocalContext context; | 13859 LocalContext context; |
| 13602 | 13860 |
| 13603 v8::V8::AddGCPrologueCallback(PrologueCallback); | 13861 v8::V8::AddGCPrologueCallback(PrologueCallback); |
| 13604 v8::V8::AddGCEpilogueCallback(EpilogueCallback); | 13862 v8::V8::AddGCEpilogueCallback(EpilogueCallback); |
| 13605 CHECK_EQ(0, prologue_call_count); | 13863 CHECK_EQ(0, prologue_call_count); |
| 13606 CHECK_EQ(0, epilogue_call_count); | 13864 CHECK_EQ(0, epilogue_call_count); |
| 13607 HEAP->CollectAllGarbage(false); | 13865 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 13608 CHECK_EQ(1, prologue_call_count); | 13866 CHECK_EQ(1, prologue_call_count); |
| 13609 CHECK_EQ(1, epilogue_call_count); | 13867 CHECK_EQ(1, epilogue_call_count); |
| 13610 v8::V8::AddGCPrologueCallback(PrologueCallbackSecond); | 13868 v8::V8::AddGCPrologueCallback(PrologueCallbackSecond); |
| 13611 v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond); | 13869 v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond); |
| 13612 HEAP->CollectAllGarbage(false); | 13870 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 13613 CHECK_EQ(2, prologue_call_count); | 13871 CHECK_EQ(2, prologue_call_count); |
| 13614 CHECK_EQ(2, epilogue_call_count); | 13872 CHECK_EQ(2, epilogue_call_count); |
| 13615 CHECK_EQ(1, prologue_call_count_second); | 13873 CHECK_EQ(1, prologue_call_count_second); |
| 13616 CHECK_EQ(1, epilogue_call_count_second); | 13874 CHECK_EQ(1, epilogue_call_count_second); |
| 13617 v8::V8::RemoveGCPrologueCallback(PrologueCallback); | 13875 v8::V8::RemoveGCPrologueCallback(PrologueCallback); |
| 13618 v8::V8::RemoveGCEpilogueCallback(EpilogueCallback); | 13876 v8::V8::RemoveGCEpilogueCallback(EpilogueCallback); |
| 13619 HEAP->CollectAllGarbage(false); | 13877 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 13620 CHECK_EQ(2, prologue_call_count); | 13878 CHECK_EQ(2, prologue_call_count); |
| 13621 CHECK_EQ(2, epilogue_call_count); | 13879 CHECK_EQ(2, epilogue_call_count); |
| 13622 CHECK_EQ(2, prologue_call_count_second); | 13880 CHECK_EQ(2, prologue_call_count_second); |
| 13623 CHECK_EQ(2, epilogue_call_count_second); | 13881 CHECK_EQ(2, epilogue_call_count_second); |
| 13624 v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond); | 13882 v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond); |
| 13625 v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond); | 13883 v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond); |
| 13626 HEAP->CollectAllGarbage(false); | 13884 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 13627 CHECK_EQ(2, prologue_call_count); | 13885 CHECK_EQ(2, prologue_call_count); |
| 13628 CHECK_EQ(2, epilogue_call_count); | 13886 CHECK_EQ(2, epilogue_call_count); |
| 13629 CHECK_EQ(2, prologue_call_count_second); | 13887 CHECK_EQ(2, prologue_call_count_second); |
| 13630 CHECK_EQ(2, epilogue_call_count_second); | 13888 CHECK_EQ(2, epilogue_call_count_second); |
| 13631 } | 13889 } |
| 13632 | 13890 |
| 13633 | 13891 |
| 13634 THREADED_TEST(AddToJSFunctionResultCache) { | 13892 THREADED_TEST(AddToJSFunctionResultCache) { |
| 13635 i::FLAG_allow_natives_syntax = true; | 13893 i::FLAG_allow_natives_syntax = true; |
| 13636 v8::HandleScope scope; | 13894 v8::HandleScope scope; |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13833 | 14091 |
| 13834 reresult = CompileRun("str2.charCodeAt(2);"); | 14092 reresult = CompileRun("str2.charCodeAt(2);"); |
| 13835 CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value()); | 14093 CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value()); |
| 13836 } | 14094 } |
| 13837 | 14095 |
| 13838 | 14096 |
| 13839 // Failed access check callback that performs a GC on each invocation. | 14097 // Failed access check callback that performs a GC on each invocation. |
| 13840 void FailedAccessCheckCallbackGC(Local<v8::Object> target, | 14098 void FailedAccessCheckCallbackGC(Local<v8::Object> target, |
| 13841 v8::AccessType type, | 14099 v8::AccessType type, |
| 13842 Local<v8::Value> data) { | 14100 Local<v8::Value> data) { |
| 13843 HEAP->CollectAllGarbage(true); | 14101 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 13844 } | 14102 } |
| 13845 | 14103 |
| 13846 | 14104 |
| 13847 TEST(GCInFailedAccessCheckCallback) { | 14105 TEST(GCInFailedAccessCheckCallback) { |
| 13848 // Install a failed access check callback that performs a GC on each | 14106 // Install a failed access check callback that performs a GC on each |
| 13849 // invocation. Then force the callback to be called from va | 14107 // invocation. Then force the callback to be called from va |
| 13850 | 14108 |
| 13851 v8::V8::Initialize(); | 14109 v8::V8::Initialize(); |
| 13852 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC); | 14110 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC); |
| 13853 | 14111 |
| (...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14407 ExpectBoolean("delete cell", true); | 14665 ExpectBoolean("delete cell", true); |
| 14408 ExpectString("(function() {" | 14666 ExpectString("(function() {" |
| 14409 " try {" | 14667 " try {" |
| 14410 " return readCell();" | 14668 " return readCell();" |
| 14411 " } catch(e) {" | 14669 " } catch(e) {" |
| 14412 " return e.toString();" | 14670 " return e.toString();" |
| 14413 " }" | 14671 " }" |
| 14414 "})()", | 14672 "})()", |
| 14415 "ReferenceError: cell is not defined"); | 14673 "ReferenceError: cell is not defined"); |
| 14416 CompileRun("cell = \"new_second\";"); | 14674 CompileRun("cell = \"new_second\";"); |
| 14417 HEAP->CollectAllGarbage(true); | 14675 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 14418 ExpectString("readCell()", "new_second"); | 14676 ExpectString("readCell()", "new_second"); |
| 14419 ExpectString("readCell()", "new_second"); | 14677 ExpectString("readCell()", "new_second"); |
| 14420 } | 14678 } |
| 14421 } | 14679 } |
| 14422 | 14680 |
| 14423 | 14681 |
| 14424 TEST(DontDeleteCellLoadICForceDelete) { | 14682 TEST(DontDeleteCellLoadICForceDelete) { |
| 14425 const char* function_code = | 14683 const char* function_code = |
| 14426 "function readCell() { while (true) { return cell; } }"; | 14684 "function readCell() { while (true) { return cell; } }"; |
| 14427 | 14685 |
| (...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15175 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]"))); | 15433 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]"))); |
| 15176 | 15434 |
| 15177 // TODO(1547): Make the following also return "i". | 15435 // TODO(1547): Make the following also return "i". |
| 15178 // Calling with environment record as base. | 15436 // Calling with environment record as base. |
| 15179 TestReceiver(o, context->Global(), "func()"); | 15437 TestReceiver(o, context->Global(), "func()"); |
| 15180 // Calling with no base. | 15438 // Calling with no base. |
| 15181 TestReceiver(o, context->Global(), "(1,func)()"); | 15439 TestReceiver(o, context->Global(), "(1,func)()"); |
| 15182 | 15440 |
| 15183 foreign_context.Dispose(); | 15441 foreign_context.Dispose(); |
| 15184 } | 15442 } |
| OLD | NEW |