Index: src/runtime.cc |
=================================================================== |
--- src/runtime.cc (revision 9327) |
+++ src/runtime.cc (working copy) |
@@ -1735,7 +1735,7 @@ |
regexp->InObjectPropertyAtPut(JSRegExp::kMultilineFieldIndex, multiline); |
regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, |
Smi::FromInt(0), |
- SKIP_WRITE_BARRIER); |
+ SKIP_WRITE_BARRIER); // It's a Smi. |
return regexp; |
} |
@@ -2149,9 +2149,7 @@ |
literals->set(JSFunction::kLiteralGlobalContextIndex, |
context->global_context()); |
} |
- // It's okay to skip the write barrier here because the literals |
- // are guaranteed to be in old space. |
- target->set_literals(*literals, SKIP_WRITE_BARRIER); |
+ target->set_literals(*literals); |
target->set_next_function_link(isolate->heap()->undefined_value()); |
if (isolate->logger()->is_logging() || CpuProfiler::is_profiling(isolate)) { |
@@ -3152,6 +3150,9 @@ |
Address end_of_string = answer->address() + string_size; |
isolate->heap()->CreateFillerObjectAt(end_of_string, delta); |
+ if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) { |
+ MemoryChunk::IncrementLiveBytes(answer->address(), -delta); |
+ } |
return *answer; |
} |
@@ -6187,11 +6188,11 @@ |
FixedArray* ascii_cache = heap->single_character_string_cache(); |
Object* undefined = heap->undefined_value(); |
int i; |
+ WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc); |
for (i = 0; i < length; ++i) { |
Object* value = ascii_cache->get(chars[i]); |
if (value == undefined) break; |
- ASSERT(!heap->InNewSpace(value)); |
- elements->set(i, value, SKIP_WRITE_BARRIER); |
+ elements->set(i, value, mode); |
} |
if (i < length) { |
ASSERT(Smi::FromInt(0) == 0); |
@@ -11376,48 +11377,53 @@ |
int target_start_position = RelocInfo::kNoPosition; |
Handle<SharedFunctionInfo> target; |
while (!done) { |
- HeapIterator iterator; |
- for (HeapObject* obj = iterator.next(); |
- obj != NULL; obj = iterator.next()) { |
- if (obj->IsSharedFunctionInfo()) { |
- Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(obj)); |
- if (shared->script() == *script) { |
- // If the SharedFunctionInfo found has the requested script data and |
- // contains the source position it is a candidate. |
- int start_position = shared->function_token_position(); |
- if (start_position == RelocInfo::kNoPosition) { |
- start_position = shared->start_position(); |
- } |
- if (start_position <= position && |
- position <= shared->end_position()) { |
- // If there is no candidate or this function is within the current |
- // candidate this is the new candidate. |
- if (target.is_null()) { |
- target_start_position = start_position; |
- target = shared; |
- } else { |
- if (target_start_position == start_position && |
- shared->end_position() == target->end_position()) { |
- // If a top-level function contain only one function |
- // declartion the source for the top-level and the function is |
- // the same. In that case prefer the non top-level function. |
- if (!shared->is_toplevel()) { |
+ { // Extra scope for iterator and no-allocation. |
+ isolate->heap()->EnsureHeapIsIterable(); |
+ AssertNoAllocation no_alloc_during_heap_iteration; |
+ HeapIterator iterator; |
+ for (HeapObject* obj = iterator.next(); |
+ obj != NULL; obj = iterator.next()) { |
+ if (obj->IsSharedFunctionInfo()) { |
+ Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(obj)); |
+ if (shared->script() == *script) { |
+ // If the SharedFunctionInfo found has the requested script data and |
+ // contains the source position it is a candidate. |
+ int start_position = shared->function_token_position(); |
+ if (start_position == RelocInfo::kNoPosition) { |
+ start_position = shared->start_position(); |
+ } |
+ if (start_position <= position && |
+ position <= shared->end_position()) { |
+ // If there is no candidate or this function is within the current |
+ // candidate this is the new candidate. |
+ if (target.is_null()) { |
+ target_start_position = start_position; |
+ target = shared; |
+ } else { |
+ if (target_start_position == start_position && |
+ shared->end_position() == target->end_position()) { |
+ // If a top-level function contain only one function |
+ // declartion the source for the top-level and the |
+ // function is the same. In that case prefer the non |
+ // top-level function. |
+ if (!shared->is_toplevel()) { |
+ target_start_position = start_position; |
+ target = shared; |
+ } |
+ } else if (target_start_position <= start_position && |
+ shared->end_position() <= target->end_position()) { |
+ // This containment check includes equality as a function |
+ // inside a top-level function can share either start or end |
+ // position with the top-level function. |
target_start_position = start_position; |
target = shared; |
} |
- } else if (target_start_position <= start_position && |
- shared->end_position() <= target->end_position()) { |
- // This containment check includes equality as a function inside |
- // a top-level function can share either start or end position |
- // with the top-level function. |
- target_start_position = start_position; |
- target = shared; |
} |
} |
} |
} |
- } |
- } |
+ } // End for loop. |
+ } // End No allocation scope. |
if (target.is_null()) { |
return isolate->heap()->undefined_value(); |
@@ -11432,7 +11438,7 @@ |
// functions which might contain the requested source position. |
CompileLazyShared(target, KEEP_EXCEPTION); |
} |
- } |
+ } // End while loop. |
return *target; |
} |
@@ -11917,7 +11923,8 @@ |
// Helper function used by Runtime_DebugReferencedBy below. |
-static int DebugReferencedBy(JSObject* target, |
+static int DebugReferencedBy(HeapIterator* iterator, |
+ JSObject* target, |
Object* instance_filter, int max_references, |
FixedArray* instances, int instances_size, |
JSFunction* arguments_function) { |
@@ -11927,9 +11934,8 @@ |
// Iterate the heap. |
int count = 0; |
JSObject* last = NULL; |
- HeapIterator iterator; |
HeapObject* heap_obj = NULL; |
- while (((heap_obj = iterator.next()) != NULL) && |
+ while (((heap_obj = iterator->next()) != NULL) && |
(max_references == 0 || count < max_references)) { |
// Only look at all JSObjects. |
if (heap_obj->IsJSObject()) { |
@@ -11994,7 +12000,11 @@ |
ASSERT(args.length() == 3); |
// First perform a full GC in order to avoid references from dead objects. |
- isolate->heap()->CollectAllGarbage(false); |
+ isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask); |
+ // The heap iterator reserves the right to do a GC to make the heap iterable. |
+ // Due to the GC above we know it won't need to do that, but it seems cleaner |
+ // to get the heap iterator constructed before we start having unprotected |
+ // Object* locals that are not protected by handles. |
// Check parameters. |
CONVERT_CHECKED(JSObject, target, args[0]); |
@@ -12004,6 +12014,7 @@ |
CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]); |
RUNTIME_ASSERT(max_references >= 0); |
+ |
// Get the constructor function for context extension and arguments array. |
JSObject* arguments_boilerplate = |
isolate->context()->global_context()->arguments_boilerplate(); |
@@ -12012,7 +12023,9 @@ |
// Get the number of referencing objects. |
int count; |
- count = DebugReferencedBy(target, instance_filter, max_references, |
+ HeapIterator heap_iterator; |
+ count = DebugReferencedBy(&heap_iterator, |
+ target, instance_filter, max_references, |
NULL, 0, arguments_function); |
// Allocate an array to hold the result. |
@@ -12023,7 +12036,11 @@ |
FixedArray* instances = FixedArray::cast(object); |
// Fill the referencing objects. |
- count = DebugReferencedBy(target, instance_filter, max_references, |
+ // AllocateFixedArray above does not make the heap non-iterable. |
+ ASSERT(HEAP->IsHeapIterable()); |
+ HeapIterator heap_iterator2; |
+ count = DebugReferencedBy(&heap_iterator2, |
+ target, instance_filter, max_references, |
instances, count, arguments_function); |
// Return result as JS array. |
@@ -12038,15 +12055,17 @@ |
// Helper function used by Runtime_DebugConstructedBy below. |
-static int DebugConstructedBy(JSFunction* constructor, int max_references, |
- FixedArray* instances, int instances_size) { |
+static int DebugConstructedBy(HeapIterator* iterator, |
+ JSFunction* constructor, |
+ int max_references, |
+ FixedArray* instances, |
+ int instances_size) { |
AssertNoAllocation no_alloc; |
// Iterate the heap. |
int count = 0; |
- HeapIterator iterator; |
HeapObject* heap_obj = NULL; |
- while (((heap_obj = iterator.next()) != NULL) && |
+ while (((heap_obj = iterator->next()) != NULL) && |
(max_references == 0 || count < max_references)) { |
// Only look at all JSObjects. |
if (heap_obj->IsJSObject()) { |
@@ -12074,7 +12093,7 @@ |
ASSERT(args.length() == 2); |
// First perform a full GC in order to avoid dead objects. |
- isolate->heap()->CollectAllGarbage(false); |
+ isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask); |
// Check parameters. |
CONVERT_CHECKED(JSFunction, constructor, args[0]); |
@@ -12083,7 +12102,12 @@ |
// Get the number of referencing objects. |
int count; |
- count = DebugConstructedBy(constructor, max_references, NULL, 0); |
+ HeapIterator heap_iterator; |
+ count = DebugConstructedBy(&heap_iterator, |
+ constructor, |
+ max_references, |
+ NULL, |
+ 0); |
// Allocate an array to hold the result. |
Object* object; |
@@ -12092,8 +12116,14 @@ |
} |
FixedArray* instances = FixedArray::cast(object); |
+ ASSERT(HEAP->IsHeapIterable()); |
// Fill the referencing objects. |
- count = DebugConstructedBy(constructor, max_references, instances, count); |
+ HeapIterator heap_iterator2; |
+ count = DebugConstructedBy(&heap_iterator2, |
+ constructor, |
+ max_references, |
+ instances, |
+ count); |
// Return result as JS array. |
Object* result; |
@@ -12166,14 +12196,15 @@ |
} |
-static int FindSharedFunctionInfosForScript(Script* script, |
+static int FindSharedFunctionInfosForScript(HeapIterator* iterator, |
+ Script* script, |
FixedArray* buffer) { |
AssertNoAllocation no_allocations; |
- |
int counter = 0; |
int buffer_size = buffer->length(); |
- HeapIterator iterator; |
- for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
+ for (HeapObject* obj = iterator->next(); |
+ obj != NULL; |
+ obj = iterator->next()) { |
ASSERT(obj != NULL); |
if (!obj->IsSharedFunctionInfo()) { |
continue; |
@@ -12199,16 +12230,30 @@ |
HandleScope scope(isolate); |
CONVERT_CHECKED(JSValue, script_value, args[0]); |
+ |
Handle<Script> script = Handle<Script>(Script::cast(script_value->value())); |
const int kBufferSize = 32; |
Handle<FixedArray> array; |
array = isolate->factory()->NewFixedArray(kBufferSize); |
- int number = FindSharedFunctionInfosForScript(*script, *array); |
+ int number; |
+ { |
+ isolate->heap()->EnsureHeapIsIterable(); |
+ AssertNoAllocation no_allocations; |
+ HeapIterator heap_iterator; |
+ Script* scr = *script; |
+ FixedArray* arr = *array; |
+ number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr); |
+ } |
if (number > kBufferSize) { |
array = isolate->factory()->NewFixedArray(number); |
- FindSharedFunctionInfosForScript(*script, *array); |
+ isolate->heap()->EnsureHeapIsIterable(); |
+ AssertNoAllocation no_allocations; |
+ HeapIterator heap_iterator; |
+ Script* scr = *script; |
+ FixedArray* arr = *array; |
+ FindSharedFunctionInfosForScript(&heap_iterator, scr, arr); |
} |
Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array); |
@@ -12689,6 +12734,8 @@ |
// Scan the heap for Script objects to find the script with the requested |
// script data. |
Handle<Script> script; |
+ script_name->GetHeap()->EnsureHeapIsIterable(); |
+ AssertNoAllocation no_allocation_during_heap_iteration; |
HeapIterator iterator; |
HeapObject* obj = NULL; |
while (script.is_null() && ((obj = iterator.next()) != NULL)) { |
@@ -13140,6 +13187,9 @@ |
Isolate* isolate = Isolate::Current(); |
Failure* failure = Failure::cast(result); |
if (failure->IsRetryAfterGC()) { |
+ if (isolate->heap()->new_space()->AddFreshPage()) { |
+ return; |
+ } |
// Try to do a garbage collection; ignore it if it fails. The C |
// entry stub will throw an out-of-memory exception in that case. |
isolate->heap()->CollectGarbage(failure->allocation_space()); |
@@ -13147,7 +13197,7 @@ |
// Handle last resort GC and make sure to allow future allocations |
// to grow the heap without causing GCs (if possible). |
isolate->counters()->gc_last_resort_from_js()->Increment(); |
- isolate->heap()->CollectAllGarbage(false); |
+ isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); |
} |
} |