Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 11 matching lines...) Expand all Loading... | |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include <climits> | 28 #include <climits> |
| 29 #include <csignal> | 29 #include <csignal> |
| 30 #include <string> | 30 #include <string> |
| 31 #include <map> | 31 #include <map> |
| 32 #include <utility> | |
|
Michael Starzinger
2013/12/02 15:34:10
nit: Can we alpha-sort the system includes block?
Sven Panne
2013/12/02 17:30:53
Done.
| |
| 32 | 33 |
| 33 #include "v8.h" | 34 #include "v8.h" |
| 34 | 35 |
| 35 #if V8_OS_POSIX | 36 #if V8_OS_POSIX |
| 36 #include <unistd.h> // NOLINT | 37 #include <unistd.h> // NOLINT |
| 37 #endif | 38 #endif |
| 38 | 39 |
| 39 #include "api.h" | 40 #include "api.h" |
| 40 #include "arguments.h" | 41 #include "arguments.h" |
| 41 #include "cctest.h" | 42 #include "cctest.h" |
| 42 #include "compilation-cache.h" | 43 #include "compilation-cache.h" |
| 43 #include "cpu-profiler.h" | 44 #include "cpu-profiler.h" |
| 44 #include "execution.h" | 45 #include "execution.h" |
| 45 #include "isolate.h" | 46 #include "isolate.h" |
| 46 #include "objects.h" | 47 #include "objects.h" |
| 47 #include "parser.h" | 48 #include "parser.h" |
| 48 #include "platform.h" | 49 #include "platform.h" |
| 49 #include "snapshot.h" | 50 #include "snapshot.h" |
| 50 #include "unicode-inl.h" | 51 #include "unicode-inl.h" |
| 51 #include "utils.h" | 52 #include "utils.h" |
| 52 #include "vm-state.h" | 53 #include "vm-state.h" |
| 53 | 54 |
| 54 static const bool kLogThreading = false; | 55 static const bool kLogThreading = false; |
| 55 | 56 |
| 57 using std::pair; | |
| 58 | |
| 56 using ::v8::Boolean; | 59 using ::v8::Boolean; |
| 57 using ::v8::BooleanObject; | 60 using ::v8::BooleanObject; |
| 58 using ::v8::Context; | 61 using ::v8::Context; |
| 59 using ::v8::Extension; | 62 using ::v8::Extension; |
| 60 using ::v8::Function; | 63 using ::v8::Function; |
| 61 using ::v8::FunctionTemplate; | 64 using ::v8::FunctionTemplate; |
| 62 using ::v8::Handle; | 65 using ::v8::Handle; |
| 63 using ::v8::HandleScope; | 66 using ::v8::HandleScope; |
| 64 using ::v8::Local; | 67 using ::v8::Local; |
| 65 using ::v8::Message; | 68 using ::v8::Message; |
| (...skipping 3372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3438 int id() { return id_; } | 3441 int id() { return id_; } |
| 3439 void increment() { number_of_weak_calls_++; } | 3442 void increment() { number_of_weak_calls_++; } |
| 3440 int NumberOfWeakCalls() { return number_of_weak_calls_; } | 3443 int NumberOfWeakCalls() { return number_of_weak_calls_; } |
| 3441 private: | 3444 private: |
| 3442 int id_; | 3445 int id_; |
| 3443 int number_of_weak_calls_; | 3446 int number_of_weak_calls_; |
| 3444 }; | 3447 }; |
| 3445 | 3448 |
| 3446 | 3449 |
| 3447 template<typename T> | 3450 template<typename T> |
| 3448 static void WeakPointerCallback(v8::Isolate* isolate, | 3451 static void WeakPointerCallback( |
| 3449 Persistent<T>* handle, | 3452 const v8::WeakCallbackData<T, std::pair<v8::Persistent<T>*, |
| 3450 WeakCallCounter* counter) { | 3453 WeakCallCounter*> >& data) { |
| 3451 CHECK_EQ(1234, counter->id()); | 3454 CHECK_EQ(1234, data.GetParameter()->second->id()); |
| 3452 counter->increment(); | 3455 data.GetParameter()->second->increment(); |
| 3453 handle->Reset(); | 3456 data.GetParameter()->first->Reset(); |
| 3454 } | 3457 } |
| 3455 | 3458 |
| 3456 | 3459 |
| 3457 template<typename T> | 3460 template<typename T> |
| 3458 static UniqueId MakeUniqueId(const Persistent<T>& p) { | 3461 static UniqueId MakeUniqueId(const Persistent<T>& p) { |
| 3459 return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p))); | 3462 return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p))); |
| 3460 } | 3463 } |
| 3461 | 3464 |
| 3462 | 3465 |
| 3463 THREADED_TEST(ApiObjectGroups) { | 3466 THREADED_TEST(ApiObjectGroups) { |
| 3464 LocalContext env; | 3467 LocalContext env; |
| 3465 v8::Isolate* iso = env->GetIsolate(); | 3468 v8::Isolate* iso = env->GetIsolate(); |
| 3466 HandleScope scope(iso); | 3469 HandleScope scope(iso); |
| 3467 | 3470 |
| 3468 Persistent<Value> g1s1; | 3471 Persistent<Value> g1s1; |
| 3469 Persistent<Value> g1s2; | 3472 Persistent<Value> g1s2; |
| 3470 Persistent<Value> g1c1; | 3473 Persistent<Value> g1c1; |
| 3471 Persistent<Value> g2s1; | 3474 Persistent<Value> g2s1; |
| 3472 Persistent<Value> g2s2; | 3475 Persistent<Value> g2s2; |
| 3473 Persistent<Value> g2c1; | 3476 Persistent<Value> g2c1; |
| 3474 | 3477 |
| 3475 WeakCallCounter counter(1234); | 3478 WeakCallCounter counter(1234); |
| 3476 | 3479 |
| 3480 pair<Persistent<Value>*, WeakCallCounter*> g1s1p(&g1s1, &counter); | |
| 3481 pair<Persistent<Value>*, WeakCallCounter*> g1s2p(&g1s2, &counter); | |
| 3482 pair<Persistent<Value>*, WeakCallCounter*> g1c1p(&g1c1, &counter); | |
| 3483 pair<Persistent<Value>*, WeakCallCounter*> g2s1p(&g2s1, &counter); | |
| 3484 pair<Persistent<Value>*, WeakCallCounter*> g2s2p(&g2s2, &counter); | |
| 3485 pair<Persistent<Value>*, WeakCallCounter*> g2c1p(&g2c1, &counter); | |
| 3486 | |
| 3477 { | 3487 { |
| 3478 HandleScope scope(iso); | 3488 HandleScope scope(iso); |
| 3479 g1s1.Reset(iso, Object::New()); | 3489 g1s1.Reset(iso, Object::New()); |
| 3480 g1s2.Reset(iso, Object::New()); | 3490 g1s2.Reset(iso, Object::New()); |
| 3481 g1c1.Reset(iso, Object::New()); | 3491 g1c1.Reset(iso, Object::New()); |
| 3482 g1s1.MakeWeak(&counter, &WeakPointerCallback); | 3492 g1s1.SetWeak(&g1s1p, &WeakPointerCallback); |
| 3483 g1s2.MakeWeak(&counter, &WeakPointerCallback); | 3493 g1s2.SetWeak(&g1s2p, &WeakPointerCallback); |
| 3484 g1c1.MakeWeak(&counter, &WeakPointerCallback); | 3494 g1c1.SetWeak(&g1c1p, &WeakPointerCallback); |
| 3485 | 3495 |
| 3486 g2s1.Reset(iso, Object::New()); | 3496 g2s1.Reset(iso, Object::New()); |
| 3487 g2s2.Reset(iso, Object::New()); | 3497 g2s2.Reset(iso, Object::New()); |
| 3488 g2c1.Reset(iso, Object::New()); | 3498 g2c1.Reset(iso, Object::New()); |
| 3489 g2s1.MakeWeak(&counter, &WeakPointerCallback); | 3499 g2s1.SetWeak(&g2s1p, &WeakPointerCallback); |
| 3490 g2s2.MakeWeak(&counter, &WeakPointerCallback); | 3500 g2s2.SetWeak(&g2s2p, &WeakPointerCallback); |
| 3491 g2c1.MakeWeak(&counter, &WeakPointerCallback); | 3501 g2c1.SetWeak(&g2c1p, &WeakPointerCallback); |
| 3492 } | 3502 } |
| 3493 | 3503 |
| 3494 Persistent<Value> root(iso, g1s1); // make a root. | 3504 Persistent<Value> root(iso, g1s1); // make a root. |
| 3505 pair<Persistent<Value>*, WeakCallCounter*> rootp(&root, &counter); | |
| 3495 | 3506 |
| 3496 // Connect group 1 and 2, make a cycle. | 3507 // Connect group 1 and 2, make a cycle. |
| 3497 { | 3508 { |
| 3498 HandleScope scope(iso); | 3509 HandleScope scope(iso); |
| 3499 CHECK(Local<Object>::New(iso, g1s2.As<Object>())-> | 3510 CHECK(Local<Object>::New(iso, g1s2.As<Object>())-> |
| 3500 Set(0, Local<Value>::New(iso, g2s2))); | 3511 Set(0, Local<Value>::New(iso, g2s2))); |
| 3501 CHECK(Local<Object>::New(iso, g2s1.As<Object>())-> | 3512 CHECK(Local<Object>::New(iso, g2s1.As<Object>())-> |
| 3502 Set(0, Local<Value>::New(iso, g1s1))); | 3513 Set(0, Local<Value>::New(iso, g1s1))); |
| 3503 } | 3514 } |
| 3504 | 3515 |
| 3505 { | 3516 { |
| 3506 UniqueId id1 = MakeUniqueId(g1s1); | 3517 UniqueId id1 = MakeUniqueId(g1s1); |
| 3507 UniqueId id2 = MakeUniqueId(g2s2); | 3518 UniqueId id2 = MakeUniqueId(g2s2); |
| 3508 iso->SetObjectGroupId(g1s1, id1); | 3519 iso->SetObjectGroupId(g1s1, id1); |
| 3509 iso->SetObjectGroupId(g1s2, id1); | 3520 iso->SetObjectGroupId(g1s2, id1); |
| 3510 iso->SetReferenceFromGroup(id1, g1c1); | 3521 iso->SetReferenceFromGroup(id1, g1c1); |
| 3511 iso->SetObjectGroupId(g2s1, id2); | 3522 iso->SetObjectGroupId(g2s1, id2); |
| 3512 iso->SetObjectGroupId(g2s2, id2); | 3523 iso->SetObjectGroupId(g2s2, id2); |
| 3513 iso->SetReferenceFromGroup(id2, g2c1); | 3524 iso->SetReferenceFromGroup(id2, g2c1); |
| 3514 } | 3525 } |
| 3515 // Do a single full GC, ensure incremental marking is stopped. | 3526 // Do a single full GC, ensure incremental marking is stopped. |
| 3516 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>( | 3527 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>( |
| 3517 iso)->heap(); | 3528 iso)->heap(); |
| 3518 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 3529 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
| 3519 | 3530 |
| 3520 // All object should be alive. | 3531 // All object should be alive. |
| 3521 CHECK_EQ(0, counter.NumberOfWeakCalls()); | 3532 CHECK_EQ(0, counter.NumberOfWeakCalls()); |
| 3522 | 3533 |
| 3523 // Weaken the root. | 3534 // Weaken the root. |
| 3524 root.MakeWeak(&counter, &WeakPointerCallback); | 3535 root.SetWeak(&rootp, &WeakPointerCallback); |
| 3525 // But make children strong roots---all the objects (except for children) | 3536 // But make children strong roots---all the objects (except for children) |
| 3526 // should be collectable now. | 3537 // should be collectable now. |
| 3527 g1c1.ClearWeak(); | 3538 g1c1.ClearWeak(); |
| 3528 g2c1.ClearWeak(); | 3539 g2c1.ClearWeak(); |
| 3529 | 3540 |
| 3530 // Groups are deleted, rebuild groups. | 3541 // Groups are deleted, rebuild groups. |
| 3531 { | 3542 { |
| 3532 UniqueId id1 = MakeUniqueId(g1s1); | 3543 UniqueId id1 = MakeUniqueId(g1s1); |
| 3533 UniqueId id2 = MakeUniqueId(g2s2); | 3544 UniqueId id2 = MakeUniqueId(g2s2); |
| 3534 iso->SetObjectGroupId(g1s1, id1); | 3545 iso->SetObjectGroupId(g1s1, id1); |
| 3535 iso->SetObjectGroupId(g1s2, id1); | 3546 iso->SetObjectGroupId(g1s2, id1); |
| 3536 iso->SetReferenceFromGroup(id1, g1c1); | 3547 iso->SetReferenceFromGroup(id1, g1c1); |
| 3537 iso->SetObjectGroupId(g2s1, id2); | 3548 iso->SetObjectGroupId(g2s1, id2); |
| 3538 iso->SetObjectGroupId(g2s2, id2); | 3549 iso->SetObjectGroupId(g2s2, id2); |
| 3539 iso->SetReferenceFromGroup(id2, g2c1); | 3550 iso->SetReferenceFromGroup(id2, g2c1); |
| 3540 } | 3551 } |
| 3541 | 3552 |
| 3542 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 3553 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
| 3543 | 3554 |
| 3544 // All objects should be gone. 5 global handles in total. | 3555 // All objects should be gone. 5 global handles in total. |
| 3545 CHECK_EQ(5, counter.NumberOfWeakCalls()); | 3556 CHECK_EQ(5, counter.NumberOfWeakCalls()); |
| 3546 | 3557 |
| 3547 // And now make children weak again and collect them. | 3558 // And now make children weak again and collect them. |
| 3548 g1c1.MakeWeak(&counter, &WeakPointerCallback); | 3559 g1c1.SetWeak(&g1c1p, &WeakPointerCallback); |
| 3549 g2c1.MakeWeak(&counter, &WeakPointerCallback); | 3560 g2c1.SetWeak(&g2c1p, &WeakPointerCallback); |
| 3550 | 3561 |
| 3551 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 3562 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
| 3552 CHECK_EQ(7, counter.NumberOfWeakCalls()); | 3563 CHECK_EQ(7, counter.NumberOfWeakCalls()); |
| 3553 } | 3564 } |
| 3554 | 3565 |
| 3555 | 3566 |
| 3556 THREADED_TEST(ApiObjectGroupsForSubtypes) { | 3567 THREADED_TEST(ApiObjectGroupsForSubtypes) { |
| 3557 LocalContext env; | 3568 LocalContext env; |
| 3558 v8::Isolate* iso = env->GetIsolate(); | 3569 v8::Isolate* iso = env->GetIsolate(); |
| 3559 HandleScope scope(iso); | 3570 HandleScope scope(iso); |
| 3560 | 3571 |
| 3561 Persistent<Object> g1s1; | 3572 Persistent<Object> g1s1; |
| 3562 Persistent<String> g1s2; | 3573 Persistent<String> g1s2; |
| 3563 Persistent<String> g1c1; | 3574 Persistent<String> g1c1; |
| 3564 Persistent<Object> g2s1; | 3575 Persistent<Object> g2s1; |
| 3565 Persistent<String> g2s2; | 3576 Persistent<String> g2s2; |
| 3566 Persistent<String> g2c1; | 3577 Persistent<String> g2c1; |
| 3567 | 3578 |
| 3568 WeakCallCounter counter(1234); | 3579 WeakCallCounter counter(1234); |
| 3569 | 3580 |
| 3581 pair<Persistent<Object>*, WeakCallCounter*> g1s1p(&g1s1, &counter); | |
| 3582 pair<Persistent<String>*, WeakCallCounter*> g1s2p(&g1s2, &counter); | |
| 3583 pair<Persistent<String>*, WeakCallCounter*> g1c1p(&g1c1, &counter); | |
| 3584 pair<Persistent<Object>*, WeakCallCounter*> g2s1p(&g2s1, &counter); | |
| 3585 pair<Persistent<String>*, WeakCallCounter*> g2s2p(&g2s2, &counter); | |
| 3586 pair<Persistent<String>*, WeakCallCounter*> g2c1p(&g2c1, &counter); | |
| 3587 | |
| 3570 { | 3588 { |
| 3571 HandleScope scope(iso); | 3589 HandleScope scope(iso); |
| 3572 g1s1.Reset(iso, Object::New()); | 3590 g1s1.Reset(iso, Object::New()); |
| 3573 g1s2.Reset(iso, String::NewFromUtf8(iso, "foo1")); | 3591 g1s2.Reset(iso, String::NewFromUtf8(iso, "foo1")); |
| 3574 g1c1.Reset(iso, String::NewFromUtf8(iso, "foo2")); | 3592 g1c1.Reset(iso, String::NewFromUtf8(iso, "foo2")); |
| 3575 g1s1.MakeWeak(&counter, &WeakPointerCallback); | 3593 g1s1.SetWeak(&g1s1p, &WeakPointerCallback); |
| 3576 g1s2.MakeWeak(&counter, &WeakPointerCallback); | 3594 g1s2.SetWeak(&g1s2p, &WeakPointerCallback); |
| 3577 g1c1.MakeWeak(&counter, &WeakPointerCallback); | 3595 g1c1.SetWeak(&g1c1p, &WeakPointerCallback); |
| 3578 | 3596 |
| 3579 g2s1.Reset(iso, Object::New()); | 3597 g2s1.Reset(iso, Object::New()); |
| 3580 g2s2.Reset(iso, String::NewFromUtf8(iso, "foo3")); | 3598 g2s2.Reset(iso, String::NewFromUtf8(iso, "foo3")); |
| 3581 g2c1.Reset(iso, String::NewFromUtf8(iso, "foo4")); | 3599 g2c1.Reset(iso, String::NewFromUtf8(iso, "foo4")); |
| 3582 g2s1.MakeWeak(&counter, &WeakPointerCallback); | 3600 g2s1.SetWeak(&g2s1p, &WeakPointerCallback); |
| 3583 g2s2.MakeWeak(&counter, &WeakPointerCallback); | 3601 g2s2.SetWeak(&g2s2p, &WeakPointerCallback); |
| 3584 g2c1.MakeWeak(&counter, &WeakPointerCallback); | 3602 g2c1.SetWeak(&g2c1p, &WeakPointerCallback); |
| 3585 } | 3603 } |
| 3586 | 3604 |
| 3587 Persistent<Value> root(iso, g1s1); // make a root. | 3605 Persistent<Value> root(iso, g1s1); // make a root. |
| 3606 pair<Persistent<Value>*, WeakCallCounter*> rootp(&root, &counter); | |
| 3588 | 3607 |
| 3589 // Connect group 1 and 2, make a cycle. | 3608 // Connect group 1 and 2, make a cycle. |
| 3590 { | 3609 { |
| 3591 HandleScope scope(iso); | 3610 HandleScope scope(iso); |
| 3592 CHECK(Local<Object>::New(iso, g1s1)->Set(0, Local<Object>::New(iso, g2s1))); | 3611 CHECK(Local<Object>::New(iso, g1s1)->Set(0, Local<Object>::New(iso, g2s1))); |
| 3593 CHECK(Local<Object>::New(iso, g2s1)->Set(0, Local<Object>::New(iso, g1s1))); | 3612 CHECK(Local<Object>::New(iso, g2s1)->Set(0, Local<Object>::New(iso, g1s1))); |
| 3594 } | 3613 } |
| 3595 | 3614 |
| 3596 { | 3615 { |
| 3597 UniqueId id1 = MakeUniqueId(g1s1); | 3616 UniqueId id1 = MakeUniqueId(g1s1); |
| 3598 UniqueId id2 = MakeUniqueId(g2s2); | 3617 UniqueId id2 = MakeUniqueId(g2s2); |
| 3599 iso->SetObjectGroupId(g1s1, id1); | 3618 iso->SetObjectGroupId(g1s1, id1); |
| 3600 iso->SetObjectGroupId(g1s2, id1); | 3619 iso->SetObjectGroupId(g1s2, id1); |
| 3601 iso->SetReference(g1s1, g1c1); | 3620 iso->SetReference(g1s1, g1c1); |
| 3602 iso->SetObjectGroupId(g2s1, id2); | 3621 iso->SetObjectGroupId(g2s1, id2); |
| 3603 iso->SetObjectGroupId(g2s2, id2); | 3622 iso->SetObjectGroupId(g2s2, id2); |
| 3604 iso->SetReferenceFromGroup(id2, g2c1); | 3623 iso->SetReferenceFromGroup(id2, g2c1); |
| 3605 } | 3624 } |
| 3606 // Do a single full GC, ensure incremental marking is stopped. | 3625 // Do a single full GC, ensure incremental marking is stopped. |
| 3607 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>( | 3626 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>( |
| 3608 iso)->heap(); | 3627 iso)->heap(); |
| 3609 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 3628 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
| 3610 | 3629 |
| 3611 // All object should be alive. | 3630 // All object should be alive. |
| 3612 CHECK_EQ(0, counter.NumberOfWeakCalls()); | 3631 CHECK_EQ(0, counter.NumberOfWeakCalls()); |
| 3613 | 3632 |
| 3614 // Weaken the root. | 3633 // Weaken the root. |
| 3615 root.MakeWeak(&counter, &WeakPointerCallback); | 3634 root.SetWeak(&rootp, &WeakPointerCallback); |
| 3616 // But make children strong roots---all the objects (except for children) | 3635 // But make children strong roots---all the objects (except for children) |
| 3617 // should be collectable now. | 3636 // should be collectable now. |
| 3618 g1c1.ClearWeak(); | 3637 g1c1.ClearWeak(); |
| 3619 g2c1.ClearWeak(); | 3638 g2c1.ClearWeak(); |
| 3620 | 3639 |
| 3621 // Groups are deleted, rebuild groups. | 3640 // Groups are deleted, rebuild groups. |
| 3622 { | 3641 { |
| 3623 UniqueId id1 = MakeUniqueId(g1s1); | 3642 UniqueId id1 = MakeUniqueId(g1s1); |
| 3624 UniqueId id2 = MakeUniqueId(g2s2); | 3643 UniqueId id2 = MakeUniqueId(g2s2); |
| 3625 iso->SetObjectGroupId(g1s1, id1); | 3644 iso->SetObjectGroupId(g1s1, id1); |
| 3626 iso->SetObjectGroupId(g1s2, id1); | 3645 iso->SetObjectGroupId(g1s2, id1); |
| 3627 iso->SetReference(g1s1, g1c1); | 3646 iso->SetReference(g1s1, g1c1); |
| 3628 iso->SetObjectGroupId(g2s1, id2); | 3647 iso->SetObjectGroupId(g2s1, id2); |
| 3629 iso->SetObjectGroupId(g2s2, id2); | 3648 iso->SetObjectGroupId(g2s2, id2); |
| 3630 iso->SetReferenceFromGroup(id2, g2c1); | 3649 iso->SetReferenceFromGroup(id2, g2c1); |
| 3631 } | 3650 } |
| 3632 | 3651 |
| 3633 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 3652 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
| 3634 | 3653 |
| 3635 // All objects should be gone. 5 global handles in total. | 3654 // All objects should be gone. 5 global handles in total. |
| 3636 CHECK_EQ(5, counter.NumberOfWeakCalls()); | 3655 CHECK_EQ(5, counter.NumberOfWeakCalls()); |
| 3637 | 3656 |
| 3638 // And now make children weak again and collect them. | 3657 // And now make children weak again and collect them. |
| 3639 g1c1.MakeWeak(&counter, &WeakPointerCallback); | 3658 g1c1.SetWeak(&g1c1p, &WeakPointerCallback); |
| 3640 g2c1.MakeWeak(&counter, &WeakPointerCallback); | 3659 g2c1.SetWeak(&g2c1p, &WeakPointerCallback); |
| 3641 | 3660 |
| 3642 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 3661 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
| 3643 CHECK_EQ(7, counter.NumberOfWeakCalls()); | 3662 CHECK_EQ(7, counter.NumberOfWeakCalls()); |
| 3644 } | 3663 } |
| 3645 | 3664 |
| 3646 | 3665 |
| 3647 THREADED_TEST(ApiObjectGroupsCycle) { | 3666 THREADED_TEST(ApiObjectGroupsCycle) { |
| 3648 LocalContext env; | 3667 LocalContext env; |
| 3649 v8::Isolate* iso = env->GetIsolate(); | 3668 v8::Isolate* iso = env->GetIsolate(); |
| 3650 HandleScope scope(iso); | 3669 HandleScope scope(iso); |
| 3651 | 3670 |
| 3652 WeakCallCounter counter(1234); | 3671 WeakCallCounter counter(1234); |
| 3653 | 3672 |
| 3654 Persistent<Value> g1s1; | 3673 Persistent<Value> g1s1; |
| 3655 Persistent<Value> g1s2; | 3674 Persistent<Value> g1s2; |
| 3656 Persistent<Value> g2s1; | 3675 Persistent<Value> g2s1; |
| 3657 Persistent<Value> g2s2; | 3676 Persistent<Value> g2s2; |
| 3658 Persistent<Value> g3s1; | 3677 Persistent<Value> g3s1; |
| 3659 Persistent<Value> g3s2; | 3678 Persistent<Value> g3s2; |
| 3660 Persistent<Value> g4s1; | 3679 Persistent<Value> g4s1; |
| 3661 Persistent<Value> g4s2; | 3680 Persistent<Value> g4s2; |
| 3662 | 3681 |
| 3682 pair<Persistent<Value>*, WeakCallCounter*> g1s1p(&g1s1, &counter); | |
| 3683 pair<Persistent<Value>*, WeakCallCounter*> g1s2p(&g1s2, &counter); | |
| 3684 pair<Persistent<Value>*, WeakCallCounter*> g2s1p(&g2s1, &counter); | |
| 3685 pair<Persistent<Value>*, WeakCallCounter*> g2s2p(&g2s2, &counter); | |
| 3686 pair<Persistent<Value>*, WeakCallCounter*> g3s1p(&g3s1, &counter); | |
| 3687 pair<Persistent<Value>*, WeakCallCounter*> g3s2p(&g3s2, &counter); | |
| 3688 pair<Persistent<Value>*, WeakCallCounter*> g4s1p(&g4s1, &counter); | |
| 3689 pair<Persistent<Value>*, WeakCallCounter*> g4s2p(&g4s2, &counter); | |
| 3690 | |
| 3663 { | 3691 { |
| 3664 HandleScope scope(iso); | 3692 HandleScope scope(iso); |
| 3665 g1s1.Reset(iso, Object::New()); | 3693 g1s1.Reset(iso, Object::New()); |
| 3666 g1s2.Reset(iso, Object::New()); | 3694 g1s2.Reset(iso, Object::New()); |
| 3667 g1s1.MakeWeak(&counter, &WeakPointerCallback); | 3695 g1s1.SetWeak(&g1s1p, &WeakPointerCallback); |
| 3668 g1s2.MakeWeak(&counter, &WeakPointerCallback); | 3696 g1s2.SetWeak(&g1s2p, &WeakPointerCallback); |
| 3669 CHECK(g1s1.IsWeak()); | 3697 CHECK(g1s1.IsWeak()); |
| 3670 CHECK(g1s2.IsWeak()); | 3698 CHECK(g1s2.IsWeak()); |
| 3671 | 3699 |
| 3672 g2s1.Reset(iso, Object::New()); | 3700 g2s1.Reset(iso, Object::New()); |
| 3673 g2s2.Reset(iso, Object::New()); | 3701 g2s2.Reset(iso, Object::New()); |
| 3674 g2s1.MakeWeak(&counter, &WeakPointerCallback); | 3702 g2s1.SetWeak(&g2s1p, &WeakPointerCallback); |
| 3675 g2s2.MakeWeak(&counter, &WeakPointerCallback); | 3703 g2s2.SetWeak(&g2s2p, &WeakPointerCallback); |
| 3676 CHECK(g2s1.IsWeak()); | 3704 CHECK(g2s1.IsWeak()); |
| 3677 CHECK(g2s2.IsWeak()); | 3705 CHECK(g2s2.IsWeak()); |
| 3678 | 3706 |
| 3679 g3s1.Reset(iso, Object::New()); | 3707 g3s1.Reset(iso, Object::New()); |
| 3680 g3s2.Reset(iso, Object::New()); | 3708 g3s2.Reset(iso, Object::New()); |
| 3681 g3s1.MakeWeak(&counter, &WeakPointerCallback); | 3709 g3s1.SetWeak(&g3s1p, &WeakPointerCallback); |
| 3682 g3s2.MakeWeak(&counter, &WeakPointerCallback); | 3710 g3s2.SetWeak(&g3s2p, &WeakPointerCallback); |
| 3683 CHECK(g3s1.IsWeak()); | 3711 CHECK(g3s1.IsWeak()); |
| 3684 CHECK(g3s2.IsWeak()); | 3712 CHECK(g3s2.IsWeak()); |
| 3685 | 3713 |
| 3686 g4s1.Reset(iso, Object::New()); | 3714 g4s1.Reset(iso, Object::New()); |
| 3687 g4s2.Reset(iso, Object::New()); | 3715 g4s2.Reset(iso, Object::New()); |
| 3688 g4s1.MakeWeak(&counter, &WeakPointerCallback); | 3716 g4s1.SetWeak(&g4s1p, &WeakPointerCallback); |
| 3689 g4s2.MakeWeak(&counter, &WeakPointerCallback); | 3717 g4s2.SetWeak(&g4s2p, &WeakPointerCallback); |
| 3690 CHECK(g4s1.IsWeak()); | 3718 CHECK(g4s1.IsWeak()); |
| 3691 CHECK(g4s2.IsWeak()); | 3719 CHECK(g4s2.IsWeak()); |
| 3692 } | 3720 } |
| 3693 | 3721 |
| 3694 Persistent<Value> root(iso, g1s1); // make a root. | 3722 Persistent<Value> root(iso, g1s1); // make a root. |
| 3723 pair<Persistent<Value>*, WeakCallCounter*> rootp(&root, &counter); | |
| 3695 | 3724 |
| 3696 // Connect groups. We're building the following cycle: | 3725 // Connect groups. We're building the following cycle: |
| 3697 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other | 3726 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other |
| 3698 // groups. | 3727 // groups. |
| 3699 { | 3728 { |
| 3700 UniqueId id1 = MakeUniqueId(g1s1); | 3729 UniqueId id1 = MakeUniqueId(g1s1); |
| 3701 UniqueId id2 = MakeUniqueId(g2s1); | 3730 UniqueId id2 = MakeUniqueId(g2s1); |
| 3702 UniqueId id3 = MakeUniqueId(g3s1); | 3731 UniqueId id3 = MakeUniqueId(g3s1); |
| 3703 UniqueId id4 = MakeUniqueId(g4s1); | 3732 UniqueId id4 = MakeUniqueId(g4s1); |
| 3704 iso->SetObjectGroupId(g1s1, id1); | 3733 iso->SetObjectGroupId(g1s1, id1); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 3716 } | 3745 } |
| 3717 // Do a single full GC | 3746 // Do a single full GC |
| 3718 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>( | 3747 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>( |
| 3719 iso)->heap(); | 3748 iso)->heap(); |
| 3720 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 3749 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
| 3721 | 3750 |
| 3722 // All object should be alive. | 3751 // All object should be alive. |
| 3723 CHECK_EQ(0, counter.NumberOfWeakCalls()); | 3752 CHECK_EQ(0, counter.NumberOfWeakCalls()); |
| 3724 | 3753 |
| 3725 // Weaken the root. | 3754 // Weaken the root. |
| 3726 root.MakeWeak(&counter, &WeakPointerCallback); | 3755 root.SetWeak(&rootp, &WeakPointerCallback); |
| 3727 | 3756 |
| 3728 // Groups are deleted, rebuild groups. | 3757 // Groups are deleted, rebuild groups. |
| 3729 { | 3758 { |
| 3730 UniqueId id1 = MakeUniqueId(g1s1); | 3759 UniqueId id1 = MakeUniqueId(g1s1); |
| 3731 UniqueId id2 = MakeUniqueId(g2s1); | 3760 UniqueId id2 = MakeUniqueId(g2s1); |
| 3732 UniqueId id3 = MakeUniqueId(g3s1); | 3761 UniqueId id3 = MakeUniqueId(g3s1); |
| 3733 UniqueId id4 = MakeUniqueId(g4s1); | 3762 UniqueId id4 = MakeUniqueId(g4s1); |
| 3734 iso->SetObjectGroupId(g1s1, id1); | 3763 iso->SetObjectGroupId(g1s1, id1); |
| 3735 iso->SetObjectGroupId(g1s2, id1); | 3764 iso->SetObjectGroupId(g1s2, id1); |
| 3736 iso->SetReferenceFromGroup(id1, g2s1); | 3765 iso->SetReferenceFromGroup(id1, g2s1); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 3763 | 3792 |
| 3764 WeakCallCounter counter(1234); | 3793 WeakCallCounter counter(1234); |
| 3765 | 3794 |
| 3766 Persistent<Value> g1s1; | 3795 Persistent<Value> g1s1; |
| 3767 Persistent<Value> g1s2; | 3796 Persistent<Value> g1s2; |
| 3768 Persistent<Value> g2s1; | 3797 Persistent<Value> g2s1; |
| 3769 Persistent<Value> g2s2; | 3798 Persistent<Value> g2s2; |
| 3770 Persistent<Value> g3s1; | 3799 Persistent<Value> g3s1; |
| 3771 Persistent<Value> g3s2; | 3800 Persistent<Value> g3s2; |
| 3772 | 3801 |
| 3802 pair<Persistent<Value>*, WeakCallCounter*> g1s1p(&g1s1, &counter); | |
| 3803 pair<Persistent<Value>*, WeakCallCounter*> g1s2p(&g1s2, &counter); | |
| 3804 pair<Persistent<Value>*, WeakCallCounter*> g2s1p(&g2s1, &counter); | |
| 3805 pair<Persistent<Value>*, WeakCallCounter*> g2s2p(&g2s2, &counter); | |
| 3806 pair<Persistent<Value>*, WeakCallCounter*> g3s1p(&g3s1, &counter); | |
| 3807 pair<Persistent<Value>*, WeakCallCounter*> g3s2p(&g3s2, &counter); | |
| 3808 | |
| 3773 { | 3809 { |
| 3774 HandleScope scope(iso); | 3810 HandleScope scope(iso); |
| 3775 g1s1.Reset(iso, Object::New()); | 3811 g1s1.Reset(iso, Object::New()); |
| 3776 g1s2.Reset(iso, Object::New()); | 3812 g1s2.Reset(iso, Object::New()); |
| 3777 g1s1.MakeWeak(&counter, &WeakPointerCallback); | 3813 g1s1.SetWeak(&g1s1p, &WeakPointerCallback); |
| 3778 g1s2.MakeWeak(&counter, &WeakPointerCallback); | 3814 g1s2.SetWeak(&g1s2p, &WeakPointerCallback); |
| 3779 | 3815 |
| 3780 g2s1.Reset(iso, Object::New()); | 3816 g2s1.Reset(iso, Object::New()); |
| 3781 g2s2.Reset(iso, Object::New()); | 3817 g2s2.Reset(iso, Object::New()); |
| 3782 g2s1.MakeWeak(&counter, &WeakPointerCallback); | 3818 g2s1.SetWeak(&g2s1p, &WeakPointerCallback); |
| 3783 g2s2.MakeWeak(&counter, &WeakPointerCallback); | 3819 g2s2.SetWeak(&g2s2p, &WeakPointerCallback); |
| 3784 | 3820 |
| 3785 g3s1.Reset(iso, Object::New()); | 3821 g3s1.Reset(iso, Object::New()); |
| 3786 g3s2.Reset(iso, Object::New()); | 3822 g3s2.Reset(iso, Object::New()); |
| 3787 g3s1.MakeWeak(&counter, &WeakPointerCallback); | 3823 g3s1.SetWeak(&g3s1p, &WeakPointerCallback); |
| 3788 g3s2.MakeWeak(&counter, &WeakPointerCallback); | 3824 g3s2.SetWeak(&g3s2p, &WeakPointerCallback); |
| 3789 } | 3825 } |
| 3790 | 3826 |
| 3791 // Make a root. | 3827 // Make a root. |
| 3792 Persistent<Value> root(iso, g1s1); | 3828 Persistent<Value> root(iso, g1s1); |
| 3829 pair<Persistent<Value>*, WeakCallCounter*> rootp(&root, &counter); | |
| 3793 root.MarkPartiallyDependent(); | 3830 root.MarkPartiallyDependent(); |
| 3794 | 3831 |
| 3795 // Connect groups. We're building the following cycle: | 3832 // Connect groups. We're building the following cycle: |
| 3796 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other | 3833 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other |
| 3797 // groups. | 3834 // groups. |
| 3798 { | 3835 { |
| 3799 HandleScope handle_scope(iso); | 3836 HandleScope handle_scope(iso); |
| 3800 g1s1.MarkPartiallyDependent(); | 3837 g1s1.MarkPartiallyDependent(); |
| 3801 g1s2.MarkPartiallyDependent(); | 3838 g1s2.MarkPartiallyDependent(); |
| 3802 g2s1.MarkPartiallyDependent(); | 3839 g2s1.MarkPartiallyDependent(); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 3818 } | 3855 } |
| 3819 | 3856 |
| 3820 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>( | 3857 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>( |
| 3821 iso)->heap(); | 3858 iso)->heap(); |
| 3822 heap->CollectGarbage(i::NEW_SPACE); | 3859 heap->CollectGarbage(i::NEW_SPACE); |
| 3823 | 3860 |
| 3824 // All objects should be alive. | 3861 // All objects should be alive. |
| 3825 CHECK_EQ(0, counter.NumberOfWeakCalls()); | 3862 CHECK_EQ(0, counter.NumberOfWeakCalls()); |
| 3826 | 3863 |
| 3827 // Weaken the root. | 3864 // Weaken the root. |
| 3828 root.MakeWeak(&counter, &WeakPointerCallback); | 3865 root.SetWeak(&rootp, &WeakPointerCallback); |
| 3829 root.MarkPartiallyDependent(); | 3866 root.MarkPartiallyDependent(); |
| 3830 | 3867 |
| 3831 // Groups are deleted, rebuild groups. | 3868 // Groups are deleted, rebuild groups. |
| 3832 { | 3869 { |
| 3833 HandleScope handle_scope(iso); | 3870 HandleScope handle_scope(iso); |
| 3834 g1s1.MarkPartiallyDependent(); | 3871 g1s1.MarkPartiallyDependent(); |
| 3835 g1s2.MarkPartiallyDependent(); | 3872 g1s2.MarkPartiallyDependent(); |
| 3836 g2s1.MarkPartiallyDependent(); | 3873 g2s1.MarkPartiallyDependent(); |
| 3837 g2s2.MarkPartiallyDependent(); | 3874 g2s2.MarkPartiallyDependent(); |
| 3838 g3s1.MarkPartiallyDependent(); | 3875 g3s1.MarkPartiallyDependent(); |
| (...skipping 3103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6942 v8::V8::AddMessageListener(MissingScriptInfoMessageListener); | 6979 v8::V8::AddMessageListener(MissingScriptInfoMessageListener); |
| 6943 Script::Compile(v8_str("throw Error()"))->Run(); | 6980 Script::Compile(v8_str("throw Error()"))->Run(); |
| 6944 v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener); | 6981 v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener); |
| 6945 } | 6982 } |
| 6946 | 6983 |
| 6947 | 6984 |
| 6948 int global_index = 0; | 6985 int global_index = 0; |
| 6949 | 6986 |
| 6950 class Snorkel { | 6987 class Snorkel { |
| 6951 public: | 6988 public: |
| 6952 Snorkel() { index_ = global_index++; } | 6989 explicit Snorkel(v8::Persistent<v8::Object>* prev) |
| 6990 : prev_(prev), index_(global_index++) { } | |
| 6991 v8::Persistent<v8::Object>* prev_; | |
| 6953 int index_; | 6992 int index_; |
| 6954 }; | 6993 }; |
| 6955 | 6994 |
| 6956 class Whammy { | 6995 class Whammy { |
| 6957 public: | 6996 public: |
| 6958 explicit Whammy(v8::Isolate* isolate) : cursor_(0), isolate_(isolate) { } | 6997 explicit Whammy(v8::Isolate* isolate) : cursor_(0), isolate_(isolate) { } |
| 6959 ~Whammy() { script_.Reset(); } | 6998 ~Whammy() { script_.Reset(); } |
| 6960 v8::Handle<Script> getScript() { | 6999 v8::Handle<Script> getScript() { |
| 6961 if (script_.IsEmpty()) script_.Reset(isolate_, v8_compile("({}).blammo")); | 7000 if (script_.IsEmpty()) script_.Reset(isolate_, v8_compile("({}).blammo")); |
| 6962 return Local<Script>::New(isolate_, script_); | 7001 return Local<Script>::New(isolate_, script_); |
| 6963 } | 7002 } |
| 6964 | 7003 |
| 6965 public: | 7004 public: |
| 6966 static const int kObjectCount = 256; | 7005 static const int kObjectCount = 256; |
| 6967 int cursor_; | 7006 int cursor_; |
| 6968 v8::Isolate* isolate_; | 7007 v8::Isolate* isolate_; |
| 6969 v8::Persistent<v8::Object> objects_[kObjectCount]; | 7008 v8::Persistent<v8::Object> objects_[kObjectCount]; |
| 6970 v8::Persistent<Script> script_; | 7009 v8::Persistent<Script> script_; |
| 6971 }; | 7010 }; |
| 6972 | 7011 |
| 6973 static void HandleWeakReference(v8::Isolate* isolate, | 7012 static void HandleWeakReference( |
| 6974 v8::Persistent<v8::Value>* obj, | 7013 const v8::WeakCallbackData<v8::Object, Snorkel>& data) { |
| 6975 Snorkel* snorkel) { | 7014 data.GetParameter()->prev_->ClearWeak(); |
| 6976 delete snorkel; | 7015 delete data.GetParameter(); |
| 6977 obj->ClearWeak(); | |
| 6978 } | 7016 } |
| 6979 | 7017 |
| 6980 void WhammyPropertyGetter(Local<String> name, | 7018 void WhammyPropertyGetter(Local<String> name, |
| 6981 const v8::PropertyCallbackInfo<v8::Value>& info) { | 7019 const v8::PropertyCallbackInfo<v8::Value>& info) { |
| 6982 Whammy* whammy = | 7020 Whammy* whammy = |
| 6983 static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value()); | 7021 static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value()); |
| 6984 | 7022 |
| 6985 v8::Persistent<v8::Object>& prev = whammy->objects_[whammy->cursor_]; | 7023 v8::Persistent<v8::Object>& prev = whammy->objects_[whammy->cursor_]; |
| 6986 | 7024 |
| 6987 v8::Handle<v8::Object> obj = v8::Object::New(); | 7025 v8::Handle<v8::Object> obj = v8::Object::New(); |
| 6988 if (!prev.IsEmpty()) { | 7026 if (!prev.IsEmpty()) { |
| 6989 v8::Local<v8::Object>::New(info.GetIsolate(), prev) | 7027 v8::Local<v8::Object>::New(info.GetIsolate(), prev) |
| 6990 ->Set(v8_str("next"), obj); | 7028 ->Set(v8_str("next"), obj); |
| 6991 prev.MakeWeak<Value, Snorkel>(new Snorkel(), &HandleWeakReference); | 7029 prev.SetWeak(new Snorkel(&prev), &HandleWeakReference); |
| 6992 } | 7030 } |
| 6993 whammy->objects_[whammy->cursor_].Reset(info.GetIsolate(), obj); | 7031 whammy->objects_[whammy->cursor_].Reset(info.GetIsolate(), obj); |
| 6994 whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount; | 7032 whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount; |
| 6995 info.GetReturnValue().Set(whammy->getScript()->Run()); | 7033 info.GetReturnValue().Set(whammy->getScript()->Run()); |
| 6996 } | 7034 } |
| 6997 | 7035 |
| 6998 | 7036 |
| 6999 THREADED_TEST(WeakReference) { | 7037 THREADED_TEST(WeakReference) { |
| 7000 v8::HandleScope handle_scope(CcTest::isolate()); | 7038 v8::HandleScope handle_scope(CcTest::isolate()); |
| 7001 v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New(); | 7039 v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New(); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 7019 " last = obj;" | 7057 " last = obj;" |
| 7020 "}" | 7058 "}" |
| 7021 "gc();" | 7059 "gc();" |
| 7022 "4"; | 7060 "4"; |
| 7023 v8::Handle<Value> result = CompileRun(code); | 7061 v8::Handle<Value> result = CompileRun(code); |
| 7024 CHECK_EQ(4.0, result->NumberValue()); | 7062 CHECK_EQ(4.0, result->NumberValue()); |
| 7025 delete whammy; | 7063 delete whammy; |
| 7026 } | 7064 } |
| 7027 | 7065 |
| 7028 | 7066 |
| 7029 static void DisposeAndSetFlag(v8::Isolate* isolate, | 7067 static void DisposeAndSetFlag( |
| 7030 v8::Persistent<v8::Object>* obj, | 7068 const v8::WeakCallbackData<v8::Object, |
| 7031 bool* data) { | 7069 pair<v8::Persistent<v8::Object>*, |
| 7032 obj->Reset(); | 7070 bool> >& data) { |
| 7033 *(data) = true; | 7071 data.GetParameter()->first->Reset(); |
| 7072 data.GetParameter()->second = true; | |
| 7034 } | 7073 } |
| 7035 | 7074 |
| 7036 | 7075 |
| 7037 THREADED_TEST(IndependentWeakHandle) { | 7076 THREADED_TEST(IndependentWeakHandle) { |
| 7038 v8::Isolate* iso = CcTest::isolate(); | 7077 v8::Isolate* iso = CcTest::isolate(); |
| 7039 v8::HandleScope scope(iso); | 7078 v8::HandleScope scope(iso); |
| 7040 v8::Handle<Context> context = Context::New(iso); | 7079 v8::Handle<Context> context = Context::New(iso); |
| 7041 Context::Scope context_scope(context); | 7080 Context::Scope context_scope(context); |
| 7042 | 7081 |
| 7043 v8::Persistent<v8::Object> object_a, object_b; | 7082 v8::Persistent<v8::Object> object_a, object_b; |
| 7044 | 7083 |
| 7045 { | 7084 { |
| 7046 v8::HandleScope handle_scope(iso); | 7085 v8::HandleScope handle_scope(iso); |
| 7047 object_a.Reset(iso, v8::Object::New()); | 7086 object_a.Reset(iso, v8::Object::New()); |
| 7048 object_b.Reset(iso, v8::Object::New()); | 7087 object_b.Reset(iso, v8::Object::New()); |
| 7049 } | 7088 } |
| 7050 | 7089 |
| 7051 bool object_a_disposed = false; | 7090 pair<v8::Persistent<v8::Object>*, bool> object_a_pair(&object_a, false); |
| 7052 bool object_b_disposed = false; | 7091 pair<v8::Persistent<v8::Object>*, bool> object_b_pair(&object_b, false); |
| 7053 object_a.MakeWeak(&object_a_disposed, &DisposeAndSetFlag); | 7092 object_a.SetWeak(&object_a_pair, &DisposeAndSetFlag); |
| 7054 object_b.MakeWeak(&object_b_disposed, &DisposeAndSetFlag); | 7093 object_b.SetWeak(&object_b_pair, &DisposeAndSetFlag); |
| 7055 CHECK(!object_b.IsIndependent()); | 7094 CHECK(!object_b.IsIndependent()); |
| 7056 object_a.MarkIndependent(); | 7095 object_a.MarkIndependent(); |
| 7057 object_b.MarkIndependent(); | 7096 object_b.MarkIndependent(); |
| 7058 CHECK(object_b.IsIndependent()); | 7097 CHECK(object_b.IsIndependent()); |
| 7059 CcTest::heap()->PerformScavenge(); | 7098 CcTest::heap()->PerformScavenge(); |
| 7060 CHECK(object_a_disposed); | 7099 CHECK(object_a_pair.second); |
| 7061 CHECK(object_b_disposed); | 7100 CHECK(object_b_pair.second); |
| 7062 } | 7101 } |
| 7063 | 7102 |
| 7064 | 7103 |
| 7065 static void InvokeScavenge() { | 7104 static void InvokeScavenge() { |
| 7066 CcTest::heap()->PerformScavenge(); | 7105 CcTest::heap()->PerformScavenge(); |
| 7067 } | 7106 } |
| 7068 | 7107 |
| 7069 | 7108 |
| 7070 static void InvokeMarkSweep() { | 7109 static void InvokeMarkSweep() { |
| 7071 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 7110 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 7072 } | 7111 } |
| 7073 | 7112 |
| 7074 | 7113 |
| 7075 static void ForceScavenge(v8::Isolate* isolate, | 7114 static void ForceScavenge( |
| 7076 v8::Persistent<v8::Object>* obj, | 7115 const v8::WeakCallbackData<v8::Object, |
| 7077 bool* data) { | 7116 pair<v8::Persistent<v8::Object>*, |
| 7078 obj->Reset(); | 7117 bool> >& data) { |
| 7079 *(data) = true; | 7118 data.GetParameter()->first->Reset(); |
| 7119 data.GetParameter()->second = true; | |
| 7080 InvokeScavenge(); | 7120 InvokeScavenge(); |
| 7081 } | 7121 } |
| 7082 | 7122 |
| 7083 | 7123 |
| 7084 static void ForceMarkSweep(v8::Isolate* isolate, | 7124 static void ForceMarkSweep( |
| 7085 v8::Persistent<v8::Object>* obj, | 7125 const v8::WeakCallbackData<v8::Object, |
| 7086 bool* data) { | 7126 pair<v8::Persistent<v8::Object>*, |
| 7087 obj->Reset(); | 7127 bool> >& data) { |
| 7088 *(data) = true; | 7128 data.GetParameter()->first->Reset(); |
| 7129 data.GetParameter()->second = true; | |
| 7089 InvokeMarkSweep(); | 7130 InvokeMarkSweep(); |
| 7090 } | 7131 } |
| 7091 | 7132 |
| 7092 | 7133 |
| 7093 THREADED_TEST(GCFromWeakCallbacks) { | 7134 THREADED_TEST(GCFromWeakCallbacks) { |
| 7094 v8::Isolate* isolate = CcTest::isolate(); | 7135 v8::Isolate* isolate = CcTest::isolate(); |
| 7095 v8::HandleScope scope(isolate); | 7136 v8::HandleScope scope(isolate); |
| 7096 v8::Handle<Context> context = Context::New(isolate); | 7137 v8::Handle<Context> context = Context::New(isolate); |
| 7097 Context::Scope context_scope(context); | 7138 Context::Scope context_scope(context); |
| 7098 | 7139 |
| 7099 static const int kNumberOfGCTypes = 2; | 7140 static const int kNumberOfGCTypes = 2; |
| 7100 typedef v8::WeakReferenceCallbacks<v8::Object, bool>::Revivable Callback; | 7141 typedef v8::WeakCallbackData<v8::Object, |
| 7142 pair<v8::Persistent<v8::Object>*, | |
| 7143 bool> >::Callback Callback; | |
| 7101 Callback gc_forcing_callback[kNumberOfGCTypes] = | 7144 Callback gc_forcing_callback[kNumberOfGCTypes] = |
| 7102 {&ForceScavenge, &ForceMarkSweep}; | 7145 {&ForceScavenge, &ForceMarkSweep}; |
| 7103 | 7146 |
| 7104 typedef void (*GCInvoker)(); | 7147 typedef void (*GCInvoker)(); |
| 7105 GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep}; | 7148 GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep}; |
| 7106 | 7149 |
| 7107 for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) { | 7150 for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) { |
| 7108 for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) { | 7151 for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) { |
| 7109 v8::Persistent<v8::Object> object; | 7152 v8::Persistent<v8::Object> object; |
| 7110 { | 7153 { |
| 7111 v8::HandleScope handle_scope(isolate); | 7154 v8::HandleScope handle_scope(isolate); |
| 7112 object.Reset(isolate, v8::Object::New()); | 7155 object.Reset(isolate, v8::Object::New()); |
| 7113 } | 7156 } |
| 7114 bool disposed = false; | 7157 pair<v8::Persistent<v8::Object>*, bool> object_pair(&object, false); |
| 7115 object.MakeWeak(&disposed, gc_forcing_callback[inner_gc]); | 7158 object.SetWeak(&object_pair, gc_forcing_callback[inner_gc]); |
| 7116 object.MarkIndependent(); | 7159 object.MarkIndependent(); |
| 7117 invoke_gc[outer_gc](); | 7160 invoke_gc[outer_gc](); |
| 7118 CHECK(disposed); | 7161 CHECK(object_pair.second); |
| 7119 } | 7162 } |
| 7120 } | 7163 } |
| 7121 } | 7164 } |
| 7122 | 7165 |
| 7123 | 7166 |
| 7124 static void RevivingCallback(v8::Isolate* isolate, | 7167 static void RevivingCallback( |
| 7125 v8::Persistent<v8::Object>* obj, | 7168 const v8::WeakCallbackData<v8::Object, |
| 7126 bool* data) { | 7169 std::pair<v8::Persistent<Object>*, |
| 7127 obj->ClearWeak(); | 7170 bool> >& data) { |
| 7128 *(data) = true; | 7171 data.GetParameter()->first->ClearWeak(); |
| 7172 data.GetParameter()->second = true; | |
| 7129 } | 7173 } |
| 7130 | 7174 |
| 7131 | 7175 |
| 7132 THREADED_TEST(IndependentHandleRevival) { | 7176 THREADED_TEST(IndependentHandleRevival) { |
| 7133 v8::Isolate* isolate = CcTest::isolate(); | 7177 v8::Isolate* isolate = CcTest::isolate(); |
| 7134 v8::HandleScope scope(isolate); | 7178 v8::HandleScope scope(isolate); |
| 7135 v8::Handle<Context> context = Context::New(isolate); | 7179 v8::Handle<Context> context = Context::New(isolate); |
| 7136 Context::Scope context_scope(context); | 7180 Context::Scope context_scope(context); |
| 7137 | 7181 |
| 7138 v8::Persistent<v8::Object> object; | 7182 v8::Persistent<v8::Object> object; |
| 7139 { | 7183 { |
| 7140 v8::HandleScope handle_scope(isolate); | 7184 v8::HandleScope handle_scope(isolate); |
| 7141 v8::Local<v8::Object> o = v8::Object::New(); | 7185 v8::Local<v8::Object> o = v8::Object::New(); |
| 7142 object.Reset(isolate, o); | 7186 object.Reset(isolate, o); |
| 7143 o->Set(v8_str("x"), v8::Integer::New(1)); | 7187 o->Set(v8_str("x"), v8::Integer::New(1)); |
| 7144 v8::Local<String> y_str = v8_str("y"); | 7188 v8::Local<String> y_str = v8_str("y"); |
| 7145 o->Set(y_str, y_str); | 7189 o->Set(y_str, y_str); |
| 7146 } | 7190 } |
| 7147 bool revived = false; | 7191 pair<v8::Persistent<v8::Object>*, bool> revived(&object, false); |
| 7148 object.MakeWeak(&revived, &RevivingCallback); | 7192 object.SetWeak(&revived, &RevivingCallback); |
| 7149 object.MarkIndependent(); | 7193 object.MarkIndependent(); |
| 7150 CcTest::heap()->PerformScavenge(); | 7194 CcTest::heap()->PerformScavenge(); |
| 7151 CHECK(revived); | 7195 CHECK(revived.second); |
| 7152 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 7196 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
| 7153 { | 7197 { |
| 7154 v8::HandleScope handle_scope(isolate); | 7198 v8::HandleScope handle_scope(isolate); |
| 7155 v8::Local<v8::Object> o = v8::Local<v8::Object>::New(isolate, object); | 7199 v8::Local<v8::Object> o = v8::Local<v8::Object>::New(isolate, object); |
| 7156 v8::Local<String> y_str = v8_str("y"); | 7200 v8::Local<String> y_str = v8_str("y"); |
| 7157 CHECK_EQ(v8::Integer::New(1), o->Get(v8_str("x"))); | 7201 CHECK_EQ(v8::Integer::New(1), o->Get(v8_str("x"))); |
| 7158 CHECK(o->Get(y_str)->Equals(y_str)); | 7202 CHECK(o->Get(y_str)->Equals(y_str)); |
| 7159 } | 7203 } |
| 7160 } | 7204 } |
| 7161 | 7205 |
| (...skipping 5937 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 13099 reinterpret_cast<i::Isolate*>(isolate)->heap()-> | 13143 reinterpret_cast<i::Isolate*>(isolate)->heap()-> |
| 13100 CollectAllGarbage(i::Heap::kNoGCFlags); | 13144 CollectAllGarbage(i::Heap::kNoGCFlags); |
| 13101 // Verify disposed. | 13145 // Verify disposed. |
| 13102 CHECK_EQ(initial_handles, globals->global_handles_count()); | 13146 CHECK_EQ(initial_handles, globals->global_handles_count()); |
| 13103 } | 13147 } |
| 13104 | 13148 |
| 13105 | 13149 |
| 13106 v8::Persistent<v8::Object> some_object; | 13150 v8::Persistent<v8::Object> some_object; |
| 13107 v8::Persistent<v8::Object> bad_handle; | 13151 v8::Persistent<v8::Object> bad_handle; |
| 13108 | 13152 |
| 13109 void NewPersistentHandleCallback(v8::Isolate* isolate, | 13153 void NewPersistentHandleCallback( |
| 13110 v8::Persistent<v8::Value>* handle, | 13154 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) { |
| 13111 void*) { | 13155 v8::HandleScope scope(data.GetIsolate()); |
| 13112 v8::HandleScope scope(isolate); | 13156 bad_handle.Reset(data.GetIsolate(), some_object); |
| 13113 bad_handle.Reset(isolate, some_object); | 13157 data.GetParameter()->Reset(); |
| 13114 handle->Reset(); | |
| 13115 } | 13158 } |
| 13116 | 13159 |
| 13117 | 13160 |
| 13118 THREADED_TEST(NewPersistentHandleFromWeakCallback) { | 13161 THREADED_TEST(NewPersistentHandleFromWeakCallback) { |
| 13119 LocalContext context; | 13162 LocalContext context; |
| 13120 v8::Isolate* isolate = context->GetIsolate(); | 13163 v8::Isolate* isolate = context->GetIsolate(); |
| 13121 | 13164 |
| 13122 v8::Persistent<v8::Object> handle1, handle2; | 13165 v8::Persistent<v8::Object> handle1, handle2; |
| 13123 { | 13166 { |
| 13124 v8::HandleScope scope(isolate); | 13167 v8::HandleScope scope(isolate); |
| 13125 some_object.Reset(isolate, v8::Object::New()); | 13168 some_object.Reset(isolate, v8::Object::New()); |
| 13126 handle1.Reset(isolate, v8::Object::New()); | 13169 handle1.Reset(isolate, v8::Object::New()); |
| 13127 handle2.Reset(isolate, v8::Object::New()); | 13170 handle2.Reset(isolate, v8::Object::New()); |
| 13128 } | 13171 } |
| 13129 // Note: order is implementation dependent alas: currently | 13172 // Note: order is implementation dependent alas: currently |
| 13130 // global handle nodes are processed by PostGarbageCollectionProcessing | 13173 // global handle nodes are processed by PostGarbageCollectionProcessing |
| 13131 // in reverse allocation order, so if second allocated handle is deleted, | 13174 // in reverse allocation order, so if second allocated handle is deleted, |
| 13132 // weak callback of the first handle would be able to 'reallocate' it. | 13175 // weak callback of the first handle would be able to 'reallocate' it. |
| 13133 handle1.MakeWeak<v8::Value, void>(NULL, NewPersistentHandleCallback); | 13176 handle1.SetWeak(&handle1, NewPersistentHandleCallback); |
| 13134 handle2.Reset(); | 13177 handle2.Reset(); |
| 13135 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 13178 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 13136 } | 13179 } |
| 13137 | 13180 |
| 13138 | 13181 |
| 13139 v8::Persistent<v8::Object> to_be_disposed; | 13182 v8::Persistent<v8::Object> to_be_disposed; |
| 13140 | 13183 |
| 13141 void DisposeAndForceGcCallback(v8::Isolate* isolate, | 13184 void DisposeAndForceGcCallback( |
| 13142 v8::Persistent<v8::Value>* handle, | 13185 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) { |
| 13143 void*) { | |
| 13144 to_be_disposed.Reset(); | 13186 to_be_disposed.Reset(); |
| 13145 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 13187 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 13146 handle->Reset(); | 13188 data.GetParameter()->Reset(); |
| 13147 } | 13189 } |
| 13148 | 13190 |
| 13149 | 13191 |
| 13150 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) { | 13192 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) { |
| 13151 LocalContext context; | 13193 LocalContext context; |
| 13152 v8::Isolate* isolate = context->GetIsolate(); | 13194 v8::Isolate* isolate = context->GetIsolate(); |
| 13153 | 13195 |
| 13154 v8::Persistent<v8::Object> handle1, handle2; | 13196 v8::Persistent<v8::Object> handle1, handle2; |
| 13155 { | 13197 { |
| 13156 v8::HandleScope scope(isolate); | 13198 v8::HandleScope scope(isolate); |
| 13157 handle1.Reset(isolate, v8::Object::New()); | 13199 handle1.Reset(isolate, v8::Object::New()); |
| 13158 handle2.Reset(isolate, v8::Object::New()); | 13200 handle2.Reset(isolate, v8::Object::New()); |
| 13159 } | 13201 } |
| 13160 handle1.MakeWeak<v8::Value, void>(NULL, DisposeAndForceGcCallback); | 13202 handle1.SetWeak(&handle1, DisposeAndForceGcCallback); |
| 13161 to_be_disposed.Reset(isolate, handle2); | 13203 to_be_disposed.Reset(isolate, handle2); |
| 13162 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 13204 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 13163 } | 13205 } |
| 13164 | 13206 |
| 13165 void DisposingCallback(v8::Isolate* isolate, | 13207 void DisposingCallback( |
| 13166 v8::Persistent<v8::Value>* handle, | 13208 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) { |
| 13167 void*) { | 13209 data.GetParameter()->Reset(); |
| 13168 handle->Reset(); | |
| 13169 } | 13210 } |
| 13170 | 13211 |
| 13171 void HandleCreatingCallback(v8::Isolate* isolate, | 13212 void HandleCreatingCallback( |
| 13172 v8::Persistent<v8::Value>* handle, | 13213 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) { |
| 13173 void*) { | 13214 v8::HandleScope scope(data.GetIsolate()); |
| 13174 v8::HandleScope scope(isolate); | 13215 v8::Persistent<v8::Object>(data.GetIsolate(), v8::Object::New()); |
| 13175 v8::Persistent<v8::Object>(isolate, v8::Object::New()); | 13216 data.GetParameter()->Reset(); |
| 13176 handle->Reset(); | |
| 13177 } | 13217 } |
| 13178 | 13218 |
| 13179 | 13219 |
| 13180 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) { | 13220 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) { |
| 13181 LocalContext context; | 13221 LocalContext context; |
| 13182 v8::Isolate* isolate = context->GetIsolate(); | 13222 v8::Isolate* isolate = context->GetIsolate(); |
| 13183 | 13223 |
| 13184 v8::Persistent<v8::Object> handle1, handle2, handle3; | 13224 v8::Persistent<v8::Object> handle1, handle2, handle3; |
| 13185 { | 13225 { |
| 13186 v8::HandleScope scope(isolate); | 13226 v8::HandleScope scope(isolate); |
| 13187 handle3.Reset(isolate, v8::Object::New()); | 13227 handle3.Reset(isolate, v8::Object::New()); |
| 13188 handle2.Reset(isolate, v8::Object::New()); | 13228 handle2.Reset(isolate, v8::Object::New()); |
| 13189 handle1.Reset(isolate, v8::Object::New()); | 13229 handle1.Reset(isolate, v8::Object::New()); |
| 13190 } | 13230 } |
| 13191 handle2.MakeWeak<v8::Value, void>(NULL, DisposingCallback); | 13231 handle2.SetWeak(&handle2, DisposingCallback); |
| 13192 handle3.MakeWeak<v8::Value, void>(NULL, HandleCreatingCallback); | 13232 handle3.SetWeak(&handle3, HandleCreatingCallback); |
| 13193 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 13233 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 13194 } | 13234 } |
| 13195 | 13235 |
| 13196 | 13236 |
| 13197 THREADED_TEST(CheckForCrossContextObjectLiterals) { | 13237 THREADED_TEST(CheckForCrossContextObjectLiterals) { |
| 13198 v8::V8::Initialize(); | 13238 v8::V8::Initialize(); |
| 13199 | 13239 |
| 13200 const int nof = 2; | 13240 const int nof = 2; |
| 13201 const char* sources[nof] = { | 13241 const char* sources[nof] = { |
| 13202 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }", | 13242 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }", |
| (...skipping 7651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 20854 } | 20894 } |
| 20855 for (int i = 0; i < runs; i++) { | 20895 for (int i = 0; i < runs; i++) { |
| 20856 Local<String> expected; | 20896 Local<String> expected; |
| 20857 if (i != 0) { | 20897 if (i != 0) { |
| 20858 CHECK_EQ(v8_str("escape value"), values[i]); | 20898 CHECK_EQ(v8_str("escape value"), values[i]); |
| 20859 } else { | 20899 } else { |
| 20860 CHECK(values[i].IsEmpty()); | 20900 CHECK(values[i].IsEmpty()); |
| 20861 } | 20901 } |
| 20862 } | 20902 } |
| 20863 } | 20903 } |
| OLD | NEW |