| 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);
|
| }
|
| }
|
|
|
|
|
|
|