Revision: 11347
Author: [email protected]
Date: Tue Apr 17 03:37:41 2012
Log: Process weak references between optimized JSFunctions on
scavenges.
[email protected]
Review URL: https://chromiumcodereview.appspot.com/10091027
http://code.google.com/p/v8/source/detail?r=11347
Modified:
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/incremental-marking.cc
/branches/bleeding_edge/src/mark-compact.cc
/branches/bleeding_edge/src/mark-compact.h
/branches/bleeding_edge/src/objects-visiting-inl.h
/branches/bleeding_edge/src/objects-visiting.h
=======================================
--- /branches/bleeding_edge/src/heap.cc Tue Apr 17 00:52:39 2012
+++ /branches/bleeding_edge/src/heap.cc Tue Apr 17 03:37:41 2012
@@ -1124,6 +1124,27 @@
}
+class ScavengeWeakObjectRetainer : public WeakObjectRetainer {
+ public:
+ explicit ScavengeWeakObjectRetainer(Heap* heap) : heap_(heap) { }
+
+ virtual Object* RetainAs(Object* object) {
+ if (!heap_->InFromSpace(object)) {
+ return object;
+ }
+
+ MapWord map_word = HeapObject::cast(object)->map_word();
+ if (map_word.IsForwardingAddress()) {
+ return map_word.ToForwardingAddress();
+ }
+ return NULL;
+ }
+
+ private:
+ Heap* heap_;
+};
+
+
void Heap::Scavenge() {
#ifdef DEBUG
if (FLAG_verify_heap) VerifyNonPointerSpacePointers();
@@ -1222,6 +1243,9 @@
}
incremental_marking()->UpdateMarkingDequeAfterScavenge();
+ ScavengeWeakObjectRetainer weak_object_retainer(this);
+ ProcessWeakReferences(&weak_object_retainer);
+
ASSERT(new_space_front == new_space_.top());
// Set age mark.
@@ -1308,7 +1332,8 @@
static Object* ProcessFunctionWeakReferences(Heap* heap,
Object* function,
- WeakObjectRetainer* retainer)
{
+ WeakObjectRetainer* retainer,
+ bool record_slots) {
Object* undefined = heap->undefined_value();
Object* head = undefined;
JSFunction* tail = NULL;
@@ -1325,6 +1350,12 @@
// Subsequent elements in the list.
ASSERT(tail != NULL);
tail->set_next_function_link(retain);
+ if (record_slots) {
+ Object** next_function =
+ HeapObject::RawField(tail,
JSFunction::kNextFunctionLinkOffset);
+ heap->mark_compact_collector()->RecordSlot(
+ next_function, next_function, retain);
+ }
}
// Retained function is new tail.
candidate_function = reinterpret_cast<JSFunction*>(retain);
@@ -1353,6 +1384,15 @@
Object* head = undefined;
Context* tail = NULL;
Object* candidate = global_contexts_list_;
+
+ // We don't record weak slots during marking or scavenges.
+ // Instead we do it once when we complete mark-compact cycle.
+ // Note that write barrier has no effect if we are already in the middle
of
+ // compacting mark-sweep cycle and we have to record slots manually.
+ bool record_slots =
+ gc_state() == MARK_COMPACT &&
+ mark_compact_collector()->is_compacting();
+
while (candidate != undefined) {
// Check whether to keep the candidate in the list.
Context* candidate_context = reinterpret_cast<Context*>(candidate);
@@ -1368,6 +1408,14 @@
Context::NEXT_CONTEXT_LINK,
retain,
UPDATE_WRITE_BARRIER);
+
+ if (record_slots) {
+ Object** next_context =
+ HeapObject::RawField(
+ tail, FixedArray::SizeFor(Context::NEXT_CONTEXT_LINK));
+ mark_compact_collector()->RecordSlot(
+ next_context, next_context, retain);
+ }
}
// Retained context is new tail.
candidate_context = reinterpret_cast<Context*>(retain);
@@ -1380,11 +1428,19 @@
ProcessFunctionWeakReferences(
this,
candidate_context->get(Context::OPTIMIZED_FUNCTIONS_LIST),
- retainer);
+ retainer,
+ record_slots);
candidate_context->set_unchecked(this,
Context::OPTIMIZED_FUNCTIONS_LIST,
function_list_head,
UPDATE_WRITE_BARRIER);
+ if (record_slots) {
+ Object** optimized_functions =
+ HeapObject::RawField(
+ tail,
FixedArray::SizeFor(Context::OPTIMIZED_FUNCTIONS_LIST));
+ mark_compact_collector()->RecordSlot(
+ optimized_functions, optimized_functions, function_list_head);
+ }
}
// Move to next element in the list.
@@ -1678,7 +1734,12 @@
MigrateObject(heap, object, target, object_size);
if (object_contents == POINTER_OBJECT) {
- heap->promotion_queue()->insert(target, object_size);
+ if (map->instance_type() == JS_FUNCTION_TYPE) {
+ heap->promotion_queue()->insert(
+ target, JSFunction::kNonWeakFieldsEndOffset);
+ } else {
+ heap->promotion_queue()->insert(target, object_size);
+ }
}
heap->tracer()->increment_promoted_objects_size(object_size);
=======================================
--- /branches/bleeding_edge/src/incremental-marking.cc Tue Apr 3 10:22:05
2012
+++ /branches/bleeding_edge/src/incremental-marking.cc Tue Apr 17 03:37:41
2012
@@ -830,6 +830,19 @@
MarkObjectGreyDoNotEnqueue(ctx->normalized_map_cache());
VisitGlobalContext(ctx, &marking_visitor);
+ } else if (map->instance_type() == JS_FUNCTION_TYPE) {
+ marking_visitor.VisitPointers(
+ HeapObject::RawField(obj, JSFunction::kPropertiesOffset),
+ HeapObject::RawField(obj, JSFunction::kCodeEntryOffset));
+
+ marking_visitor.VisitCodeEntry(
+ obj->address() + JSFunction::kCodeEntryOffset);
+
+ marking_visitor.VisitPointers(
+ HeapObject::RawField(obj,
+ JSFunction::kCodeEntryOffset +
kPointerSize),
+ HeapObject::RawField(obj,
+ JSFunction::kNonWeakFieldsEndOffset));
} else {
obj->IterateBody(map->instance_type(), size, &marking_visitor);
}
=======================================
--- /branches/bleeding_edge/src/mark-compact.cc Wed Apr 11 08:32:31 2012
+++ /branches/bleeding_edge/src/mark-compact.cc Tue Apr 17 03:37:41 2012
@@ -1525,12 +1525,6 @@
JSFunction::kCodeEntryOffset + kPointerSize),
HeapObject::RawField(object,
JSFunction::kNonWeakFieldsEndOffset));
-
- // Don't visit the next function list field as it is a weak reference.
- Object** next_function =
- HeapObject::RawField(object, JSFunction::kNextFunctionLinkOffset);
- heap->mark_compact_collector()->RecordSlot(
- next_function, next_function, *next_function);
}
static inline void VisitJSRegExpFields(Map* map,
=======================================
--- /branches/bleeding_edge/src/mark-compact.h Fri Mar 23 06:33:11 2012
+++ /branches/bleeding_edge/src/mark-compact.h Tue Apr 17 03:37:41 2012
@@ -543,6 +543,8 @@
void InvalidateCode(Code* code);
void ClearMarkbits();
+
+ bool is_compacting() const { return compacting_; }
private:
MarkCompactCollector();
=======================================
--- /branches/bleeding_edge/src/objects-visiting-inl.h Mon Feb 20 04:57:23
2012
+++ /branches/bleeding_edge/src/objects-visiting-inl.h Tue Apr 17 03:37:41
2012
@@ -72,9 +72,7 @@
table_.Register(kVisitSeqTwoByteString, &VisitSeqTwoByteString);
- table_.Register(kVisitJSFunction,
- &JSObjectVisitor::
- template VisitSpecialized<JSFunction::kSize>);
+ table_.Register(kVisitJSFunction, &VisitJSFunction);
table_.Register(kVisitFreeSpace, &VisitFreeSpace);
=======================================
--- /branches/bleeding_edge/src/objects-visiting.h Thu Feb 23 04:11:24 2012
+++ /branches/bleeding_edge/src/objects-visiting.h Tue Apr 17 03:37:41 2012
@@ -289,6 +289,23 @@
}
private:
+ static inline int VisitJSFunction(Map* map, HeapObject* object) {
+ Heap* heap = map->GetHeap();
+ VisitPointers(heap,
+ HeapObject::RawField(object,
JSFunction::kPropertiesOffset),
+ HeapObject::RawField(object,
JSFunction::kCodeEntryOffset));
+
+ // Don't visit code entry. We are using this visitor only during
scavenges.
+
+ VisitPointers(
+ heap,
+ HeapObject::RawField(object,
+ JSFunction::kCodeEntryOffset + kPointerSize),
+ HeapObject::RawField(object,
+ JSFunction::kNonWeakFieldsEndOffset));
+ return JSFunction::kSize;
+ }
+
static inline int VisitByteArray(Map* map, HeapObject* object) {
return reinterpret_cast<ByteArray*>(object)->ByteArraySize();
}
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev