OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 ~Node() { | 83 ~Node() { |
84 // TODO(1428): if it's a weak handle we should have invoked its callback. | 84 // TODO(1428): if it's a weak handle we should have invoked its callback. |
85 // Zap the values for eager trapping. | 85 // Zap the values for eager trapping. |
86 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 86 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
87 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 87 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
88 index_ = 0; | 88 index_ = 0; |
89 set_independent(false); | 89 set_independent(false); |
90 set_partially_dependent(false); | 90 set_partially_dependent(false); |
91 set_in_new_space_list(false); | 91 set_in_new_space_list(false); |
92 parameter_or_next_free_.next_free = NULL; | 92 parameter_or_next_free_.next_free = NULL; |
93 weak_reference_callback_ = NULL; | 93 weak_callback_ = NULL; |
94 } | 94 } |
95 #endif | 95 #endif |
96 | 96 |
97 void Initialize(int index, Node** first_free) { | 97 void Initialize(int index, Node** first_free) { |
98 index_ = static_cast<uint8_t>(index); | 98 index_ = static_cast<uint8_t>(index); |
99 ASSERT(static_cast<int>(index_) == index); | 99 ASSERT(static_cast<int>(index_) == index); |
100 set_state(FREE); | 100 set_state(FREE); |
101 set_in_new_space_list(false); | 101 set_in_new_space_list(false); |
102 parameter_or_next_free_.next_free = *first_free; | 102 parameter_or_next_free_.next_free = *first_free; |
103 *first_free = this; | 103 *first_free = this; |
104 } | 104 } |
105 | 105 |
106 void Acquire(Object* object) { | 106 void Acquire(Object* object) { |
107 ASSERT(state() == FREE); | 107 ASSERT(state() == FREE); |
108 object_ = object; | 108 object_ = object; |
109 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 109 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
110 set_independent(false); | 110 set_independent(false); |
111 set_partially_dependent(false); | 111 set_partially_dependent(false); |
112 set_state(NORMAL); | 112 set_state(NORMAL); |
113 parameter_or_next_free_.parameter = NULL; | 113 parameter_or_next_free_.parameter = NULL; |
114 weak_reference_callback_ = NULL; | 114 weak_callback_ = NULL; |
115 IncreaseBlockUses(); | 115 IncreaseBlockUses(); |
116 } | 116 } |
117 | 117 |
118 void Release() { | 118 void Release() { |
119 ASSERT(state() != FREE); | 119 ASSERT(state() != FREE); |
120 set_state(FREE); | 120 set_state(FREE); |
121 #ifdef ENABLE_EXTRA_CHECKS | 121 #ifdef ENABLE_EXTRA_CHECKS |
122 // Zap the values for eager trapping. | 122 // Zap the values for eager trapping. |
123 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 123 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
124 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 124 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
125 set_independent(false); | 125 set_independent(false); |
126 set_partially_dependent(false); | 126 set_partially_dependent(false); |
127 weak_reference_callback_ = NULL; | 127 weak_callback_ = NULL; |
128 #endif | 128 #endif |
129 DecreaseBlockUses(); | 129 DecreaseBlockUses(); |
130 } | 130 } |
131 | 131 |
132 // Object slot accessors. | 132 // Object slot accessors. |
133 Object* object() const { return object_; } | 133 Object* object() const { return object_; } |
134 Object** location() { return &object_; } | 134 Object** location() { return &object_; } |
135 Handle<Object> handle() { return Handle<Object>(location()); } | 135 Handle<Object> handle() { return Handle<Object>(location()); } |
136 | 136 |
137 // Wrapper class ID accessors. | 137 // Wrapper class ID accessors. |
(...skipping 26 matching lines...) Expand all Loading... |
164 flags_ = IsPartiallyDependent::update(flags_, v); | 164 flags_ = IsPartiallyDependent::update(flags_, v); |
165 } | 165 } |
166 | 166 |
167 bool is_in_new_space_list() { | 167 bool is_in_new_space_list() { |
168 return IsInNewSpaceList::decode(flags_); | 168 return IsInNewSpaceList::decode(flags_); |
169 } | 169 } |
170 void set_in_new_space_list(bool v) { | 170 void set_in_new_space_list(bool v) { |
171 flags_ = IsInNewSpaceList::update(flags_, v); | 171 flags_ = IsInNewSpaceList::update(flags_, v); |
172 } | 172 } |
173 | 173 |
| 174 bool is_revivable_callback() { |
| 175 return IsRevivableCallback::decode(flags_); |
| 176 } |
| 177 void set_revivable_callback(bool v) { |
| 178 flags_ = IsRevivableCallback::update(flags_, v); |
| 179 } |
| 180 |
174 bool IsNearDeath() const { | 181 bool IsNearDeath() const { |
175 // Check for PENDING to ensure correct answer when processing callbacks. | 182 // Check for PENDING to ensure correct answer when processing callbacks. |
176 return state() == PENDING || state() == NEAR_DEATH; | 183 return state() == PENDING || state() == NEAR_DEATH; |
177 } | 184 } |
178 | 185 |
179 bool IsWeak() const { return state() == WEAK; } | 186 bool IsWeak() const { return state() == WEAK; } |
180 | 187 |
181 bool IsRetainer() const { return state() != FREE; } | 188 bool IsRetainer() const { return state() != FREE; } |
182 | 189 |
183 bool IsStrongRetainer() const { return state() == NORMAL; } | 190 bool IsStrongRetainer() const { return state() == NORMAL; } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
223 Node* next_free() { | 230 Node* next_free() { |
224 ASSERT(state() == FREE); | 231 ASSERT(state() == FREE); |
225 return parameter_or_next_free_.next_free; | 232 return parameter_or_next_free_.next_free; |
226 } | 233 } |
227 void set_next_free(Node* value) { | 234 void set_next_free(Node* value) { |
228 ASSERT(state() == FREE); | 235 ASSERT(state() == FREE); |
229 parameter_or_next_free_.next_free = value; | 236 parameter_or_next_free_.next_free = value; |
230 } | 237 } |
231 | 238 |
232 void MakeWeak(void* parameter, | 239 void MakeWeak(void* parameter, |
233 RevivableCallback weak_reference_callback) { | 240 WeakCallback weak_callback, |
| 241 RevivableCallback revivable_callback) { |
| 242 ASSERT((weak_callback == NULL) != (revivable_callback == NULL)); |
234 ASSERT(state() != FREE); | 243 ASSERT(state() != FREE); |
235 set_state(WEAK); | 244 set_state(WEAK); |
236 set_parameter(parameter); | 245 set_parameter(parameter); |
237 weak_reference_callback_ = weak_reference_callback; | 246 if (weak_callback != NULL) { |
| 247 weak_callback_ = weak_callback; |
| 248 set_revivable_callback(false); |
| 249 } else { |
| 250 weak_callback_ = |
| 251 reinterpret_cast<WeakCallback>(revivable_callback); |
| 252 set_revivable_callback(true); |
| 253 } |
238 } | 254 } |
239 | 255 |
240 void ClearWeakness() { | 256 void ClearWeakness() { |
241 ASSERT(state() != FREE); | 257 ASSERT(state() != FREE); |
242 set_state(NORMAL); | 258 set_state(NORMAL); |
243 set_parameter(NULL); | 259 set_parameter(NULL); |
244 } | 260 } |
245 | 261 |
246 bool PostGarbageCollectionProcessing(Isolate* isolate) { | 262 bool PostGarbageCollectionProcessing(Isolate* isolate) { |
247 if (state() != Node::PENDING) return false; | 263 if (state() != Node::PENDING) return false; |
248 if (weak_reference_callback_ == NULL) { | 264 if (weak_callback_ == NULL) { |
249 Release(); | 265 Release(); |
250 return false; | 266 return false; |
251 } | 267 } |
252 void* par = parameter(); | 268 void* par = parameter(); |
253 set_state(NEAR_DEATH); | 269 set_state(NEAR_DEATH); |
254 set_parameter(NULL); | 270 set_parameter(NULL); |
255 | 271 |
256 Object** object = location(); | 272 Object** object = location(); |
257 { | 273 { |
258 // Check that we are not passing a finalized external string to | 274 // Check that we are not passing a finalized external string to |
259 // the callback. | 275 // the callback. |
260 ASSERT(!object_->IsExternalAsciiString() || | 276 ASSERT(!object_->IsExternalAsciiString() || |
261 ExternalAsciiString::cast(object_)->resource() != NULL); | 277 ExternalAsciiString::cast(object_)->resource() != NULL); |
262 ASSERT(!object_->IsExternalTwoByteString() || | 278 ASSERT(!object_->IsExternalTwoByteString() || |
263 ExternalTwoByteString::cast(object_)->resource() != NULL); | 279 ExternalTwoByteString::cast(object_)->resource() != NULL); |
264 // Leaving V8. | 280 // Leaving V8. |
265 VMState<EXTERNAL> state(isolate); | 281 VMState<EXTERNAL> state(isolate); |
266 HandleScope handle_scope(isolate); | 282 HandleScope handle_scope(isolate); |
267 weak_reference_callback_(reinterpret_cast<v8::Isolate*>(isolate), | 283 if (is_revivable_callback()) { |
268 reinterpret_cast<Persistent<Value>*>(&object), | 284 RevivableCallback revivable = |
269 par); | 285 reinterpret_cast<RevivableCallback>(weak_callback_); |
| 286 revivable(reinterpret_cast<v8::Isolate*>(isolate), |
| 287 reinterpret_cast<Persistent<Value>*>(&object), |
| 288 par); |
| 289 } else { |
| 290 Handle<Object> handle(*object, isolate); |
| 291 v8::WeakCallbackData<v8::Value, void> data( |
| 292 reinterpret_cast<v8::Isolate*>(isolate), |
| 293 v8::Utils::ToLocal(handle), |
| 294 par); |
| 295 weak_callback_(&data); |
| 296 } |
270 } | 297 } |
271 // Absence of explicit cleanup or revival of weak handle | 298 // Absence of explicit cleanup or revival of weak handle |
272 // in most of the cases would lead to memory leak. | 299 // in most of the cases would lead to memory leak. |
273 ASSERT(state() != NEAR_DEATH); | 300 ASSERT(state() != NEAR_DEATH); |
274 return true; | 301 return true; |
275 } | 302 } |
276 | 303 |
| 304 inline GlobalHandles* GetGlobalHandles(); |
| 305 |
277 private: | 306 private: |
278 inline NodeBlock* FindBlock(); | 307 inline NodeBlock* FindBlock(); |
279 inline GlobalHandles* GetGlobalHandles(); | |
280 inline void IncreaseBlockUses(); | 308 inline void IncreaseBlockUses(); |
281 inline void DecreaseBlockUses(); | 309 inline void DecreaseBlockUses(); |
282 | 310 |
283 // Storage for object pointer. | 311 // Storage for object pointer. |
284 // Placed first to avoid offset computation. | 312 // Placed first to avoid offset computation. |
285 Object* object_; | 313 Object* object_; |
286 | 314 |
287 // Next word stores class_id, index, state, and independent. | 315 // Next word stores class_id, index, state, and independent. |
288 // Note: the most aligned fields should go first. | 316 // Note: the most aligned fields should go first. |
289 | 317 |
290 // Wrapper class ID. | 318 // Wrapper class ID. |
291 uint16_t class_id_; | 319 uint16_t class_id_; |
292 | 320 |
293 // Index in the containing handle block. | 321 // Index in the containing handle block. |
294 uint8_t index_; | 322 uint8_t index_; |
295 | 323 |
296 // This stores three flags (independent, partially_dependent and | 324 // This stores three flags (independent, partially_dependent and |
297 // in_new_space_list) and a State. | 325 // in_new_space_list) and a State. |
298 class NodeState: public BitField<State, 0, 4> {}; | 326 class NodeState: public BitField<State, 0, 4> {}; |
299 class IsIndependent: public BitField<bool, 4, 1> {}; | 327 class IsIndependent: public BitField<bool, 4, 1> {}; |
300 class IsPartiallyDependent: public BitField<bool, 5, 1> {}; | 328 class IsPartiallyDependent: public BitField<bool, 5, 1> {}; |
301 class IsInNewSpaceList: public BitField<bool, 6, 1> {}; | 329 class IsInNewSpaceList: public BitField<bool, 6, 1> {}; |
| 330 class IsRevivableCallback: public BitField<bool, 7, 1> {}; |
302 | 331 |
303 uint8_t flags_; | 332 uint8_t flags_; |
304 | 333 |
305 // Handle specific callback - might be a weak reference in disguise. | 334 // Handle specific callback - might be a weak reference in disguise. |
306 RevivableCallback weak_reference_callback_; | 335 WeakCallback weak_callback_; |
307 | 336 |
308 // Provided data for callback. In FREE state, this is used for | 337 // Provided data for callback. In FREE state, this is used for |
309 // the free list link. | 338 // the free list link. |
310 union { | 339 union { |
311 void* parameter; | 340 void* parameter; |
312 Node* next_free; | 341 Node* next_free; |
313 } parameter_or_next_free_; | 342 } parameter_or_next_free_; |
314 | 343 |
315 DISALLOW_COPY_AND_ASSIGN(Node); | 344 DISALLOW_COPY_AND_ASSIGN(Node); |
316 }; | 345 }; |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 result->Acquire(value); | 504 result->Acquire(value); |
476 if (isolate_->heap()->InNewSpace(value) && | 505 if (isolate_->heap()->InNewSpace(value) && |
477 !result->is_in_new_space_list()) { | 506 !result->is_in_new_space_list()) { |
478 new_space_nodes_.Add(result); | 507 new_space_nodes_.Add(result); |
479 result->set_in_new_space_list(true); | 508 result->set_in_new_space_list(true); |
480 } | 509 } |
481 return result->handle(); | 510 return result->handle(); |
482 } | 511 } |
483 | 512 |
484 | 513 |
| 514 Handle<Object> GlobalHandles::CopyGlobal(Object** location) { |
| 515 ASSERT(location != NULL); |
| 516 return Node::FromLocation(location)->GetGlobalHandles()->Create(*location); |
| 517 } |
| 518 |
| 519 |
485 void GlobalHandles::Destroy(Object** location) { | 520 void GlobalHandles::Destroy(Object** location) { |
486 if (location != NULL) Node::FromLocation(location)->Release(); | 521 if (location != NULL) Node::FromLocation(location)->Release(); |
487 } | 522 } |
488 | 523 |
489 | 524 |
490 void GlobalHandles::MakeWeak(Object** location, | 525 void GlobalHandles::MakeWeak(Object** location, |
491 void* parameter, | 526 void* parameter, |
492 RevivableCallback weak_reference_callback) { | 527 WeakCallback weak_callback, |
493 ASSERT(weak_reference_callback != NULL); | 528 RevivableCallback revivable_callback) { |
494 Node::FromLocation(location)->MakeWeak(parameter, weak_reference_callback); | 529 Node::FromLocation(location)->MakeWeak( |
| 530 parameter, weak_callback, revivable_callback); |
495 } | 531 } |
496 | 532 |
497 | 533 |
498 void GlobalHandles::ClearWeakness(Object** location) { | 534 void GlobalHandles::ClearWeakness(Object** location) { |
499 Node::FromLocation(location)->ClearWeakness(); | 535 Node::FromLocation(location)->ClearWeakness(); |
500 } | 536 } |
501 | 537 |
502 | 538 |
503 void GlobalHandles::MarkIndependent(Object** location) { | 539 void GlobalHandles::MarkIndependent(Object** location) { |
504 Node::FromLocation(location)->MarkIndependent(); | 540 Node::FromLocation(location)->MarkIndependent(); |
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1077 ASSERT_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]); | 1113 ASSERT_EQ(isolate->heap()->the_hole_value(), blocks_[block][offset]); |
1078 blocks_[block][offset] = object; | 1114 blocks_[block][offset] = object; |
1079 if (isolate->heap()->InNewSpace(object)) { | 1115 if (isolate->heap()->InNewSpace(object)) { |
1080 new_space_indices_.Add(size_); | 1116 new_space_indices_.Add(size_); |
1081 } | 1117 } |
1082 return size_++; | 1118 return size_++; |
1083 } | 1119 } |
1084 | 1120 |
1085 | 1121 |
1086 } } // namespace v8::internal | 1122 } } // namespace v8::internal |
OLD | NEW |