Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 222 | 222 |
| 223 #ifdef DEBUG | 223 #ifdef DEBUG |
| 224 void PrintStats(); | 224 void PrintStats(); |
| 225 void Print(); | 225 void Print(); |
| 226 #endif | 226 #endif |
| 227 class Pool; | 227 class Pool; |
| 228 private: | 228 private: |
| 229 explicit GlobalHandles(Isolate* isolate); | 229 explicit GlobalHandles(Isolate* isolate); |
| 230 | 230 |
| 231 // Internal node structure, one for each global handle. | 231 // Internal node structure, one for each global handle. |
| 232 class Node; | 232 class Node : public Malloced { |
| 233 public: | |
| 234 | |
| 235 void Initialize(Object* object) { | |
| 236 // Set the initial value of the handle. | |
| 237 object_ = object; | |
| 238 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | |
| 239 independent_ = false; | |
| 240 is_in_independent_tail_ = false; | |
| 241 state_ = NORMAL; | |
| 242 parameter_or_next_free_.parameter = NULL; | |
| 243 callback_ = NULL; | |
| 244 } | |
| 245 | |
| 246 Node() { | |
| 247 state_ = DESTROYED; | |
| 248 // Initialize link structure. | |
| 249 next_ = NULL; | |
| 250 prev_ = NULL; | |
| 251 } | |
| 252 | |
| 253 explicit Node(Object* object) { | |
| 254 Initialize(object); | |
| 255 // Initialize link structure. | |
| 256 next_ = NULL; | |
| 257 prev_ = NULL; | |
| 258 } | |
| 259 | |
| 260 ~Node(); | |
| 261 | |
| 262 void Destroy(GlobalHandles* global_handles) { | |
| 263 if (state_ == WEAK || IsNearDeath()) { | |
| 264 global_handles->number_of_weak_handles_--; | |
| 265 if (object_->IsJSGlobalObject()) { | |
| 266 global_handles->number_of_global_object_weak_handles_--; | |
| 267 } | |
| 268 } | |
| 269 state_ = DESTROYED; | |
| 270 } | |
| 271 | |
| 272 // Accessors for next_. | |
| 273 Node* next() { return next_; } | |
| 274 void set_next(Node* value) { next_ = value; } | |
| 275 Node** next_addr() { return &next_; } | |
| 276 | |
| 277 Node* prev() { return prev_; } | |
| 278 void set_prev(Node* value) { prev_ = value; } | |
| 279 | |
| 280 // Accessors for next free node in the free list. | |
| 281 Node* next_free() { | |
| 282 ASSERT(state_ == DESTROYED); | |
| 283 return parameter_or_next_free_.next_free; | |
| 284 } | |
| 285 void set_next_free(Node* value) { | |
| 286 ASSERT(state_ == DESTROYED); | |
| 287 parameter_or_next_free_.next_free = value; | |
| 288 } | |
| 289 | |
| 290 // Returns a link from the handle. | |
| 291 static Node* FromLocation(Object** location) { | |
| 292 ASSERT(OFFSET_OF(Node, object_) == 0); | |
| 293 return reinterpret_cast<Node*>(location); | |
| 294 } | |
| 295 | |
| 296 // Returns the handle. | |
| 297 Handle<Object> handle() { return Handle<Object>(&object_); } | |
| 298 | |
| 299 // Make this handle weak. | |
| 300 void MakeWeak(GlobalHandles* global_handles, | |
| 301 void* parameter, | |
| 302 WeakReferenceCallback callback); | |
| 303 | |
| 304 void ClearWeakness(GlobalHandles* global_handles); | |
| 305 | |
| 306 void MarkIndependent(GlobalHandles* global_handles); | |
| 307 | |
| 308 bool IsNearDeath() { | |
| 309 // Check for PENDING to ensure correct answer when processing callbacks. | |
| 310 return state_ == PENDING || state_ == NEAR_DEATH; | |
| 311 } | |
| 312 | |
| 313 bool IsWeak() { | |
| 314 return state_ == WEAK; | |
| 315 } | |
| 316 | |
| 317 bool CanBeRetainer() { | |
| 318 return state_ != DESTROYED && state_ != NEAR_DEATH; | |
| 319 } | |
| 320 | |
| 321 void SetWrapperClassId(uint16_t class_id) { | |
| 322 class_id_ = class_id; | |
| 323 } | |
| 324 | |
| 325 // Returns the id for this weak handle. | |
| 326 void set_parameter(void* parameter) { | |
| 327 ASSERT(state_ != DESTROYED); | |
| 328 parameter_or_next_free_.parameter = parameter; | |
| 329 } | |
| 330 void* parameter() { | |
| 331 ASSERT(state_ != DESTROYED); | |
| 332 return parameter_or_next_free_.parameter; | |
| 333 } | |
| 334 | |
| 335 // Returns the callback for this weak handle. | |
| 336 WeakReferenceCallback callback() { return callback_; } | |
| 337 | |
| 338 bool PostGarbageCollectionProcessing(Isolate* isolate, | |
| 339 GlobalHandles* global_handles); | |
| 340 | |
| 341 // Place the handle address first to avoid offset computation. | |
| 342 Object* object_; // Storage for object pointer. | |
| 343 | |
| 344 uint16_t class_id_; | |
| 345 | |
| 346 // Transition diagram: | |
| 347 // NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED } | |
| 348 enum State { | |
| 349 NORMAL, // Normal global handle. | |
| 350 WEAK, // Flagged as weak but not yet finalized. | |
| 351 PENDING, // Has been recognized as only reachable by weak handles. | |
| 352 NEAR_DEATH, // Callback has informed the handle is near death. | |
| 353 DESTROYED | |
| 354 }; | |
| 355 State state_ : 4; // Need one more bit for MSVC as it treats enums as signe d. | |
|
antonm
2011/05/23 19:44:19
nit: apparently more than 80 chars (or my browser
| |
| 356 | |
| 357 bool independent_ : 1; | |
| 358 bool is_in_independent_tail_ : 1; | |
| 359 | |
| 360 private: | |
| 361 // Handle specific callback. | |
| 362 WeakReferenceCallback callback_; | |
| 363 // Provided data for callback. In DESTROYED state, this is used for | |
| 364 // the free list link. | |
| 365 union { | |
| 366 void* parameter; | |
| 367 Node* next_free; | |
| 368 } parameter_or_next_free_; | |
| 369 | |
| 370 // Linkage for the list. | |
| 371 Node* next_; | |
| 372 Node* prev_; | |
| 373 | |
| 374 public: | |
| 375 TRACK_MEMORY("GlobalHandles::Node") | |
| 376 }; | |
| 377 | |
| 233 | 378 |
| 234 Isolate* isolate_; | 379 Isolate* isolate_; |
| 235 | 380 |
| 236 // Field always containing the number of weak and near-death handles. | 381 // Field always containing the number of weak and near-death handles. |
| 237 int number_of_weak_handles_; | 382 int number_of_weak_handles_; |
| 238 | 383 |
| 239 // Field always containing the number of weak and near-death handles | 384 // Field always containing the number of weak and near-death handles |
| 240 // to global objects. These objects are also included in | 385 // to global objects. These objects are also included in |
| 241 // number_of_weak_handles_. | 386 // number_of_weak_handles_. |
| 242 int number_of_global_object_weak_handles_; | 387 int number_of_global_object_weak_handles_; |
| 243 | 388 |
| 244 // Global handles are kept in a single linked list pointed to by head_. | 389 // Global handles are kept in a single linked list pointed to by |
| 245 Node* head_; | 390 // next field of an achor node. |
| 246 Node* head() { return head_; } | 391 Node anchor_node_; |
| 247 void set_head(Node* value) { head_ = value; } | 392 |
| 393 Node* head() { | |
| 394 return anchor_node_.next(); | |
| 395 } | |
| 396 | |
| 397 void set_head(Node* value) { | |
|
antonm
2011/05/23 19:44:19
it might be more easier to reason about this code
| |
| 398 anchor_node_.set_next(value); | |
| 399 if (value != NULL) { | |
| 400 value->set_prev(&anchor_node_); | |
| 401 if (young_independent_anchor_ == &anchor_node_ && | |
| 402 !value->independent_) { | |
|
antonm
2011/05/23 19:44:19
given that set_head is invoked from ::Create, is i
| |
| 403 young_independent_anchor_ = value; | |
| 404 } | |
| 405 } else { | |
| 406 young_independent_anchor_ = &anchor_node_; | |
| 407 } | |
| 408 } | |
| 409 | |
| 410 // List of independent nodes pointing to young objects. | |
| 411 // This list forms a suffix of the whole list of nodes. | |
|
antonm
2011/05/23 19:44:19
in veryfyheap, can we assert this? or overall, do
| |
| 412 Node* young_independent_anchor_; | |
| 413 | |
| 414 Node* FirstYoungIndependent() { | |
| 415 ASSERT(young_independent_anchor_ != NULL); | |
| 416 return young_independent_anchor_->next(); | |
| 417 } | |
| 248 | 418 |
| 249 // Free list for DESTROYED global handles not yet deallocated. | 419 // Free list for DESTROYED global handles not yet deallocated. |
| 250 Node* first_free_; | 420 Node* first_free_; |
| 251 Node* first_free() { return first_free_; } | 421 Node* first_free() { return first_free_; } |
| 252 void set_first_free(Node* value) { first_free_ = value; } | 422 void set_first_free(Node* value) { first_free_ = value; } |
| 253 | 423 |
| 424 void UnlinkNode(Node* node); | |
| 425 void LinkAfter(Node* prev, Node* node); | |
| 426 void RemoveFromIndependentTail(Node* node); | |
| 427 | |
| 428 | |
|
antonm
2011/05/23 19:44:19
nit: extra blank line?
| |
| 254 // List of deallocated nodes. | 429 // List of deallocated nodes. |
| 255 // Deallocated nodes form a prefix of all the nodes and | 430 // Deallocated nodes form a prefix of all the nodes and |
| 256 // |first_deallocated| points to last deallocated node before | 431 // |first_deallocated| points to last deallocated node before |
| 257 // |head|. Those deallocated nodes are additionally linked | 432 // |head|. Those deallocated nodes are additionally linked |
| 258 // by |next_free|: | 433 // by |next_free|: |
| 259 // 1st deallocated head | 434 // 1st deallocated head |
| 260 // | | | 435 // | | |
| 261 // V V | 436 // V V |
| 262 // node node ... node node | 437 // node node ... node node |
| 263 // .next -> .next -> .next -> | 438 // .next -> .next -> .next -> |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 275 | 450 |
| 276 friend class Isolate; | 451 friend class Isolate; |
| 277 | 452 |
| 278 DISALLOW_COPY_AND_ASSIGN(GlobalHandles); | 453 DISALLOW_COPY_AND_ASSIGN(GlobalHandles); |
| 279 }; | 454 }; |
| 280 | 455 |
| 281 | 456 |
| 282 } } // namespace v8::internal | 457 } } // namespace v8::internal |
| 283 | 458 |
| 284 #endif // V8_GLOBAL_HANDLES_H_ | 459 #endif // V8_GLOBAL_HANDLES_H_ |
| OLD | NEW |