| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef RUNTIME_VM_DART_API_STATE_H_ | 5 #ifndef RUNTIME_VM_DART_API_STATE_H_ |
| 6 #define RUNTIME_VM_DART_API_STATE_H_ | 6 #define RUNTIME_VM_DART_API_STATE_H_ |
| 7 | 7 |
| 8 #include "include/dart_api.h" | 8 #include "include/dart_api.h" |
| 9 | 9 |
| 10 #include "platform/utils.h" | 10 #include "platform/utils.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 | 25 |
| 26 namespace dart { | 26 namespace dart { |
| 27 | 27 |
| 28 class FinalizablePersistentHandle; | 28 class FinalizablePersistentHandle; |
| 29 typedef MallocGrowableArray<FinalizablePersistentHandle*> FinalizationQueue; | 29 typedef MallocGrowableArray<FinalizablePersistentHandle*> FinalizationQueue; |
| 30 | 30 |
| 31 | 31 |
| 32 class BackgroundFinalizer : public ThreadPool::Task { | 32 class BackgroundFinalizer : public ThreadPool::Task { |
| 33 public: | 33 public: |
| 34 BackgroundFinalizer(Isolate* isolate, FinalizationQueue* queue); | 34 BackgroundFinalizer(Isolate* isolate, FinalizationQueue* queue); |
| 35 virtual ~BackgroundFinalizer() { } | 35 virtual ~BackgroundFinalizer() {} |
| 36 | 36 |
| 37 void Run(); | 37 void Run(); |
| 38 | 38 |
| 39 private: | 39 private: |
| 40 Isolate* isolate_; | 40 Isolate* isolate_; |
| 41 FinalizationQueue* queue_; | 41 FinalizationQueue* queue_; |
| 42 | 42 |
| 43 DISALLOW_IMPLICIT_CONSTRUCTORS(BackgroundFinalizer); | 43 DISALLOW_IMPLICIT_CONSTRUCTORS(BackgroundFinalizer); |
| 44 }; | 44 }; |
| 45 | 45 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 OS::PrintErr("*** Deleting Api zone 0x%" Px "(0x%" Px ")\n", | 81 OS::PrintErr("*** Deleting Api zone 0x%" Px "(0x%" Px ")\n", |
| 82 reinterpret_cast<intptr_t>(this), | 82 reinterpret_cast<intptr_t>(this), |
| 83 reinterpret_cast<intptr_t>(&zone_)); | 83 reinterpret_cast<intptr_t>(&zone_)); |
| 84 } | 84 } |
| 85 } | 85 } |
| 86 | 86 |
| 87 // Allocates an array sized to hold 'len' elements of type | 87 // Allocates an array sized to hold 'len' elements of type |
| 88 // 'ElementType'. Checks for integer overflow when performing the | 88 // 'ElementType'. Checks for integer overflow when performing the |
| 89 // size computation. | 89 // size computation. |
| 90 template <class ElementType> | 90 template <class ElementType> |
| 91 ElementType* Alloc(intptr_t len) { return zone_.Alloc<ElementType>(len); } | 91 ElementType* Alloc(intptr_t len) { |
| 92 return zone_.Alloc<ElementType>(len); |
| 93 } |
| 92 | 94 |
| 93 // Allocates an array sized to hold 'len' elements of type | 95 // Allocates an array sized to hold 'len' elements of type |
| 94 // 'ElementType'. The new array is initialized from the memory of | 96 // 'ElementType'. The new array is initialized from the memory of |
| 95 // 'old_array' up to 'old_len'. | 97 // 'old_array' up to 'old_len'. |
| 96 template <class ElementType> | 98 template <class ElementType> |
| 97 ElementType* Realloc(ElementType* old_array, | 99 ElementType* Realloc(ElementType* old_array, |
| 98 intptr_t old_len, | 100 intptr_t old_len, |
| 99 intptr_t new_len) { | 101 intptr_t new_len) { |
| 100 return zone_.Realloc<ElementType>(old_array, old_len, new_len); | 102 return zone_.Realloc<ElementType>(old_array, old_len, new_len); |
| 101 } | 103 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 126 void Reset(Thread* thread) { | 128 void Reset(Thread* thread) { |
| 127 if ((thread != NULL) && (thread->zone() == &zone_)) { | 129 if ((thread != NULL) && (thread->zone() == &zone_)) { |
| 128 thread->set_zone(zone_.previous_); | 130 thread->set_zone(zone_.previous_); |
| 129 } | 131 } |
| 130 zone_.DeleteAll(); | 132 zone_.DeleteAll(); |
| 131 } | 133 } |
| 132 | 134 |
| 133 private: | 135 private: |
| 134 Zone zone_; | 136 Zone zone_; |
| 135 | 137 |
| 136 template<typename T> friend class ApiGrowableArray; | 138 template <typename T> |
| 139 friend class ApiGrowableArray; |
| 137 DISALLOW_COPY_AND_ASSIGN(ApiZone); | 140 DISALLOW_COPY_AND_ASSIGN(ApiZone); |
| 138 }; | 141 }; |
| 139 | 142 |
| 140 | 143 |
| 141 // Implementation of local handles which are handed out from every | 144 // Implementation of local handles which are handed out from every |
| 142 // dart API call, these handles are valid only in the present scope | 145 // dart API call, these handles are valid only in the present scope |
| 143 // and are destroyed when a Dart_ExitScope() is called. | 146 // and are destroyed when a Dart_ExitScope() is called. |
| 144 class LocalHandle { | 147 class LocalHandle { |
| 145 public: | 148 public: |
| 146 // Accessors. | 149 // Accessors. |
| 147 RawObject* raw() const { return raw_; } | 150 RawObject* raw() const { return raw_; } |
| 148 void set_raw(RawObject* raw) { raw_ = raw; } | 151 void set_raw(RawObject* raw) { raw_ = raw; } |
| 149 static intptr_t raw_offset() { return OFFSET_OF(LocalHandle, raw_); } | 152 static intptr_t raw_offset() { return OFFSET_OF(LocalHandle, raw_); } |
| 150 | 153 |
| 151 Dart_Handle apiHandle() { | 154 Dart_Handle apiHandle() { return reinterpret_cast<Dart_Handle>(this); } |
| 152 return reinterpret_cast<Dart_Handle>(this); | |
| 153 } | |
| 154 | 155 |
| 155 private: | 156 private: |
| 156 LocalHandle() { } | 157 LocalHandle() {} |
| 157 ~LocalHandle() { } | 158 ~LocalHandle() {} |
| 158 | 159 |
| 159 RawObject* raw_; | 160 RawObject* raw_; |
| 160 DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods. | 161 DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods. |
| 161 DISALLOW_COPY_AND_ASSIGN(LocalHandle); | 162 DISALLOW_COPY_AND_ASSIGN(LocalHandle); |
| 162 }; | 163 }; |
| 163 | 164 |
| 164 | 165 |
| 165 // A distinguished callback which indicates that a persistent handle | 166 // A distinguished callback which indicates that a persistent handle |
| 166 // should not be deleted from the dart api. | 167 // should not be deleted from the dart api. |
| 167 void ProtectedHandleCallback(void* peer); | 168 void ProtectedHandleCallback(void* peer); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 181 return reinterpret_cast<Dart_PersistentHandle>(this); | 182 return reinterpret_cast<Dart_PersistentHandle>(this); |
| 182 } | 183 } |
| 183 | 184 |
| 184 static intptr_t raw_offset() { return OFFSET_OF(PersistentHandle, raw_); } | 185 static intptr_t raw_offset() { return OFFSET_OF(PersistentHandle, raw_); } |
| 185 | 186 |
| 186 static PersistentHandle* Cast(Dart_PersistentHandle handle); | 187 static PersistentHandle* Cast(Dart_PersistentHandle handle); |
| 187 | 188 |
| 188 private: | 189 private: |
| 189 friend class PersistentHandles; | 190 friend class PersistentHandles; |
| 190 | 191 |
| 191 PersistentHandle() { } | 192 PersistentHandle() {} |
| 192 ~PersistentHandle() { } | 193 ~PersistentHandle() {} |
| 193 | 194 |
| 194 // Overload the raw_ field as a next pointer when adding freed | 195 // Overload the raw_ field as a next pointer when adding freed |
| 195 // handles to the free list. | 196 // handles to the free list. |
| 196 PersistentHandle* Next() { | 197 PersistentHandle* Next() { return reinterpret_cast<PersistentHandle*>(raw_); } |
| 197 return reinterpret_cast<PersistentHandle*>(raw_); | |
| 198 } | |
| 199 void SetNext(PersistentHandle* free_list) { | 198 void SetNext(PersistentHandle* free_list) { |
| 200 raw_ = reinterpret_cast<RawObject*>(free_list); | 199 raw_ = reinterpret_cast<RawObject*>(free_list); |
| 201 ASSERT(!raw_->IsHeapObject()); | 200 ASSERT(!raw_->IsHeapObject()); |
| 202 } | 201 } |
| 203 void FreeHandle(PersistentHandle* free_list) { | 202 void FreeHandle(PersistentHandle* free_list) { SetNext(free_list); } |
| 204 SetNext(free_list); | |
| 205 } | |
| 206 | 203 |
| 207 RawObject* raw_; | 204 RawObject* raw_; |
| 208 DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods. | 205 DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods. |
| 209 DISALLOW_COPY_AND_ASSIGN(PersistentHandle); | 206 DISALLOW_COPY_AND_ASSIGN(PersistentHandle); |
| 210 }; | 207 }; |
| 211 | 208 |
| 212 | 209 |
| 213 // Implementation of persistent handles which are handed out through the | 210 // Implementation of persistent handles which are handed out through the |
| 214 // dart API. | 211 // dart API. |
| 215 class FinalizablePersistentHandle { | 212 class FinalizablePersistentHandle { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 kExternalSizeBitsSize = (kBitsPerWord - 2), | 283 kExternalSizeBitsSize = (kBitsPerWord - 2), |
| 287 }; | 284 }; |
| 288 | 285 |
| 289 // This part of external_data_ is the number of externally allocated bytes. | 286 // This part of external_data_ is the number of externally allocated bytes. |
| 290 class ExternalSizeInWordsBits : public BitField<uword, | 287 class ExternalSizeInWordsBits : public BitField<uword, |
| 291 intptr_t, | 288 intptr_t, |
| 292 kExternalSizeBits, | 289 kExternalSizeBits, |
| 293 kExternalSizeBitsSize> {}; | 290 kExternalSizeBitsSize> {}; |
| 294 // This bit of external_data_ is true if the referent was created in new | 291 // This bit of external_data_ is true if the referent was created in new |
| 295 // space and UpdateRelocated has not yet detected any promotion. | 292 // space and UpdateRelocated has not yet detected any promotion. |
| 296 class ExternalNewSpaceBit : | 293 class ExternalNewSpaceBit |
| 297 public BitField<uword, bool, kExternalNewSpaceBit, 1> {}; | 294 : public BitField<uword, bool, kExternalNewSpaceBit, 1> {}; |
| 298 class QueuedForFinalizationBit : | 295 class QueuedForFinalizationBit |
| 299 public BitField<uword, bool, kQueuedForFinalizationBit, 1> {}; | 296 : public BitField<uword, bool, kQueuedForFinalizationBit, 1> {}; |
| 300 | 297 |
| 301 friend class FinalizablePersistentHandles; | 298 friend class FinalizablePersistentHandles; |
| 302 | 299 |
| 303 FinalizablePersistentHandle() | 300 FinalizablePersistentHandle() |
| 304 : raw_(NULL), | 301 : raw_(NULL), peer_(NULL), external_data_(0), callback_(NULL) {} |
| 305 peer_(NULL), | 302 ~FinalizablePersistentHandle() {} |
| 306 external_data_(0), | |
| 307 callback_(NULL) { } | |
| 308 ~FinalizablePersistentHandle() { } | |
| 309 | 303 |
| 310 static void Finalize(Isolate* isolate, FinalizablePersistentHandle* handle); | 304 static void Finalize(Isolate* isolate, FinalizablePersistentHandle* handle); |
| 311 | 305 |
| 312 // Overload the raw_ field as a next pointer when adding freed | 306 // Overload the raw_ field as a next pointer when adding freed |
| 313 // handles to the free list. | 307 // handles to the free list. |
| 314 FinalizablePersistentHandle* Next() { | 308 FinalizablePersistentHandle* Next() { |
| 315 return reinterpret_cast<FinalizablePersistentHandle*>(raw_); | 309 return reinterpret_cast<FinalizablePersistentHandle*>(raw_); |
| 316 } | 310 } |
| 317 void SetNext(FinalizablePersistentHandle* free_list) { | 311 void SetNext(FinalizablePersistentHandle* free_list) { |
| 318 raw_ = reinterpret_cast<RawObject*>(free_list); | 312 raw_ = reinterpret_cast<RawObject*>(free_list); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 341 | 335 |
| 342 void set_peer(void* peer) { peer_ = peer; } | 336 void set_peer(void* peer) { peer_ = peer; } |
| 343 | 337 |
| 344 void set_callback(Dart_WeakPersistentHandleFinalizer callback) { | 338 void set_callback(Dart_WeakPersistentHandleFinalizer callback) { |
| 345 callback_ = callback; | 339 callback_ = callback; |
| 346 } | 340 } |
| 347 | 341 |
| 348 void set_external_size(intptr_t size) { | 342 void set_external_size(intptr_t size) { |
| 349 intptr_t size_in_words = Utils::RoundUp(size, kObjectAlignment) / kWordSize; | 343 intptr_t size_in_words = Utils::RoundUp(size, kObjectAlignment) / kWordSize; |
| 350 ASSERT(ExternalSizeInWordsBits::is_valid(size_in_words)); | 344 ASSERT(ExternalSizeInWordsBits::is_valid(size_in_words)); |
| 351 external_data_ = ExternalSizeInWordsBits::update(size_in_words, | 345 external_data_ = |
| 352 external_data_); | 346 ExternalSizeInWordsBits::update(size_in_words, external_data_); |
| 353 } | 347 } |
| 354 | 348 |
| 355 bool is_queued_for_finalization() const { | 349 bool is_queued_for_finalization() const { |
| 356 return QueuedForFinalizationBit::decode(external_data_); | 350 return QueuedForFinalizationBit::decode(external_data_); |
| 357 } | 351 } |
| 358 void set_is_queued_for_finalization(bool value) { | 352 void set_is_queued_for_finalization(bool value) { |
| 359 external_data_ = QueuedForFinalizationBit::update(value, external_data_); | 353 external_data_ = QueuedForFinalizationBit::update(value, external_data_); |
| 360 } | 354 } |
| 361 | 355 |
| 362 bool IsSetNewSpaceBit() const { | 356 bool IsSetNewSpaceBit() const { |
| 363 return ExternalNewSpaceBit::decode(external_data_); | 357 return ExternalNewSpaceBit::decode(external_data_); |
| 364 } | 358 } |
| 365 | 359 |
| 366 void SetExternalNewSpaceBit() { | 360 void SetExternalNewSpaceBit() { |
| 367 external_data_ = ExternalNewSpaceBit::update(true, external_data_); | 361 external_data_ = ExternalNewSpaceBit::update(true, external_data_); |
| 368 } | 362 } |
| 369 | 363 |
| 370 void ClearExternalNewSpaceBit() { | 364 void ClearExternalNewSpaceBit() { |
| 371 external_data_ = ExternalNewSpaceBit::update(false, external_data_); | 365 external_data_ = ExternalNewSpaceBit::update(false, external_data_); |
| 372 } | 366 } |
| 373 | 367 |
| 374 // Returns the space to charge for the external size. | 368 // Returns the space to charge for the external size. |
| 375 Heap::Space SpaceForExternal() const { | 369 Heap::Space SpaceForExternal() const { |
| 376 // Non-heap and VM-heap objects count as old space here. | 370 // Non-heap and VM-heap objects count as old space here. |
| 377 return (raw_->IsHeapObject() && raw_->IsNewObject()) ? | 371 return (raw_->IsHeapObject() && raw_->IsNewObject()) ? Heap::kNew |
| 378 Heap::kNew : Heap::kOld; | 372 : Heap::kOld; |
| 379 } | 373 } |
| 380 | 374 |
| 381 friend class BackgroundFinalizer; | 375 friend class BackgroundFinalizer; |
| 382 | 376 |
| 383 RawObject* raw_; | 377 RawObject* raw_; |
| 384 void* peer_; | 378 void* peer_; |
| 385 uword external_data_; | 379 uword external_data_; |
| 386 Dart_WeakPersistentHandleFinalizer callback_; | 380 Dart_WeakPersistentHandleFinalizer callback_; |
| 387 | 381 |
| 388 DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods. | 382 DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods. |
| 389 DISALLOW_COPY_AND_ASSIGN(FinalizablePersistentHandle); | 383 DISALLOW_COPY_AND_ASSIGN(FinalizablePersistentHandle); |
| 390 }; | 384 }; |
| 391 | 385 |
| 392 | 386 |
| 393 // Local handles repository structure. | 387 // Local handles repository structure. |
| 394 static const int kLocalHandleSizeInWords = sizeof(LocalHandle) / kWordSize; | 388 static const int kLocalHandleSizeInWords = sizeof(LocalHandle) / kWordSize; |
| 395 static const int kLocalHandlesPerChunk = 64; | 389 static const int kLocalHandlesPerChunk = 64; |
| 396 static const int kOffsetOfRawPtrInLocalHandle = 0; | 390 static const int kOffsetOfRawPtrInLocalHandle = 0; |
| 397 class LocalHandles : Handles<kLocalHandleSizeInWords, | 391 class LocalHandles : Handles<kLocalHandleSizeInWords, |
| 398 kLocalHandlesPerChunk, | 392 kLocalHandlesPerChunk, |
| 399 kOffsetOfRawPtrInLocalHandle> { | 393 kOffsetOfRawPtrInLocalHandle> { |
| 400 public: | 394 public: |
| 401 LocalHandles() : Handles<kLocalHandleSizeInWords, | 395 LocalHandles() |
| 402 kLocalHandlesPerChunk, | 396 : Handles<kLocalHandleSizeInWords, |
| 403 kOffsetOfRawPtrInLocalHandle>() { | 397 kLocalHandlesPerChunk, |
| 398 kOffsetOfRawPtrInLocalHandle>() { |
| 404 if (FLAG_trace_handles) { | 399 if (FLAG_trace_handles) { |
| 405 OS::PrintErr("*** Starting a new Local handle block 0x%" Px "\n", | 400 OS::PrintErr("*** Starting a new Local handle block 0x%" Px "\n", |
| 406 reinterpret_cast<intptr_t>(this)); | 401 reinterpret_cast<intptr_t>(this)); |
| 407 } | 402 } |
| 408 } | 403 } |
| 409 ~LocalHandles() { | 404 ~LocalHandles() { |
| 410 if (FLAG_trace_handles) { | 405 if (FLAG_trace_handles) { |
| 411 OS::PrintErr("*** Handle Counts for 0x(%" Px "):Scoped = %d\n", | 406 OS::PrintErr("*** Handle Counts for 0x(%" Px "):Scoped = %d\n", |
| 412 reinterpret_cast<intptr_t>(this), | 407 reinterpret_cast<intptr_t>(this), CountHandles()); |
| 413 CountHandles()); | |
| 414 OS::PrintErr("*** Deleting Local handle block 0x%" Px "\n", | 408 OS::PrintErr("*** Deleting Local handle block 0x%" Px "\n", |
| 415 reinterpret_cast<intptr_t>(this)); | 409 reinterpret_cast<intptr_t>(this)); |
| 416 } | 410 } |
| 417 } | 411 } |
| 418 | 412 |
| 419 | 413 |
| 420 // Visit all object pointers stored in the various handles. | 414 // Visit all object pointers stored in the various handles. |
| 421 void VisitObjectPointers(ObjectPointerVisitor* visitor) { | 415 void VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 422 Handles<kLocalHandleSizeInWords, | 416 Handles<kLocalHandleSizeInWords, kLocalHandlesPerChunk, |
| 423 kLocalHandlesPerChunk, | |
| 424 kOffsetOfRawPtrInLocalHandle>::VisitObjectPointers(visitor); | 417 kOffsetOfRawPtrInLocalHandle>::VisitObjectPointers(visitor); |
| 425 } | 418 } |
| 426 | 419 |
| 427 // Reset the local handles block for reuse. | 420 // Reset the local handles block for reuse. |
| 428 void Reset() { | 421 void Reset() { |
| 429 Handles<kLocalHandleSizeInWords, | 422 Handles<kLocalHandleSizeInWords, kLocalHandlesPerChunk, |
| 430 kLocalHandlesPerChunk, | |
| 431 kOffsetOfRawPtrInLocalHandle>::Reset(); | 423 kOffsetOfRawPtrInLocalHandle>::Reset(); |
| 432 } | 424 } |
| 433 | 425 |
| 434 // Allocates a handle in the current handle scope. This handle is valid only | 426 // Allocates a handle in the current handle scope. This handle is valid only |
| 435 // in the current handle scope and is destroyed when the current handle | 427 // in the current handle scope and is destroyed when the current handle |
| 436 // scope ends. | 428 // scope ends. |
| 437 LocalHandle* AllocateHandle() { | 429 LocalHandle* AllocateHandle() { |
| 438 return reinterpret_cast<LocalHandle*>(AllocateScopedHandle()); | 430 return reinterpret_cast<LocalHandle*>(AllocateScopedHandle()); |
| 439 } | 431 } |
| 440 | 432 |
| 441 // Validate if passed in handle is a Local Handle. | 433 // Validate if passed in handle is a Local Handle. |
| 442 bool IsValidHandle(Dart_Handle object) const { | 434 bool IsValidHandle(Dart_Handle object) const { |
| 443 return IsValidScopedHandle(reinterpret_cast<uword>(object)); | 435 return IsValidScopedHandle(reinterpret_cast<uword>(object)); |
| 444 } | 436 } |
| 445 | 437 |
| 446 // Returns a count of active handles (used for testing purposes). | 438 // Returns a count of active handles (used for testing purposes). |
| 447 int CountHandles() const { | 439 int CountHandles() const { return CountScopedHandles(); } |
| 448 return CountScopedHandles(); | |
| 449 } | |
| 450 | 440 |
| 451 private: | 441 private: |
| 452 DISALLOW_COPY_AND_ASSIGN(LocalHandles); | 442 DISALLOW_COPY_AND_ASSIGN(LocalHandles); |
| 453 }; | 443 }; |
| 454 | 444 |
| 455 | 445 |
| 456 // Persistent handles repository structure. | 446 // Persistent handles repository structure. |
| 457 static const int kPersistentHandleSizeInWords = | 447 static const int kPersistentHandleSizeInWords = |
| 458 sizeof(PersistentHandle) / kWordSize; | 448 sizeof(PersistentHandle) / kWordSize; |
| 459 static const int kPersistentHandlesPerChunk = 64; | 449 static const int kPersistentHandlesPerChunk = 64; |
| 460 static const int kOffsetOfRawPtrInPersistentHandle = 0; | 450 static const int kOffsetOfRawPtrInPersistentHandle = 0; |
| 461 class PersistentHandles : Handles<kPersistentHandleSizeInWords, | 451 class PersistentHandles : Handles<kPersistentHandleSizeInWords, |
| 462 kPersistentHandlesPerChunk, | 452 kPersistentHandlesPerChunk, |
| 463 kOffsetOfRawPtrInPersistentHandle> { | 453 kOffsetOfRawPtrInPersistentHandle> { |
| 464 public: | 454 public: |
| 465 PersistentHandles() : Handles<kPersistentHandleSizeInWords, | 455 PersistentHandles() |
| 466 kPersistentHandlesPerChunk, | 456 : Handles<kPersistentHandleSizeInWords, |
| 467 kOffsetOfRawPtrInPersistentHandle>(), | 457 kPersistentHandlesPerChunk, |
| 458 kOffsetOfRawPtrInPersistentHandle>(), |
| 468 free_list_(NULL) { | 459 free_list_(NULL) { |
| 469 if (FLAG_trace_handles) { | 460 if (FLAG_trace_handles) { |
| 470 OS::PrintErr("*** Starting a new Persistent handle block 0x%" Px "\n", | 461 OS::PrintErr("*** Starting a new Persistent handle block 0x%" Px "\n", |
| 471 reinterpret_cast<intptr_t>(this)); | 462 reinterpret_cast<intptr_t>(this)); |
| 472 } | 463 } |
| 473 } | 464 } |
| 474 ~PersistentHandles() { | 465 ~PersistentHandles() { |
| 475 free_list_ = NULL; | 466 free_list_ = NULL; |
| 476 if (FLAG_trace_handles) { | 467 if (FLAG_trace_handles) { |
| 477 OS::PrintErr("*** Handle Counts for 0x(%" Px "):Scoped = %d\n", | 468 OS::PrintErr("*** Handle Counts for 0x(%" Px "):Scoped = %d\n", |
| 478 reinterpret_cast<intptr_t>(this), | 469 reinterpret_cast<intptr_t>(this), CountHandles()); |
| 479 CountHandles()); | |
| 480 OS::PrintErr("*** Deleting Persistent handle block 0x%" Px "\n", | 470 OS::PrintErr("*** Deleting Persistent handle block 0x%" Px "\n", |
| 481 reinterpret_cast<intptr_t>(this)); | 471 reinterpret_cast<intptr_t>(this)); |
| 482 } | 472 } |
| 483 } | 473 } |
| 484 | 474 |
| 485 // Accessors. | 475 // Accessors. |
| 486 PersistentHandle* free_list() const { return free_list_; } | 476 PersistentHandle* free_list() const { return free_list_; } |
| 487 void set_free_list(PersistentHandle* value) { free_list_ = value; } | 477 void set_free_list(PersistentHandle* value) { free_list_ = value; } |
| 488 | 478 |
| 489 // Visit all object pointers stored in the various handles. | 479 // Visit all object pointers stored in the various handles. |
| 490 void VisitObjectPointers(ObjectPointerVisitor* visitor) { | 480 void VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 491 Handles<kPersistentHandleSizeInWords, | 481 Handles<kPersistentHandleSizeInWords, kPersistentHandlesPerChunk, |
| 492 kPersistentHandlesPerChunk, | |
| 493 kOffsetOfRawPtrInPersistentHandle>::VisitObjectPointers(visitor); | 482 kOffsetOfRawPtrInPersistentHandle>::VisitObjectPointers(visitor); |
| 494 } | 483 } |
| 495 | 484 |
| 496 // Visit all the handles. | 485 // Visit all the handles. |
| 497 void Visit(HandleVisitor* visitor) { | 486 void Visit(HandleVisitor* visitor) { |
| 498 Handles<kPersistentHandleSizeInWords, | 487 Handles<kPersistentHandleSizeInWords, kPersistentHandlesPerChunk, |
| 499 kPersistentHandlesPerChunk, | |
| 500 kOffsetOfRawPtrInPersistentHandle>::Visit(visitor); | 488 kOffsetOfRawPtrInPersistentHandle>::Visit(visitor); |
| 501 } | 489 } |
| 502 | 490 |
| 503 // Allocates a persistent handle, these have to be destroyed explicitly | 491 // Allocates a persistent handle, these have to be destroyed explicitly |
| 504 // by calling FreeHandle. | 492 // by calling FreeHandle. |
| 505 PersistentHandle* AllocateHandle() { | 493 PersistentHandle* AllocateHandle() { |
| 506 PersistentHandle* handle; | 494 PersistentHandle* handle; |
| 507 if (free_list_ != NULL) { | 495 if (free_list_ != NULL) { |
| 508 handle = free_list_; | 496 handle = free_list_; |
| 509 free_list_ = handle->Next(); | 497 free_list_ = handle->Next(); |
| 510 } else { | 498 } else { |
| 511 handle = reinterpret_cast<PersistentHandle*>(AllocateScopedHandle()); | 499 handle = reinterpret_cast<PersistentHandle*>(AllocateScopedHandle()); |
| 512 } | 500 } |
| 513 handle->set_raw(Object::null()); | 501 handle->set_raw(Object::null()); |
| 514 return handle; | 502 return handle; |
| 515 } | 503 } |
| 516 | 504 |
| 517 void FreeHandle(PersistentHandle* handle) { | 505 void FreeHandle(PersistentHandle* handle) { |
| 518 handle->FreeHandle(free_list()); | 506 handle->FreeHandle(free_list()); |
| 519 set_free_list(handle); | 507 set_free_list(handle); |
| 520 } | 508 } |
| 521 | 509 |
| 522 // Validate if passed in handle is a Persistent Handle. | 510 // Validate if passed in handle is a Persistent Handle. |
| 523 bool IsValidHandle(Dart_PersistentHandle object) const { | 511 bool IsValidHandle(Dart_PersistentHandle object) const { |
| 524 return IsValidScopedHandle(reinterpret_cast<uword>(object)); | 512 return IsValidScopedHandle(reinterpret_cast<uword>(object)); |
| 525 } | 513 } |
| 526 | 514 |
| 527 // Returns a count of active handles (used for testing purposes). | 515 // Returns a count of active handles (used for testing purposes). |
| 528 int CountHandles() const { | 516 int CountHandles() const { return CountScopedHandles(); } |
| 529 return CountScopedHandles(); | |
| 530 } | |
| 531 | 517 |
| 532 private: | 518 private: |
| 533 PersistentHandle* free_list_; | 519 PersistentHandle* free_list_; |
| 534 DISALLOW_COPY_AND_ASSIGN(PersistentHandles); | 520 DISALLOW_COPY_AND_ASSIGN(PersistentHandles); |
| 535 }; | 521 }; |
| 536 | 522 |
| 537 | 523 |
| 538 // Finalizable persistent handles repository structure. | 524 // Finalizable persistent handles repository structure. |
| 539 static const int kFinalizablePersistentHandleSizeInWords = | 525 static const int kFinalizablePersistentHandleSizeInWords = |
| 540 sizeof(FinalizablePersistentHandle) / kWordSize; | 526 sizeof(FinalizablePersistentHandle) / kWordSize; |
| 541 static const int kFinalizablePersistentHandlesPerChunk = 64; | 527 static const int kFinalizablePersistentHandlesPerChunk = 64; |
| 542 static const int kOffsetOfRawPtrInFinalizablePersistentHandle = 0; | 528 static const int kOffsetOfRawPtrInFinalizablePersistentHandle = 0; |
| 543 class FinalizablePersistentHandles | 529 class FinalizablePersistentHandles |
| 544 : Handles<kFinalizablePersistentHandleSizeInWords, | 530 : Handles<kFinalizablePersistentHandleSizeInWords, |
| 545 kFinalizablePersistentHandlesPerChunk, | 531 kFinalizablePersistentHandlesPerChunk, |
| 546 kOffsetOfRawPtrInFinalizablePersistentHandle> { | 532 kOffsetOfRawPtrInFinalizablePersistentHandle> { |
| 547 public: | 533 public: |
| 548 FinalizablePersistentHandles() | 534 FinalizablePersistentHandles() |
| 549 : Handles<kFinalizablePersistentHandleSizeInWords, | 535 : Handles<kFinalizablePersistentHandleSizeInWords, |
| 550 kFinalizablePersistentHandlesPerChunk, | 536 kFinalizablePersistentHandlesPerChunk, |
| 551 kOffsetOfRawPtrInFinalizablePersistentHandle>(), | 537 kOffsetOfRawPtrInFinalizablePersistentHandle>(), |
| 552 free_list_(NULL), mutex_(new Mutex()) { } | 538 free_list_(NULL), |
| 539 mutex_(new Mutex()) {} |
| 553 ~FinalizablePersistentHandles() { | 540 ~FinalizablePersistentHandles() { |
| 554 free_list_ = NULL; | 541 free_list_ = NULL; |
| 555 delete mutex_; | 542 delete mutex_; |
| 556 mutex_ = NULL; | 543 mutex_ = NULL; |
| 557 } | 544 } |
| 558 | 545 |
| 559 // Accessors. | 546 // Accessors. |
| 560 FinalizablePersistentHandle* free_list() const { return free_list_; } | 547 FinalizablePersistentHandle* free_list() const { return free_list_; } |
| 561 void set_free_list(FinalizablePersistentHandle* value) { free_list_ = value; } | 548 void set_free_list(FinalizablePersistentHandle* value) { free_list_ = value; } |
| 562 | 549 |
| 563 // Visit all handles stored in the various handle blocks. | 550 // Visit all handles stored in the various handle blocks. |
| 564 void VisitHandles(HandleVisitor* visitor) { | 551 void VisitHandles(HandleVisitor* visitor) { |
| 565 Handles<kFinalizablePersistentHandleSizeInWords, | 552 Handles<kFinalizablePersistentHandleSizeInWords, |
| 566 kFinalizablePersistentHandlesPerChunk, | 553 kFinalizablePersistentHandlesPerChunk, |
| 567 kOffsetOfRawPtrInFinalizablePersistentHandle>::Visit( | 554 kOffsetOfRawPtrInFinalizablePersistentHandle>::Visit(visitor); |
| 568 visitor); | |
| 569 } | 555 } |
| 570 | 556 |
| 571 // Visit all object pointers stored in the various handles. | 557 // Visit all object pointers stored in the various handles. |
| 572 void VisitObjectPointers(ObjectPointerVisitor* visitor) { | 558 void VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 573 Handles<kFinalizablePersistentHandleSizeInWords, | 559 Handles<kFinalizablePersistentHandleSizeInWords, |
| 574 kFinalizablePersistentHandlesPerChunk, | 560 kFinalizablePersistentHandlesPerChunk, |
| 575 kOffsetOfRawPtrInFinalizablePersistentHandle>::VisitObjectPointers( | 561 kOffsetOfRawPtrInFinalizablePersistentHandle>:: |
| 576 visitor); | 562 VisitObjectPointers(visitor); |
| 577 } | 563 } |
| 578 | 564 |
| 579 // Allocates a persistent handle, these have to be destroyed explicitly | 565 // Allocates a persistent handle, these have to be destroyed explicitly |
| 580 // by calling FreeHandle. | 566 // by calling FreeHandle. |
| 581 FinalizablePersistentHandle* AllocateHandle() { | 567 FinalizablePersistentHandle* AllocateHandle() { |
| 582 FinalizablePersistentHandle* handle; | 568 FinalizablePersistentHandle* handle; |
| 583 { | 569 { |
| 584 MutexLocker ml(mutex_); | 570 MutexLocker ml(mutex_); |
| 585 if (free_list_ != NULL) { | 571 if (free_list_ != NULL) { |
| 586 handle = free_list_; | 572 handle = free_list_; |
| 587 free_list_ = handle->Next(); | 573 free_list_ = handle->Next(); |
| 588 handle->set_raw(Object::null()); | 574 handle->set_raw(Object::null()); |
| 589 return handle; | 575 return handle; |
| 590 } | 576 } |
| 591 } | 577 } |
| 592 | 578 |
| 593 handle = reinterpret_cast<FinalizablePersistentHandle*>( | 579 handle = |
| 594 AllocateScopedHandle()); | 580 reinterpret_cast<FinalizablePersistentHandle*>(AllocateScopedHandle()); |
| 595 handle->Clear(); | 581 handle->Clear(); |
| 596 return handle; | 582 return handle; |
| 597 } | 583 } |
| 598 | 584 |
| 599 void FreeHandle(FinalizablePersistentHandle* handle) { | 585 void FreeHandle(FinalizablePersistentHandle* handle) { |
| 600 MutexLocker ml(mutex_); | 586 MutexLocker ml(mutex_); |
| 601 handle->FreeHandle(free_list()); | 587 handle->FreeHandle(free_list()); |
| 602 set_free_list(handle); | 588 set_free_list(handle); |
| 603 } | 589 } |
| 604 | 590 |
| 605 // Validate if passed in handle is a Persistent Handle. | 591 // Validate if passed in handle is a Persistent Handle. |
| 606 bool IsValidHandle(Dart_WeakPersistentHandle object) const { | 592 bool IsValidHandle(Dart_WeakPersistentHandle object) const { |
| 607 MutexLocker ml(mutex_); | 593 MutexLocker ml(mutex_); |
| 608 return IsValidScopedHandle(reinterpret_cast<uword>(object)); | 594 return IsValidScopedHandle(reinterpret_cast<uword>(object)); |
| 609 } | 595 } |
| 610 | 596 |
| 611 // Returns a count of active handles (used for testing purposes). | 597 // Returns a count of active handles (used for testing purposes). |
| 612 int CountHandles() const { | 598 int CountHandles() const { return CountScopedHandles(); } |
| 613 return CountScopedHandles(); | |
| 614 } | |
| 615 | 599 |
| 616 private: | 600 private: |
| 617 FinalizablePersistentHandle* free_list_; | 601 FinalizablePersistentHandle* free_list_; |
| 618 Mutex* mutex_; | 602 Mutex* mutex_; |
| 619 DISALLOW_COPY_AND_ASSIGN(FinalizablePersistentHandles); | 603 DISALLOW_COPY_AND_ASSIGN(FinalizablePersistentHandles); |
| 620 }; | 604 }; |
| 621 | 605 |
| 622 | 606 |
| 623 // Structure used for the implementation of local scopes used in dart_api. | 607 // Structure used for the implementation of local scopes used in dart_api. |
| 624 // These local scopes manage handles and memory allocated in the scope. | 608 // These local scopes manage handles and memory allocated in the scope. |
| 625 class ApiLocalScope { | 609 class ApiLocalScope { |
| 626 public: | 610 public: |
| 627 ApiLocalScope(ApiLocalScope* previous, uword stack_marker) : | 611 ApiLocalScope(ApiLocalScope* previous, uword stack_marker) |
| 628 previous_(previous), stack_marker_(stack_marker) { } | 612 : previous_(previous), stack_marker_(stack_marker) {} |
| 629 ~ApiLocalScope() { | 613 ~ApiLocalScope() { previous_ = NULL; } |
| 630 previous_ = NULL; | |
| 631 } | |
| 632 | 614 |
| 633 // Reinit the ApiLocalScope to new values. | 615 // Reinit the ApiLocalScope to new values. |
| 634 void Reinit(Thread* thread, ApiLocalScope* previous, uword stack_marker) { | 616 void Reinit(Thread* thread, ApiLocalScope* previous, uword stack_marker) { |
| 635 previous_ = previous; | 617 previous_ = previous; |
| 636 stack_marker_ = stack_marker; | 618 stack_marker_ = stack_marker; |
| 637 zone_.Reinit(thread); | 619 zone_.Reinit(thread); |
| 638 } | 620 } |
| 639 | 621 |
| 640 // Reset the ApiLocalScope so that it can be reused again. | 622 // Reset the ApiLocalScope so that it can be reused again. |
| 641 void Reset(Thread* thread) { | 623 void Reset(Thread* thread) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 661 DISALLOW_COPY_AND_ASSIGN(ApiLocalScope); | 643 DISALLOW_COPY_AND_ASSIGN(ApiLocalScope); |
| 662 }; | 644 }; |
| 663 | 645 |
| 664 | 646 |
| 665 class ApiNativeScope { | 647 class ApiNativeScope { |
| 666 public: | 648 public: |
| 667 ApiNativeScope() { | 649 ApiNativeScope() { |
| 668 // Currently no support for nesting native scopes. | 650 // Currently no support for nesting native scopes. |
| 669 ASSERT(Current() == NULL); | 651 ASSERT(Current() == NULL); |
| 670 OSThread::SetThreadLocal(Api::api_native_key_, | 652 OSThread::SetThreadLocal(Api::api_native_key_, |
| 671 reinterpret_cast<uword>(this)); | 653 reinterpret_cast<uword>(this)); |
| 672 } | 654 } |
| 673 | 655 |
| 674 ~ApiNativeScope() { | 656 ~ApiNativeScope() { |
| 675 ASSERT(Current() == this); | 657 ASSERT(Current() == this); |
| 676 OSThread::SetThreadLocal(Api::api_native_key_, 0); | 658 OSThread::SetThreadLocal(Api::api_native_key_, 0); |
| 677 } | 659 } |
| 678 | 660 |
| 679 static inline ApiNativeScope* Current() { | 661 static inline ApiNativeScope* Current() { |
| 680 return reinterpret_cast<ApiNativeScope*>( | 662 return reinterpret_cast<ApiNativeScope*>( |
| 681 OSThread::GetThreadLocal(Api::api_native_key_)); | 663 OSThread::GetThreadLocal(Api::api_native_key_)); |
| 682 } | 664 } |
| 683 | 665 |
| 684 Zone* zone() { | 666 Zone* zone() { |
| 685 Zone* result = zone_.GetZone(); | 667 Zone* result = zone_.GetZone(); |
| 686 ASSERT(result->handles()->CountScopedHandles() == 0); | 668 ASSERT(result->handles()->CountScopedHandles() == 0); |
| 687 ASSERT(result->handles()->CountZoneHandles() == 0); | 669 ASSERT(result->handles()->CountZoneHandles() == 0); |
| 688 return result; | 670 return result; |
| 689 } | 671 } |
| 690 | 672 |
| 691 private: | 673 private: |
| 692 ApiZone zone_; | 674 ApiZone zone_; |
| 693 }; | 675 }; |
| 694 | 676 |
| 695 | 677 |
| 696 // Api growable arrays use a zone for allocation. The constructor | 678 // Api growable arrays use a zone for allocation. The constructor |
| 697 // picks the zone from the current isolate if in an isolate | 679 // picks the zone from the current isolate if in an isolate |
| 698 // environment. When outside an isolate environment it picks the zone | 680 // environment. When outside an isolate environment it picks the zone |
| 699 // from the current native scope. | 681 // from the current native scope. |
| 700 template<typename T> | 682 template <typename T> |
| 701 class ApiGrowableArray : public BaseGrowableArray<T, ValueObject> { | 683 class ApiGrowableArray : public BaseGrowableArray<T, ValueObject> { |
| 702 public: | 684 public: |
| 703 explicit ApiGrowableArray(int initial_capacity) | 685 explicit ApiGrowableArray(int initial_capacity) |
| 704 : BaseGrowableArray<T, ValueObject>( | 686 : BaseGrowableArray<T, ValueObject>(initial_capacity, |
| 705 initial_capacity, | 687 ApiNativeScope::Current()->zone()) {} |
| 706 ApiNativeScope::Current()->zone()) {} | |
| 707 ApiGrowableArray() | 688 ApiGrowableArray() |
| 708 : BaseGrowableArray<T, ValueObject>( | 689 : BaseGrowableArray<T, ValueObject>(ApiNativeScope::Current()->zone()) {} |
| 709 ApiNativeScope::Current()->zone()) {} | |
| 710 ApiGrowableArray(intptr_t initial_capacity, Zone* zone) | 690 ApiGrowableArray(intptr_t initial_capacity, Zone* zone) |
| 711 : BaseGrowableArray<T, ValueObject>(initial_capacity, zone) {} | 691 : BaseGrowableArray<T, ValueObject>(initial_capacity, zone) {} |
| 712 }; | 692 }; |
| 713 | 693 |
| 714 | 694 |
| 715 // Implementation of the API State used in dart api for maintaining | 695 // Implementation of the API State used in dart api for maintaining |
| 716 // local scopes, persistent handles etc. These are setup on a per isolate | 696 // local scopes, persistent handles etc. These are setup on a per isolate |
| 717 // basis and destroyed when the isolate is shutdown. | 697 // basis and destroyed when the isolate is shutdown. |
| 718 class ApiState { | 698 class ApiState { |
| 719 public: | 699 public: |
| 720 ApiState() : persistent_handles_(), | 700 ApiState() |
| 721 weak_persistent_handles_(), | 701 : persistent_handles_(), |
| 722 null_(NULL), | 702 weak_persistent_handles_(), |
| 723 true_(NULL), | 703 null_(NULL), |
| 724 false_(NULL), | 704 true_(NULL), |
| 725 acquired_error_(NULL) {} | 705 false_(NULL), |
| 706 acquired_error_(NULL) {} |
| 726 ~ApiState() { | 707 ~ApiState() { |
| 727 if (null_ != NULL) { | 708 if (null_ != NULL) { |
| 728 persistent_handles().FreeHandle(null_); | 709 persistent_handles().FreeHandle(null_); |
| 729 null_ = NULL; | 710 null_ = NULL; |
| 730 } | 711 } |
| 731 if (true_ != NULL) { | 712 if (true_ != NULL) { |
| 732 persistent_handles().FreeHandle(true_); | 713 persistent_handles().FreeHandle(true_); |
| 733 true_ = NULL; | 714 true_ = NULL; |
| 734 } | 715 } |
| 735 if (false_ != NULL) { | 716 if (false_ != NULL) { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 ref->set_callback(callback); | 801 ref->set_callback(callback); |
| 821 ref->set_is_queued_for_finalization(false); | 802 ref->set_is_queued_for_finalization(false); |
| 822 // This may trigger GC, so it must be called last. | 803 // This may trigger GC, so it must be called last. |
| 823 ref->SetExternalSize(external_size, isolate); | 804 ref->SetExternalSize(external_size, isolate); |
| 824 return ref; | 805 return ref; |
| 825 } | 806 } |
| 826 | 807 |
| 827 } // namespace dart | 808 } // namespace dart |
| 828 | 809 |
| 829 #endif // RUNTIME_VM_DART_API_STATE_H_ | 810 #endif // RUNTIME_VM_DART_API_STATE_H_ |
| OLD | NEW |