| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #include "vm/handles.h" |
| #include "platform/assert.h" |
| #include "vm/dart_api_state.h" |
| #include "vm/flags.h" |
| #include "vm/heap/heap.h" |
| #include "vm/object.h" |
| #include "vm/unit_test.h" |
| #include "vm/zone.h" |
| |
| namespace dart { |
| |
| // Unit test for Zone handle allocation. |
| ISOLATE_UNIT_TEST_CASE(AllocateZoneHandle) { |
| #if defined(DEBUG) |
| FLAG_trace_handles = true; |
| #endif |
| // The previously run stub code generation may have created zone handles. |
| int initial_count = VMHandles::ZoneHandleCount(); |
| static const int kNumHandles = 65; |
| // Create some zone handles. |
| for (int i = 0; i < kNumHandles; i++) { |
| const Smi& handle = Smi::ZoneHandle(Smi::New(i)); |
| EXPECT(handle.IsSmi()); |
| EXPECT_EQ(i, handle.Value()); |
| } |
| EXPECT_EQ(kNumHandles + initial_count, VMHandles::ZoneHandleCount()); |
| // Create some more zone handles. |
| for (int i = kNumHandles; i < (2 * kNumHandles); i++) { |
| const Smi& handle = Smi::ZoneHandle(Smi::New(i)); |
| EXPECT(handle.IsSmi()); |
| EXPECT_EQ(i, handle.Value()); |
| } |
| EXPECT_EQ((2 * kNumHandles) + initial_count, VMHandles::ZoneHandleCount()); |
| } |
| |
| // Unit test for Scope handle allocation. |
| ISOLATE_UNIT_TEST_CASE(AllocateScopeHandle) { |
| #if defined(DEBUG) |
| FLAG_trace_handles = true; |
| #endif |
| int32_t handle_count = VMHandles::ScopedHandleCount(); |
| static const int kNumHandles = 65; |
| // Create some scoped handles. |
| { |
| Thread* thread = Thread::Current(); |
| HANDLESCOPE(thread); |
| for (int i = 0; i < kNumHandles; i++) { |
| const Smi& handle = Smi::Handle(Smi::New(i)); |
| EXPECT(handle.IsSmi()); |
| EXPECT_EQ(i, handle.Value()); |
| } |
| EXPECT_EQ((handle_count + kNumHandles), VMHandles::ScopedHandleCount()); |
| // Create lots of scoped handles in a loop with a nested scope. |
| for (int loop = 0; loop < 1000; loop++) { |
| HANDLESCOPE(thread); |
| for (int i = 0; i < 2; i++) { |
| const Smi& handle = Smi::Handle(Smi::New(i + loop)); |
| EXPECT(handle.IsSmi()); |
| EXPECT_EQ(i + loop, handle.Value()); |
| } |
| EXPECT_EQ((handle_count + kNumHandles + 2), |
| VMHandles::ScopedHandleCount()); |
| } |
| EXPECT_EQ((handle_count + kNumHandles), VMHandles::ScopedHandleCount()); |
| for (int i = 0; i < kNumHandles; i++) { |
| const Smi& handle = Smi::Handle(Smi::New(i)); |
| EXPECT(handle.IsSmi()); |
| EXPECT_EQ(i, handle.Value()); |
| } |
| EXPECT_EQ((handle_count + (2 * kNumHandles)), |
| VMHandles::ScopedHandleCount()); |
| } |
| EXPECT_EQ(handle_count, VMHandles::ScopedHandleCount()); |
| } |
| |
| static void NoopCallback(void* isolate_callback_data, |
| Dart_WeakPersistentHandle handle, |
| void* peer) {} |
| |
| // Unit test for handle validity checks. |
| TEST_CASE(CheckHandleValidity) { |
| #if defined(DEBUG) |
| FLAG_trace_handles = true; |
| #endif |
| Dart_Handle handle = NULL; |
| // Check validity using zone handles. |
| { |
| TransitionNativeToVM transition(thread); |
| StackZone sz(thread); |
| handle = reinterpret_cast<Dart_Handle>(&Smi::ZoneHandle(Smi::New(1))); |
| EXPECT_VALID(handle); |
| } |
| EXPECT(!Api::IsValid(handle)); |
| |
| // Check validity using scoped handles. |
| { |
| Dart_EnterScope(); |
| { |
| TransitionNativeToVM transition(thread); |
| HANDLESCOPE(thread); |
| handle = reinterpret_cast<Dart_Handle>(&Smi::Handle(Smi::New(1))); |
| EXPECT_VALID(handle); |
| } |
| Dart_ExitScope(); |
| } |
| EXPECT(!Api::IsValid(handle)); |
| |
| // Check validity using persistent handle. |
| Isolate* isolate = Isolate::Current(); |
| Dart_Handle scoped_handle; |
| { |
| TransitionNativeToVM transition(thread); |
| scoped_handle = Api::NewHandle(thread, Smi::New(1)); |
| } |
| Dart_PersistentHandle persistent_handle = |
| Dart_NewPersistentHandle(scoped_handle); |
| EXPECT_VALID(persistent_handle); |
| |
| Dart_DeletePersistentHandle(persistent_handle); |
| EXPECT(!Api::IsValid(persistent_handle)); |
| |
| // Check validity using weak persistent handle. |
| handle = reinterpret_cast<Dart_Handle>(Dart_NewWeakPersistentHandle( |
| Dart_NewStringFromCString("foo"), NULL, 0, NoopCallback)); |
| |
| EXPECT_NOTNULL(handle); |
| EXPECT_VALID(handle); |
| |
| Dart_DeleteWeakPersistentHandle( |
| reinterpret_cast<Dart_Isolate>(isolate), |
| reinterpret_cast<Dart_WeakPersistentHandle>(handle)); |
| EXPECT(!Api::IsValid(handle)); |
| } |
| |
| } // namespace dart |