| 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 VM_DART_API_STATE_H_ | 5 #ifndef VM_DART_API_STATE_H_ |
| 6 #define VM_DART_API_STATE_H_ | 6 #define VM_DART_API_STATE_H_ |
| 7 | 7 |
| 8 #include "include/dart_api.h" | 8 #include "include/dart_api.h" |
| 9 | 9 |
| 10 #include "platform/thread.h" | 10 #include "platform/thread.h" |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 RawObject** raw_addr() { return &raw_; } | 198 RawObject** raw_addr() { return &raw_; } |
| 199 static intptr_t raw_offset() { | 199 static intptr_t raw_offset() { |
| 200 return OFFSET_OF(FinalizablePersistentHandle, raw_); | 200 return OFFSET_OF(FinalizablePersistentHandle, raw_); |
| 201 } | 201 } |
| 202 void* peer() const { return peer_; } | 202 void* peer() const { return peer_; } |
| 203 void set_peer(void* peer) { peer_ = peer; } | 203 void set_peer(void* peer) { peer_ = peer; } |
| 204 Dart_WeakPersistentHandleFinalizer callback() const { return callback_; } | 204 Dart_WeakPersistentHandleFinalizer callback() const { return callback_; } |
| 205 void set_callback(Dart_WeakPersistentHandleFinalizer callback) { | 205 void set_callback(Dart_WeakPersistentHandleFinalizer callback) { |
| 206 callback_ = callback; | 206 callback_ = callback; |
| 207 } | 207 } |
| 208 Dart_WeakPersistentHandle apiPrologueHandle() { | |
| 209 uword addr = reinterpret_cast<uword>(this); | |
| 210 return reinterpret_cast<Dart_WeakPersistentHandle>( | |
| 211 addr | kPrologueWeakPersistentTag); | |
| 212 } | |
| 213 Dart_WeakPersistentHandle apiHandle() { | 208 Dart_WeakPersistentHandle apiHandle() { |
| 214 return reinterpret_cast<Dart_WeakPersistentHandle>(this); | 209 return reinterpret_cast<Dart_WeakPersistentHandle>(this); |
| 215 } | 210 } |
| 216 | 211 |
| 217 void SetExternalSize(intptr_t size, Isolate* isolate) { | 212 void SetExternalSize(intptr_t size, Isolate* isolate) { |
| 218 ASSERT(size >= 0); | 213 ASSERT(size >= 0); |
| 219 set_external_size(Utils::RoundUp(size, kObjectAlignment)); | 214 set_external_size(Utils::RoundUp(size, kObjectAlignment)); |
| 220 if (SpaceForExternal() == Heap::kNew) { | 215 if (SpaceForExternal() == Heap::kNew) { |
| 221 SetExternalNewSpaceBit(); | 216 SetExternalNewSpaceBit(); |
| 222 } | 217 } |
| 223 // TODO(koda): On repeated/large external allocations for existing objects, | 218 // TODO(koda): On repeated/large external allocations for existing objects, |
| 224 // without any intervening normal allocation, GC will not trigger. | 219 // without any intervening normal allocation, GC will not trigger. |
| 225 isolate->heap()->AllocateExternal(external_size(), SpaceForExternal()); | 220 isolate->heap()->AllocateExternal(external_size(), SpaceForExternal()); |
| 226 } | 221 } |
| 227 | 222 |
| 228 // Called when the referent becomes unreachable. | 223 // Called when the referent becomes unreachable. |
| 229 void UpdateUnreachable(Isolate* isolate, bool is_prologue_weak) { | 224 void UpdateUnreachable(Isolate* isolate) { |
| 230 EnsureFreeExternal(isolate); | 225 EnsureFreeExternal(isolate); |
| 231 Finalize(isolate, this, is_prologue_weak); | 226 Finalize(isolate, this); |
| 232 } | 227 } |
| 233 | 228 |
| 234 // Called when the referent has moved, potentially between generations. | 229 // Called when the referent has moved, potentially between generations. |
| 235 void UpdateRelocated(Isolate* isolate) { | 230 void UpdateRelocated(Isolate* isolate) { |
| 236 if (IsSetNewSpaceBit() && (SpaceForExternal() == Heap::kOld)) { | 231 if (IsSetNewSpaceBit() && (SpaceForExternal() == Heap::kOld)) { |
| 237 isolate->heap()->FreeExternal(external_size(), Heap::kNew); | 232 isolate->heap()->FreeExternal(external_size(), Heap::kNew); |
| 238 isolate->heap()->AllocateExternal(external_size(), Heap::kOld); | 233 isolate->heap()->AllocateExternal(external_size(), Heap::kOld); |
| 239 ClearExternalNewSpaceBit(); | 234 ClearExternalNewSpaceBit(); |
| 240 } | 235 } |
| 241 } | 236 } |
| 242 | 237 |
| 243 // Idempotent. Called when the handle is explicitly deleted or the | 238 // Idempotent. Called when the handle is explicitly deleted or the |
| 244 // referent becomes unreachable. | 239 // referent becomes unreachable. |
| 245 void EnsureFreeExternal(Isolate* isolate) { | 240 void EnsureFreeExternal(Isolate* isolate) { |
| 246 isolate->heap()->FreeExternal(external_size(), SpaceForExternal()); | 241 isolate->heap()->FreeExternal(external_size(), SpaceForExternal()); |
| 247 set_external_size(0); | 242 set_external_size(0); |
| 248 } | 243 } |
| 249 | 244 |
| 250 static bool IsPrologueWeakPersistentHandle(Dart_WeakPersistentHandle handle) { | 245 bool IsPrologueWeakPersistent() { |
| 251 uword addr = reinterpret_cast<uword>(handle); | 246 return PrologueWeakBit::decode(external_data_); |
| 252 return (addr & kWeakPersistentTagMask) == kPrologueWeakPersistentTag; | |
| 253 } | 247 } |
| 248 |
| 249 void SetPrologueWeakPersistent(bool value) { |
| 250 external_data_ = PrologueWeakBit::update(value, external_data_); |
| 251 } |
| 252 |
| 254 static FinalizablePersistentHandle* Cast(Dart_WeakPersistentHandle handle); | 253 static FinalizablePersistentHandle* Cast(Dart_WeakPersistentHandle handle); |
| 255 | 254 |
| 256 private: | 255 private: |
| 257 enum { | 256 enum { |
| 258 kWeakPersistentTag = 0, | 257 kExternalNewSpaceBit = 0, |
| 259 kPrologueWeakPersistentTag = 1, | 258 kPrologueWeakBit = 1, |
| 260 kWeakPersistentTagSize = 1, | 259 kExternalSizeBits = 2, |
| 261 kWeakPersistentTagMask = 1, | 260 kExternalSizeBitsSize = (kBitsPerWord - 2), |
| 262 }; | 261 }; |
| 263 | 262 |
| 264 // This part of external_data_ is the number of externally allocated bytes. | 263 // This part of external_data_ is the number of externally allocated bytes. |
| 265 // TODO(koda): Measure size in words instead. | 264 // TODO(koda): Measure size in words instead. |
| 266 class ExternalSizeBits : public BitField<intptr_t, 1, kBitsPerWord - 1> {}; | 265 class ExternalSizeBits : public BitField<intptr_t, |
| 266 kExternalSizeBits, |
| 267 kExternalSizeBitsSize> {}; // NOLINT |
| 267 // This bit of external_data_ is true if the referent was created in new | 268 // This bit of external_data_ is true if the referent was created in new |
| 268 // space and UpdateRelocated has not yet detected any promotion. | 269 // space and UpdateRelocated has not yet detected any promotion. |
| 269 class ExternalNewSpaceBit : public BitField<bool, 0, 1> {}; | 270 class ExternalNewSpaceBit : public BitField<bool, kExternalNewSpaceBit, 1> {}; |
| 270 // TODO(koda): Use bitfield also for the prologue tag. | 271 // This bit is used to indicate that it is a prologue weak persistent handle. |
| 272 class PrologueWeakBit : public BitField<bool, kPrologueWeakBit, 1> {}; |
| 271 | 273 |
| 272 friend class FinalizablePersistentHandles; | 274 friend class FinalizablePersistentHandles; |
| 273 | 275 |
| 274 FinalizablePersistentHandle() | 276 FinalizablePersistentHandle() |
| 275 : raw_(NULL), | 277 : raw_(NULL), |
| 276 peer_(NULL), | 278 peer_(NULL), |
| 277 external_data_(0), | 279 external_data_(0), |
| 278 callback_(NULL) { } | 280 callback_(NULL) { } |
| 279 ~FinalizablePersistentHandle() { } | 281 ~FinalizablePersistentHandle() { } |
| 280 | 282 |
| 281 static void Finalize(Isolate* isolate, | 283 static void Finalize(Isolate* isolate, FinalizablePersistentHandle* handle); |
| 282 FinalizablePersistentHandle* handle, | |
| 283 bool is_prologue_weak); | |
| 284 | 284 |
| 285 // Overload the raw_ field as a next pointer when adding freed | 285 // Overload the raw_ field as a next pointer when adding freed |
| 286 // handles to the free list. | 286 // handles to the free list. |
| 287 FinalizablePersistentHandle* Next() { | 287 FinalizablePersistentHandle* Next() { |
| 288 return reinterpret_cast<FinalizablePersistentHandle*>(raw_); | 288 return reinterpret_cast<FinalizablePersistentHandle*>(raw_); |
| 289 } | 289 } |
| 290 void SetNext(FinalizablePersistentHandle* free_list) { | 290 void SetNext(FinalizablePersistentHandle* free_list) { |
| 291 raw_ = reinterpret_cast<RawObject*>(free_list); | 291 raw_ = reinterpret_cast<RawObject*>(free_list); |
| 292 ASSERT(!raw_->IsHeapObject()); | 292 ASSERT(!raw_->IsHeapObject()); |
| 293 } | 293 } |
| 294 void FreeHandle(FinalizablePersistentHandle* free_list) { | 294 void FreeHandle(FinalizablePersistentHandle* free_list) { |
| 295 Clear(); | 295 Clear(); |
| 296 SetNext(free_list); | 296 SetNext(free_list); |
| 297 } | 297 } |
| 298 | 298 |
| 299 void Clear() { | 299 void Clear() { |
| 300 raw_ = Object::null(); | 300 raw_ = Object::null(); |
| 301 peer_ = NULL; | 301 peer_ = NULL; |
| 302 external_data_ = 0; | 302 external_data_ = 0; |
| 303 callback_ = NULL; | 303 callback_ = NULL; |
| 304 } | 304 } |
| 305 | 305 |
| 306 intptr_t external_size() const { | 306 intptr_t external_size() const { |
| 307 return ExternalSizeBits::decode(external_data_); | 307 return ExternalSizeBits::decode(external_data_); |
| 308 } | 308 } |
| 309 | 309 |
| 310 void set_external_size(intptr_t size) { | 310 void set_external_size(intptr_t size) { |
| 311 ASSERT(ExternalSizeBits::is_valid(size)); |
| 311 external_data_ = ExternalSizeBits::update(size, external_data_); | 312 external_data_ = ExternalSizeBits::update(size, external_data_); |
| 312 } | 313 } |
| 313 | 314 |
| 314 bool IsSetNewSpaceBit() const { | 315 bool IsSetNewSpaceBit() const { |
| 315 return ExternalNewSpaceBit::decode(external_data_); | 316 return ExternalNewSpaceBit::decode(external_data_); |
| 316 } | 317 } |
| 317 | 318 |
| 318 void SetExternalNewSpaceBit() { | 319 void SetExternalNewSpaceBit() { |
| 319 external_data_ = ExternalNewSpaceBit::update(true, external_data_); | 320 external_data_ = ExternalNewSpaceBit::update(true, external_data_); |
| 320 } | 321 } |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 free_list_(NULL) { } | 503 free_list_(NULL) { } |
| 503 ~FinalizablePersistentHandles() { | 504 ~FinalizablePersistentHandles() { |
| 504 free_list_ = NULL; | 505 free_list_ = NULL; |
| 505 } | 506 } |
| 506 | 507 |
| 507 // Accessors. | 508 // Accessors. |
| 508 FinalizablePersistentHandle* free_list() const { return free_list_; } | 509 FinalizablePersistentHandle* free_list() const { return free_list_; } |
| 509 void set_free_list(FinalizablePersistentHandle* value) { free_list_ = value; } | 510 void set_free_list(FinalizablePersistentHandle* value) { free_list_ = value; } |
| 510 | 511 |
| 511 // Visit all handles stored in the various handle blocks. | 512 // Visit all handles stored in the various handle blocks. |
| 512 void VisitHandles(HandleVisitor* visitor, bool is_prologue_weak) { | 513 void VisitHandles(HandleVisitor* visitor) { |
| 513 Handles<kFinalizablePersistentHandleSizeInWords, | 514 Handles<kFinalizablePersistentHandleSizeInWords, |
| 514 kFinalizablePersistentHandlesPerChunk, | 515 kFinalizablePersistentHandlesPerChunk, |
| 515 kOffsetOfRawPtrInFinalizablePersistentHandle>::Visit( | 516 kOffsetOfRawPtrInFinalizablePersistentHandle>::Visit( |
| 516 visitor, is_prologue_weak); | 517 visitor); |
| 517 } | 518 } |
| 518 | 519 |
| 519 // Visit all object pointers stored in the various handles. | 520 // Visit all object pointers stored in the various handles. |
| 520 void VisitObjectPointers(ObjectPointerVisitor* visitor) { | 521 void VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 521 Handles<kFinalizablePersistentHandleSizeInWords, | 522 Handles<kFinalizablePersistentHandleSizeInWords, |
| 522 kFinalizablePersistentHandlesPerChunk, | 523 kFinalizablePersistentHandlesPerChunk, |
| 523 kOffsetOfRawPtrInFinalizablePersistentHandle>::VisitObjectPointers( | 524 kOffsetOfRawPtrInFinalizablePersistentHandle>::VisitObjectPointers( |
| 524 visitor); | 525 visitor); |
| 525 } | 526 } |
| 526 | 527 |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 scope = scope->previous(); | 745 scope = scope->previous(); |
| 745 } | 746 } |
| 746 persistent_handles().VisitObjectPointers(visitor); | 747 persistent_handles().VisitObjectPointers(visitor); |
| 747 if (visit_prologue_weak_handles) { | 748 if (visit_prologue_weak_handles) { |
| 748 prologue_weak_persistent_handles().VisitObjectPointers(visitor); | 749 prologue_weak_persistent_handles().VisitObjectPointers(visitor); |
| 749 } | 750 } |
| 750 } | 751 } |
| 751 | 752 |
| 752 void VisitWeakHandles(HandleVisitor* visitor, | 753 void VisitWeakHandles(HandleVisitor* visitor, |
| 753 bool visit_prologue_weak_handles) { | 754 bool visit_prologue_weak_handles) { |
| 754 weak_persistent_handles().VisitHandles(visitor, false); | 755 weak_persistent_handles().VisitHandles(visitor); |
| 755 if (visit_prologue_weak_handles) { | 756 if (visit_prologue_weak_handles) { |
| 756 prologue_weak_persistent_handles().VisitHandles(visitor, true); | 757 prologue_weak_persistent_handles().VisitHandles(visitor); |
| 757 } | 758 } |
| 758 } | 759 } |
| 759 | 760 |
| 760 bool IsValidLocalHandle(Dart_Handle object) const { | 761 bool IsValidLocalHandle(Dart_Handle object) const { |
| 761 ApiLocalScope* scope = top_scope_; | 762 ApiLocalScope* scope = top_scope_; |
| 762 while (scope != NULL) { | 763 while (scope != NULL) { |
| 763 if (scope->local_handles()->IsValidHandle(object)) { | 764 if (scope->local_handles()->IsValidHandle(object)) { |
| 764 return true; | 765 return true; |
| 765 } | 766 } |
| 766 scope = scope->previous(); | 767 scope = scope->previous(); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 881 ApiNativeScope::Current()->zone()) {} | 882 ApiNativeScope::Current()->zone()) {} |
| 882 ApiGrowableArray() | 883 ApiGrowableArray() |
| 883 : BaseGrowableArray<T, ValueObject>( | 884 : BaseGrowableArray<T, ValueObject>( |
| 884 ApiNativeScope::Current()->zone()) {} | 885 ApiNativeScope::Current()->zone()) {} |
| 885 }; | 886 }; |
| 886 | 887 |
| 887 | 888 |
| 888 } // namespace dart | 889 } // namespace dart |
| 889 | 890 |
| 890 #endif // VM_DART_API_STATE_H_ | 891 #endif // VM_DART_API_STATE_H_ |
| OLD | NEW |