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 |