Commit fe4d8e28 authored by yangguo's avatar yangguo Committed by Commit bot

Debugger: remove duplicate heap iterations.

R=mlippautz@chromium.org

Review URL: https://codereview.chromium.org/1291043002

Cr-Commit-Position: refs/heads/master@{#30162}
parent 4b340c89
...@@ -900,23 +900,6 @@ MaybeHandle<JSArray> LiveEdit::GatherCompileInfo(Handle<Script> script, ...@@ -900,23 +900,6 @@ MaybeHandle<JSArray> LiveEdit::GatherCompileInfo(Handle<Script> script,
} }
void LiveEdit::WrapSharedFunctionInfos(Handle<JSArray> array) {
Isolate* isolate = array->GetIsolate();
HandleScope scope(isolate);
int len = GetArrayLength(array);
for (int i = 0; i < len; i++) {
Handle<SharedFunctionInfo> info(
SharedFunctionInfo::cast(
*Object::GetElement(isolate, array, i).ToHandleChecked()));
SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create(isolate);
Handle<String> name_handle(String::cast(info->name()));
info_wrapper.SetProperties(name_handle, info->start_position(),
info->end_position(), info);
SetElementSloppy(array, i, info_wrapper.GetJSArray());
}
}
// Visitor that finds all references to a particular code object, // Visitor that finds all references to a particular code object,
// including "CODE_TARGET" references in other code objects and replaces // including "CODE_TARGET" references in other code objects and replaces
// them on the fly. // them on the fly.
......
...@@ -81,8 +81,6 @@ class LiveEdit : AllStatic { ...@@ -81,8 +81,6 @@ class LiveEdit : AllStatic {
Handle<Script> script, Handle<Script> script,
Handle<String> source); Handle<String> source);
static void WrapSharedFunctionInfos(Handle<JSArray> array);
static void ReplaceFunctionCode(Handle<JSArray> new_compile_info_array, static void ReplaceFunctionCode(Handle<JSArray> new_compile_info_array,
Handle<JSArray> shared_info_array); Handle<JSArray> shared_info_array);
......
...@@ -598,6 +598,16 @@ void JSObject::SetNormalizedProperty(Handle<JSObject> object, ...@@ -598,6 +598,16 @@ void JSObject::SetNormalizedProperty(Handle<JSObject> object,
} }
bool Object::HasInPrototypeChain(Isolate* isolate, Object* target) {
PrototypeIterator iter(isolate, this, PrototypeIterator::START_AT_RECEIVER);
while (true) {
iter.AdvanceIgnoringProxies();
if (iter.IsAtEnd()) return false;
if (iter.IsAtEnd(target)) return true;
}
}
Map* Object::GetRootMap(Isolate* isolate) { Map* Object::GetRootMap(Isolate* isolate) {
DisallowHeapAllocation no_alloc; DisallowHeapAllocation no_alloc;
if (IsSmi()) { if (IsSmi()) {
......
...@@ -1165,6 +1165,8 @@ class Object { ...@@ -1165,6 +1165,8 @@ class Object {
static inline Handle<Object> GetPrototypeSkipHiddenPrototypes( static inline Handle<Object> GetPrototypeSkipHiddenPrototypes(
Isolate* isolate, Handle<Object> receiver); Isolate* isolate, Handle<Object> receiver);
bool HasInPrototypeChain(Isolate* isolate, Object* object);
// Returns the permanent hash code associated with this object. May return // Returns the permanent hash code associated with this object. May return
// undefined if not yet created. // undefined if not yet created.
Object* GetHash(); Object* GetHash();
......
...@@ -1360,76 +1360,6 @@ RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) { ...@@ -1360,76 +1360,6 @@ RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
} }
// Helper function used by Runtime_DebugReferencedBy below.
static int DebugReferencedBy(HeapIterator* iterator, JSObject* target,
Object* instance_filter, int max_references,
FixedArray* instances, int instances_size,
JSFunction* arguments_function) {
Isolate* isolate = target->GetIsolate();
SealHandleScope shs(isolate);
DisallowHeapAllocation no_allocation;
// Iterate the heap.
int count = 0;
JSObject* last = NULL;
HeapObject* heap_obj = NULL;
while (((heap_obj = iterator->next()) != NULL) &&
(max_references == 0 || count < max_references)) {
// Only look at all JSObjects.
if (heap_obj->IsJSObject()) {
// Skip context extension objects and argument arrays as these are
// checked in the context of functions using them.
JSObject* obj = JSObject::cast(heap_obj);
if (obj->IsJSContextExtensionObject() ||
obj->map()->GetConstructor() == arguments_function) {
continue;
}
// Check if the JS object has a reference to the object looked for.
if (obj->ReferencesObject(target)) {
// Check instance filter if supplied. This is normally used to avoid
// references from mirror objects (see Runtime_IsInPrototypeChain).
if (!instance_filter->IsUndefined()) {
for (PrototypeIterator iter(isolate, obj); !iter.IsAtEnd();
iter.Advance()) {
if (iter.GetCurrent() == instance_filter) {
obj = NULL; // Don't add this object.
break;
}
}
}
// Do not expose the global object directly.
if (obj->IsJSGlobalObject()) {
obj = JSGlobalObject::cast(obj)->global_proxy();
}
if (obj != NULL) {
// Valid reference found add to instance array if supplied an update
// count.
if (instances != NULL && count < instances_size) {
instances->set(count, obj);
}
last = obj;
count++;
}
}
}
}
// Check for circular reference only. This can happen when the object is only
// referenced from mirrors and has a circular reference in which case the
// object is not really alive and would have been garbage collected if not
// referenced from the mirror.
if (count == 1 && last == target) {
count = 0;
}
// Return the number of referencing objects found.
return count;
}
// Scan the heap for objects with direct references to an object // Scan the heap for objects with direct references to an object
// args[0]: the object to find references to // args[0]: the object to find references to
// args[1]: constructor function for instances to exclude (Mirror) // args[1]: constructor function for instances to exclude (Mirror)
...@@ -1437,79 +1367,54 @@ static int DebugReferencedBy(HeapIterator* iterator, JSObject* target, ...@@ -1437,79 +1367,54 @@ static int DebugReferencedBy(HeapIterator* iterator, JSObject* target,
RUNTIME_FUNCTION(Runtime_DebugReferencedBy) { RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 3); DCHECK(args.length() == 3);
// Check parameters.
CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0); CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, instance_filter, 1); CONVERT_ARG_HANDLE_CHECKED(Object, filter, 1);
RUNTIME_ASSERT(instance_filter->IsUndefined() || RUNTIME_ASSERT(filter->IsUndefined() || filter->IsJSObject());
instance_filter->IsJSObject());
CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]); CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
RUNTIME_ASSERT(max_references >= 0); RUNTIME_ASSERT(max_references >= 0);
List<Handle<JSObject> > instances;
// Get the constructor function for context extension and arguments array.
Handle<JSFunction> arguments_function(
JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
// Get the number of referencing objects.
int count;
// First perform a full GC in order to avoid dead objects and to make the heap
// iterable.
Heap* heap = isolate->heap(); Heap* heap = isolate->heap();
heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
{
HeapIterator heap_iterator(heap);
count = DebugReferencedBy(&heap_iterator, *target, *instance_filter,
max_references, NULL, 0, *arguments_function);
}
// Allocate an array to hold the result.
Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
// Fill the referencing objects.
{ {
HeapIterator heap_iterator(heap); HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
count = DebugReferencedBy(&heap_iterator, *target, *instance_filter, // Get the constructor function for context extension and arguments array.
max_references, *instances, count, Object* arguments_fun = isolate->sloppy_arguments_map()->GetConstructor();
*arguments_function); HeapObject* heap_obj;
} while ((heap_obj = iterator.next())) {
if (!heap_obj->IsJSObject()) continue;
// Return result as JS array.
Handle<JSFunction> constructor = isolate->array_function();
Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
JSArray::SetContent(Handle<JSArray>::cast(result), instances);
return *result;
}
// Helper function used by Runtime_DebugConstructedBy below.
static int DebugConstructedBy(HeapIterator* iterator, JSFunction* constructor,
int max_references, FixedArray* instances,
int instances_size) {
DisallowHeapAllocation no_allocation;
// Iterate the heap.
int count = 0;
HeapObject* heap_obj = NULL;
while (((heap_obj = iterator->next()) != NULL) &&
(max_references == 0 || count < max_references)) {
// Only look at all JSObjects.
if (heap_obj->IsJSObject()) {
JSObject* obj = JSObject::cast(heap_obj); JSObject* obj = JSObject::cast(heap_obj);
if (obj->map()->GetConstructor() == constructor) { if (obj->IsJSContextExtensionObject()) continue;
// Valid reference found add to instance array if supplied an update if (obj->map()->GetConstructor() == arguments_fun) continue;
// count. if (!obj->ReferencesObject(*target)) continue;
if (instances != NULL && count < instances_size) { // Check filter if supplied. This is normally used to avoid
instances->set(count, obj); // references from mirror objects.
} if (!filter->IsUndefined() &&
count++; obj->HasInPrototypeChain(isolate, *filter)) {
continue;
}
if (obj->IsJSGlobalObject()) {
obj = JSGlobalObject::cast(obj)->global_proxy();
} }
instances.Add(Handle<JSObject>(obj));
if (instances.length() == max_references) break;
}
// Iterate the rest of the heap to satisfy HeapIterator constraints.
while (iterator.next()) {
} }
} }
// Return the number of referencing objects found. Handle<FixedArray> result;
return count; if (instances.length() == 1 && instances.last().is_identical_to(target)) {
// Check for circular reference only. This can happen when the object is
// only referenced from mirrors and has a circular reference in which case
// the object is not really alive and would have been garbage collected if
// not referenced from the mirror.
result = isolate->factory()->empty_fixed_array();
} else {
result = isolate->factory()->NewFixedArray(instances.length());
for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
}
return *isolate->factory()->NewJSArrayWithElements(result);
} }
...@@ -1519,40 +1424,31 @@ static int DebugConstructedBy(HeapIterator* iterator, JSFunction* constructor, ...@@ -1519,40 +1424,31 @@ static int DebugConstructedBy(HeapIterator* iterator, JSFunction* constructor,
RUNTIME_FUNCTION(Runtime_DebugConstructedBy) { RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 2); DCHECK(args.length() == 2);
// Check parameters.
CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0); CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]); CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
RUNTIME_ASSERT(max_references >= 0); RUNTIME_ASSERT(max_references >= 0);
// Get the number of referencing objects. List<Handle<JSObject> > instances;
int count;
// First perform a full GC in order to avoid dead objects and to make the heap
// iterable.
Heap* heap = isolate->heap(); Heap* heap = isolate->heap();
heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
{
HeapIterator heap_iterator(heap);
count = DebugConstructedBy(&heap_iterator, *constructor, max_references,
NULL, 0);
}
// Allocate an array to hold the result.
Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
// Fill the referencing objects.
{ {
HeapIterator heap_iterator2(heap); HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
count = DebugConstructedBy(&heap_iterator2, *constructor, max_references, HeapObject* heap_obj;
*instances, count); while ((heap_obj = iterator.next())) {
if (!heap_obj->IsJSObject()) continue;
JSObject* obj = JSObject::cast(heap_obj);
if (obj->map()->GetConstructor() != *constructor) continue;
instances.Add(Handle<JSObject>(obj));
if (instances.length() == max_references) break;
}
// Iterate the rest of the heap to satisfy HeapIterator constraints.
while (iterator.next()) {
}
} }
// Return result as JS array. Handle<FixedArray> result =
Handle<JSFunction> array_function = isolate->array_function(); isolate->factory()->NewFixedArray(instances.length());
Handle<JSObject> result = isolate->factory()->NewJSObject(array_function); for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
JSArray::SetContent(Handle<JSArray>::cast(result), instances); return *isolate->factory()->NewJSArrayWithElements(result);
return *result;
} }
......
...@@ -15,32 +15,6 @@ ...@@ -15,32 +15,6 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
Script* script,
FixedArray* buffer) {
DisallowHeapAllocation no_allocation;
int counter = 0;
int buffer_size = buffer->length();
for (HeapObject* obj = iterator->next(); obj != NULL;
obj = iterator->next()) {
DCHECK(obj != NULL);
if (!obj->IsSharedFunctionInfo()) {
continue;
}
SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
if (shared->script() != script) {
continue;
}
if (counter < buffer_size) {
buffer->set(counter, shared);
}
counter++;
}
return counter;
}
// For a script finds all SharedFunctionInfo's in the heap that points // For a script finds all SharedFunctionInfo's in the heap that points
// to this script. Returns JSArray of SharedFunctionInfo wrapped // to this script. Returns JSArray of SharedFunctionInfo wrapped
// in OpaqueReferences. // in OpaqueReferences.
...@@ -53,32 +27,29 @@ RUNTIME_FUNCTION(Runtime_LiveEditFindSharedFunctionInfosForScript) { ...@@ -53,32 +27,29 @@ RUNTIME_FUNCTION(Runtime_LiveEditFindSharedFunctionInfosForScript) {
RUNTIME_ASSERT(script_value->value()->IsScript()); RUNTIME_ASSERT(script_value->value()->IsScript());
Handle<Script> script = Handle<Script>(Script::cast(script_value->value())); Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
const int kBufferSize = 32; List<Handle<SharedFunctionInfo> > found;
Handle<FixedArray> array;
array = isolate->factory()->NewFixedArray(kBufferSize);
int number;
Heap* heap = isolate->heap(); Heap* heap = isolate->heap();
{ {
HeapIterator heap_iterator(heap); HeapIterator iterator(heap);
Script* scr = *script; HeapObject* heap_obj;
FixedArray* arr = *array; while ((heap_obj = iterator.next())) {
number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr); if (!heap_obj->IsSharedFunctionInfo()) continue;
} SharedFunctionInfo* shared = SharedFunctionInfo::cast(heap_obj);
if (number > kBufferSize) { if (shared->script() != *script) continue;
array = isolate->factory()->NewFixedArray(number); found.Add(Handle<SharedFunctionInfo>(shared));
HeapIterator heap_iterator(heap); }
Script* scr = *script;
FixedArray* arr = *array;
FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
} }
Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array); Handle<FixedArray> result = isolate->factory()->NewFixedArray(found.length());
result->set_length(Smi::FromInt(number)); for (int i = 0; i < found.length(); ++i) {
Handle<SharedFunctionInfo> shared = found[i];
LiveEdit::WrapSharedFunctionInfos(result); SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create(isolate);
Handle<String> name(String::cast(shared->name()));
return *result; info_wrapper.SetProperties(name, shared->start_position(),
shared->end_position(), shared);
result->set(i, *info_wrapper.GetJSArray());
}
return *isolate->factory()->NewJSArrayWithElements(result);
} }
......
...@@ -264,17 +264,12 @@ RUNTIME_FUNCTION(Runtime_SetPrototype) { ...@@ -264,17 +264,12 @@ RUNTIME_FUNCTION(Runtime_SetPrototype) {
RUNTIME_FUNCTION(Runtime_IsInPrototypeChain) { RUNTIME_FUNCTION(Runtime_IsInPrototypeChain) {
HandleScope shs(isolate); SealHandleScope shs(isolate);
DCHECK(args.length() == 2); DCHECK(args.length() == 2);
// See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8). // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
CONVERT_ARG_HANDLE_CHECKED(Object, O, 0); CONVERT_ARG_CHECKED(Object, O, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, V, 1); CONVERT_ARG_CHECKED(Object, V, 1);
PrototypeIterator iter(isolate, V, PrototypeIterator::START_AT_RECEIVER); return isolate->heap()->ToBoolean(V->HasInPrototypeChain(isolate, O));
while (true) {
iter.AdvanceIgnoringProxies();
if (iter.IsAtEnd()) return isolate->heap()->false_value();
if (iter.IsAtEnd(O)) return isolate->heap()->true_value();
}
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment