| OLD | NEW | 
|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "v8.h" | 5 #include "v8.h" | 
| 6 | 6 | 
| 7 #include "ic-inl.h" | 7 #include "ic-inl.h" | 
| 8 #include "objects-visiting.h" | 8 #include "objects-visiting.h" | 
| 9 | 9 | 
| 10 namespace v8 { | 10 namespace v8 { | 
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 184                                      kVisitStructGeneric, | 184                                      kVisitStructGeneric, | 
| 185                                      instance_size); | 185                                      instance_size); | 
| 186 | 186 | 
| 187     default: | 187     default: | 
| 188       UNREACHABLE(); | 188       UNREACHABLE(); | 
| 189       return kVisitorIdCount; | 189       return kVisitorIdCount; | 
| 190   } | 190   } | 
| 191 } | 191 } | 
| 192 | 192 | 
| 193 | 193 | 
|  | 194 // We don't record weak slots during marking or scavenges. Instead we do it | 
|  | 195 // once when we complete mark-compact cycle.  Note that write barrier has no | 
|  | 196 // effect if we are already in the middle of compacting mark-sweep cycle and we | 
|  | 197 // have to record slots manually. | 
|  | 198 static bool MustRecordSlots(Heap* heap) { | 
|  | 199   return heap->gc_state() == Heap::MARK_COMPACT && | 
|  | 200       heap->mark_compact_collector()->is_compacting(); | 
|  | 201 } | 
|  | 202 | 
|  | 203 | 
| 194 template <class T> | 204 template <class T> | 
| 195 struct WeakListVisitor; | 205 struct WeakListVisitor; | 
| 196 | 206 | 
| 197 | 207 | 
| 198 template <class T> | 208 template <class T> | 
| 199 Object* VisitWeakList(Heap* heap, | 209 Object* VisitWeakList(Heap* heap, | 
| 200                       Object* list, | 210                       Object* list, | 
| 201                       WeakObjectRetainer* retainer, | 211                       WeakObjectRetainer* retainer) { | 
| 202                       bool record_slots) { |  | 
| 203   Object* undefined = heap->undefined_value(); | 212   Object* undefined = heap->undefined_value(); | 
| 204   Object* head = undefined; | 213   Object* head = undefined; | 
| 205   T* tail = NULL; | 214   T* tail = NULL; | 
| 206   MarkCompactCollector* collector = heap->mark_compact_collector(); | 215   MarkCompactCollector* collector = heap->mark_compact_collector(); | 
|  | 216   bool record_slots = MustRecordSlots(heap); | 
| 207   while (list != undefined) { | 217   while (list != undefined) { | 
| 208     // Check whether to keep the candidate in the list. | 218     // Check whether to keep the candidate in the list. | 
| 209     T* candidate = reinterpret_cast<T*>(list); | 219     T* candidate = reinterpret_cast<T*>(list); | 
| 210     Object* retained = retainer->RetainAs(list); | 220     Object* retained = retainer->RetainAs(list); | 
| 211     if (retained != NULL) { | 221     if (retained != NULL) { | 
| 212       if (head == undefined) { | 222       if (head == undefined) { | 
| 213         // First element in the list. | 223         // First element in the list. | 
| 214         head = retained; | 224         head = retained; | 
| 215       } else { | 225       } else { | 
| 216         // Subsequent elements in the list. | 226         // Subsequent elements in the list. | 
| 217         ASSERT(tail != NULL); | 227         ASSERT(tail != NULL); | 
| 218         WeakListVisitor<T>::SetWeakNext(tail, retained); | 228         WeakListVisitor<T>::SetWeakNext(tail, retained); | 
| 219         if (record_slots) { | 229         if (record_slots) { | 
| 220           Object** next_slot = | 230           Object** next_slot = | 
| 221             HeapObject::RawField(tail, WeakListVisitor<T>::WeakNextOffset()); | 231             HeapObject::RawField(tail, WeakListVisitor<T>::WeakNextOffset()); | 
| 222           collector->RecordSlot(next_slot, next_slot, retained); | 232           collector->RecordSlot(next_slot, next_slot, retained); | 
| 223         } | 233         } | 
| 224       } | 234       } | 
| 225       // Retained object is new tail. | 235       // Retained object is new tail. | 
| 226       ASSERT(!retained->IsUndefined()); | 236       ASSERT(!retained->IsUndefined()); | 
| 227       candidate = reinterpret_cast<T*>(retained); | 237       candidate = reinterpret_cast<T*>(retained); | 
| 228       tail = candidate; | 238       tail = candidate; | 
| 229 | 239 | 
| 230 | 240 | 
| 231       // tail is a live object, visit it. | 241       // tail is a live object, visit it. | 
| 232       WeakListVisitor<T>::VisitLiveObject( | 242       WeakListVisitor<T>::VisitLiveObject(heap, tail, retainer); | 
| 233           heap, tail, retainer, record_slots); |  | 
| 234     } else { | 243     } else { | 
| 235       WeakListVisitor<T>::VisitPhantomObject(heap, candidate); | 244       WeakListVisitor<T>::VisitPhantomObject(heap, candidate); | 
| 236     } | 245     } | 
| 237 | 246 | 
| 238     // Move to next element in the list. | 247     // Move to next element in the list. | 
| 239     list = WeakListVisitor<T>::WeakNext(candidate); | 248     list = WeakListVisitor<T>::WeakNext(candidate); | 
| 240   } | 249   } | 
| 241 | 250 | 
| 242   // Terminate the list if there is one or more elements. | 251   // Terminate the list if there is one or more elements. | 
| 243   if (tail != NULL) { | 252   if (tail != NULL) { | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
| 266   } | 275   } | 
| 267 | 276 | 
| 268   static Object* WeakNext(JSFunction* function) { | 277   static Object* WeakNext(JSFunction* function) { | 
| 269     return function->next_function_link(); | 278     return function->next_function_link(); | 
| 270   } | 279   } | 
| 271 | 280 | 
| 272   static int WeakNextOffset() { | 281   static int WeakNextOffset() { | 
| 273     return JSFunction::kNextFunctionLinkOffset; | 282     return JSFunction::kNextFunctionLinkOffset; | 
| 274   } | 283   } | 
| 275 | 284 | 
| 276   static void VisitLiveObject(Heap*, JSFunction*, | 285   static void VisitLiveObject(Heap*, JSFunction*, WeakObjectRetainer*) {} | 
| 277                               WeakObjectRetainer*, bool) { |  | 
| 278   } |  | 
| 279 | 286 | 
| 280   static void VisitPhantomObject(Heap*, JSFunction*) { | 287   static void VisitPhantomObject(Heap*, JSFunction*) {} | 
| 281   } |  | 
| 282 }; | 288 }; | 
| 283 | 289 | 
| 284 | 290 | 
| 285 template<> | 291 template<> | 
| 286 struct WeakListVisitor<Code> { | 292 struct WeakListVisitor<Code> { | 
| 287   static void SetWeakNext(Code* code, Object* next) { | 293   static void SetWeakNext(Code* code, Object* next) { | 
| 288     code->set_next_code_link(next); | 294     code->set_next_code_link(next); | 
| 289   } | 295   } | 
| 290 | 296 | 
| 291   static Object* WeakNext(Code* code) { | 297   static Object* WeakNext(Code* code) { | 
| 292     return code->next_code_link(); | 298     return code->next_code_link(); | 
| 293   } | 299   } | 
| 294 | 300 | 
| 295   static int WeakNextOffset() { | 301   static int WeakNextOffset() { | 
| 296     return Code::kNextCodeLinkOffset; | 302     return Code::kNextCodeLinkOffset; | 
| 297   } | 303   } | 
| 298 | 304 | 
| 299   static void VisitLiveObject(Heap*, Code*, | 305   static void VisitLiveObject(Heap*, Code*, WeakObjectRetainer*) {} | 
| 300                               WeakObjectRetainer*, bool) { |  | 
| 301   } |  | 
| 302 | 306 | 
| 303   static void VisitPhantomObject(Heap*, Code*) { | 307   static void VisitPhantomObject(Heap*, Code*) {} | 
| 304   } |  | 
| 305 }; | 308 }; | 
| 306 | 309 | 
| 307 | 310 | 
| 308 template<> | 311 template<> | 
| 309 struct WeakListVisitor<Context> { | 312 struct WeakListVisitor<Context> { | 
| 310   static void SetWeakNext(Context* context, Object* next) { | 313   static void SetWeakNext(Context* context, Object* next) { | 
| 311     context->set(Context::NEXT_CONTEXT_LINK, | 314     context->set(Context::NEXT_CONTEXT_LINK, | 
| 312                  next, | 315                  next, | 
| 313                  UPDATE_WRITE_BARRIER); | 316                  UPDATE_WRITE_BARRIER); | 
| 314   } | 317   } | 
| 315 | 318 | 
| 316   static Object* WeakNext(Context* context) { | 319   static Object* WeakNext(Context* context) { | 
| 317     return context->get(Context::NEXT_CONTEXT_LINK); | 320     return context->get(Context::NEXT_CONTEXT_LINK); | 
| 318   } | 321   } | 
| 319 | 322 | 
|  | 323   static int WeakNextOffset() { | 
|  | 324     return FixedArray::SizeFor(Context::NEXT_CONTEXT_LINK); | 
|  | 325   } | 
|  | 326 | 
| 320   static void VisitLiveObject(Heap* heap, | 327   static void VisitLiveObject(Heap* heap, | 
| 321                               Context* context, | 328                               Context* context, | 
| 322                               WeakObjectRetainer* retainer, | 329                               WeakObjectRetainer* retainer) { | 
| 323                               bool record_slots) { |  | 
| 324     // Process the three weak lists linked off the context. | 330     // Process the three weak lists linked off the context. | 
| 325     DoWeakList<JSFunction>(heap, context, retainer, record_slots, | 331     DoWeakList<JSFunction>(heap, context, retainer, | 
| 326         Context::OPTIMIZED_FUNCTIONS_LIST); | 332         Context::OPTIMIZED_FUNCTIONS_LIST); | 
| 327     DoWeakList<Code>(heap, context, retainer, record_slots, | 333     DoWeakList<Code>(heap, context, retainer, Context::OPTIMIZED_CODE_LIST); | 
| 328         Context::OPTIMIZED_CODE_LIST); | 334     DoWeakList<Code>(heap, context, retainer, Context::DEOPTIMIZED_CODE_LIST); | 
| 329     DoWeakList<Code>(heap, context, retainer, record_slots, |  | 
| 330         Context::DEOPTIMIZED_CODE_LIST); |  | 
| 331   } | 335   } | 
| 332 | 336 | 
| 333   template<class T> | 337   template<class T> | 
| 334   static void DoWeakList(Heap* heap, | 338   static void DoWeakList(Heap* heap, | 
| 335                          Context* context, | 339                          Context* context, | 
| 336                          WeakObjectRetainer* retainer, | 340                          WeakObjectRetainer* retainer, | 
| 337                          bool record_slots, |  | 
| 338                          int index) { | 341                          int index) { | 
| 339     // Visit the weak list, removing dead intermediate elements. | 342     // Visit the weak list, removing dead intermediate elements. | 
| 340     Object* list_head = VisitWeakList<T>(heap, context->get(index), retainer, | 343     Object* list_head = VisitWeakList<T>(heap, context->get(index), retainer); | 
| 341         record_slots); |  | 
| 342 | 344 | 
| 343     // Update the list head. | 345     // Update the list head. | 
| 344     context->set(index, list_head, UPDATE_WRITE_BARRIER); | 346     context->set(index, list_head, UPDATE_WRITE_BARRIER); | 
| 345 | 347 | 
| 346     if (record_slots) { | 348     if (MustRecordSlots(heap)) { | 
| 347       // Record the updated slot if necessary. | 349       // Record the updated slot if necessary. | 
| 348       Object** head_slot = HeapObject::RawField( | 350       Object** head_slot = HeapObject::RawField( | 
| 349           context, FixedArray::SizeFor(index)); | 351           context, FixedArray::SizeFor(index)); | 
| 350       heap->mark_compact_collector()->RecordSlot( | 352       heap->mark_compact_collector()->RecordSlot( | 
| 351           head_slot, head_slot, list_head); | 353           head_slot, head_slot, list_head); | 
| 352     } | 354     } | 
| 353   } | 355   } | 
| 354 | 356 | 
| 355   static void VisitPhantomObject(Heap* heap, Context* context) { | 357   static void VisitPhantomObject(Heap* heap, Context* context) { | 
| 356     ClearWeakList<JSFunction>(heap, | 358     ClearWeakList<JSFunction>(heap, | 
| 357         context->get(Context::OPTIMIZED_FUNCTIONS_LIST)); | 359         context->get(Context::OPTIMIZED_FUNCTIONS_LIST)); | 
| 358     ClearWeakList<Code>(heap, context->get(Context::OPTIMIZED_CODE_LIST)); | 360     ClearWeakList<Code>(heap, context->get(Context::OPTIMIZED_CODE_LIST)); | 
| 359     ClearWeakList<Code>(heap, context->get(Context::DEOPTIMIZED_CODE_LIST)); | 361     ClearWeakList<Code>(heap, context->get(Context::DEOPTIMIZED_CODE_LIST)); | 
| 360   } | 362   } | 
| 361 |  | 
| 362   static int WeakNextOffset() { |  | 
| 363     return FixedArray::SizeFor(Context::NEXT_CONTEXT_LINK); |  | 
| 364   } |  | 
| 365 }; | 363 }; | 
| 366 | 364 | 
| 367 | 365 | 
| 368 template<> | 366 template<> | 
| 369 struct WeakListVisitor<JSArrayBufferView> { | 367 struct WeakListVisitor<JSArrayBufferView> { | 
| 370   static void SetWeakNext(JSArrayBufferView* obj, Object* next) { | 368   static void SetWeakNext(JSArrayBufferView* obj, Object* next) { | 
| 371     obj->set_weak_next(next); | 369     obj->set_weak_next(next); | 
| 372   } | 370   } | 
| 373 | 371 | 
| 374   static Object* WeakNext(JSArrayBufferView* obj) { | 372   static Object* WeakNext(JSArrayBufferView* obj) { | 
| 375     return obj->weak_next(); | 373     return obj->weak_next(); | 
| 376   } | 374   } | 
| 377 | 375 | 
| 378   static void VisitLiveObject(Heap*, |  | 
| 379                               JSArrayBufferView* obj, |  | 
| 380                               WeakObjectRetainer* retainer, |  | 
| 381                               bool record_slots) {} |  | 
| 382 |  | 
| 383   static void VisitPhantomObject(Heap*, JSArrayBufferView*) {} |  | 
| 384 |  | 
| 385   static int WeakNextOffset() { | 376   static int WeakNextOffset() { | 
| 386     return JSArrayBufferView::kWeakNextOffset; | 377     return JSArrayBufferView::kWeakNextOffset; | 
| 387   } | 378   } | 
|  | 379 | 
|  | 380   static void VisitLiveObject(Heap*, JSArrayBufferView*, WeakObjectRetainer*) {} | 
|  | 381 | 
|  | 382   static void VisitPhantomObject(Heap*, JSArrayBufferView*) {} | 
| 388 }; | 383 }; | 
| 389 | 384 | 
| 390 | 385 | 
| 391 template<> | 386 template<> | 
| 392 struct WeakListVisitor<JSArrayBuffer> { | 387 struct WeakListVisitor<JSArrayBuffer> { | 
| 393   static void SetWeakNext(JSArrayBuffer* obj, Object* next) { | 388   static void SetWeakNext(JSArrayBuffer* obj, Object* next) { | 
| 394     obj->set_weak_next(next); | 389     obj->set_weak_next(next); | 
| 395   } | 390   } | 
| 396 | 391 | 
| 397   static Object* WeakNext(JSArrayBuffer* obj) { | 392   static Object* WeakNext(JSArrayBuffer* obj) { | 
| 398     return obj->weak_next(); | 393     return obj->weak_next(); | 
| 399   } | 394   } | 
| 400 | 395 | 
|  | 396   static int WeakNextOffset() { | 
|  | 397     return JSArrayBuffer::kWeakNextOffset; | 
|  | 398   } | 
|  | 399 | 
| 401   static void VisitLiveObject(Heap* heap, | 400   static void VisitLiveObject(Heap* heap, | 
| 402                               JSArrayBuffer* array_buffer, | 401                               JSArrayBuffer* array_buffer, | 
| 403                               WeakObjectRetainer* retainer, | 402                               WeakObjectRetainer* retainer) { | 
| 404                               bool record_slots) { |  | 
| 405     Object* typed_array_obj = | 403     Object* typed_array_obj = | 
| 406         VisitWeakList<JSArrayBufferView>( | 404         VisitWeakList<JSArrayBufferView>( | 
| 407             heap, | 405             heap, | 
| 408             array_buffer->weak_first_view(), | 406             array_buffer->weak_first_view(), | 
| 409             retainer, record_slots); | 407             retainer); | 
| 410     array_buffer->set_weak_first_view(typed_array_obj); | 408     array_buffer->set_weak_first_view(typed_array_obj); | 
| 411     if (typed_array_obj != heap->undefined_value() && record_slots) { | 409     if (typed_array_obj != heap->undefined_value() && MustRecordSlots(heap)) { | 
| 412       Object** slot = HeapObject::RawField( | 410       Object** slot = HeapObject::RawField( | 
| 413           array_buffer, JSArrayBuffer::kWeakFirstViewOffset); | 411           array_buffer, JSArrayBuffer::kWeakFirstViewOffset); | 
| 414       heap->mark_compact_collector()->RecordSlot(slot, slot, typed_array_obj); | 412       heap->mark_compact_collector()->RecordSlot(slot, slot, typed_array_obj); | 
| 415     } | 413     } | 
| 416   } | 414   } | 
| 417 | 415 | 
| 418   static void VisitPhantomObject(Heap* heap, JSArrayBuffer* phantom) { | 416   static void VisitPhantomObject(Heap* heap, JSArrayBuffer* phantom) { | 
| 419     Runtime::FreeArrayBuffer(heap->isolate(), phantom); | 417     Runtime::FreeArrayBuffer(heap->isolate(), phantom); | 
| 420   } | 418   } | 
| 421 |  | 
| 422   static int WeakNextOffset() { |  | 
| 423     return JSArrayBuffer::kWeakNextOffset; |  | 
| 424   } |  | 
| 425 }; | 419 }; | 
| 426 | 420 | 
| 427 | 421 | 
| 428 template<> | 422 template<> | 
| 429 struct WeakListVisitor<AllocationSite> { | 423 struct WeakListVisitor<AllocationSite> { | 
| 430   static void SetWeakNext(AllocationSite* obj, Object* next) { | 424   static void SetWeakNext(AllocationSite* obj, Object* next) { | 
| 431     obj->set_weak_next(next); | 425     obj->set_weak_next(next); | 
| 432   } | 426   } | 
| 433 | 427 | 
| 434   static Object* WeakNext(AllocationSite* obj) { | 428   static Object* WeakNext(AllocationSite* obj) { | 
| 435     return obj->weak_next(); | 429     return obj->weak_next(); | 
| 436   } | 430   } | 
| 437 | 431 | 
| 438   static void VisitLiveObject(Heap* heap, |  | 
| 439                               AllocationSite* site, |  | 
| 440                               WeakObjectRetainer* retainer, |  | 
| 441                               bool record_slots) {} |  | 
| 442 |  | 
| 443   static void VisitPhantomObject(Heap* heap, AllocationSite* phantom) {} |  | 
| 444 |  | 
| 445   static int WeakNextOffset() { | 432   static int WeakNextOffset() { | 
| 446     return AllocationSite::kWeakNextOffset; | 433     return AllocationSite::kWeakNextOffset; | 
| 447   } | 434   } | 
|  | 435 | 
|  | 436   static void VisitLiveObject(Heap*, AllocationSite*, WeakObjectRetainer*) {} | 
|  | 437 | 
|  | 438   static void VisitPhantomObject(Heap*, AllocationSite*) {} | 
| 448 }; | 439 }; | 
| 449 | 440 | 
| 450 | 441 | 
| 451 template Object* VisitWeakList<Code>( | 442 template Object* VisitWeakList<Code>( | 
| 452     Heap* heap, Object* list, WeakObjectRetainer* retainer, bool record_slots); | 443     Heap* heap, Object* list, WeakObjectRetainer* retainer); | 
| 453 | 444 | 
| 454 | 445 | 
| 455 template Object* VisitWeakList<JSFunction>( | 446 template Object* VisitWeakList<JSFunction>( | 
| 456     Heap* heap, Object* list, WeakObjectRetainer* retainer, bool record_slots); | 447     Heap* heap, Object* list, WeakObjectRetainer* retainer); | 
| 457 | 448 | 
| 458 | 449 | 
| 459 template Object* VisitWeakList<Context>( | 450 template Object* VisitWeakList<Context>( | 
| 460     Heap* heap, Object* list, WeakObjectRetainer* retainer, bool record_slots); | 451     Heap* heap, Object* list, WeakObjectRetainer* retainer); | 
| 461 | 452 | 
| 462 | 453 | 
| 463 template Object* VisitWeakList<JSArrayBuffer>( | 454 template Object* VisitWeakList<JSArrayBuffer>( | 
| 464     Heap* heap, Object* list, WeakObjectRetainer* retainer, bool record_slots); | 455     Heap* heap, Object* list, WeakObjectRetainer* retainer); | 
| 465 | 456 | 
| 466 | 457 | 
| 467 template Object* VisitWeakList<AllocationSite>( | 458 template Object* VisitWeakList<AllocationSite>( | 
| 468     Heap* heap, Object* list, WeakObjectRetainer* retainer, bool record_slots); | 459     Heap* heap, Object* list, WeakObjectRetainer* retainer); | 
| 469 | 460 | 
| 470 } }  // namespace v8::internal | 461 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|