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