Skip to content

Commit fe4d8e2

Browse files
hashseedCommit bot
authored andcommitted
Debugger: remove duplicate heap iterations.
R=mlippautz@chromium.org Review URL: https://codereview.chromium.org/1291043002 Cr-Commit-Position: refs/heads/master@{#30162}
1 parent 4b340c8 commit fe4d8e2

7 files changed

Lines changed: 89 additions & 234 deletions

File tree

src/debug/liveedit.cc

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -900,23 +900,6 @@ MaybeHandle<JSArray> LiveEdit::GatherCompileInfo(Handle<Script> script,
900900
}
901901

902902

903-
void LiveEdit::WrapSharedFunctionInfos(Handle<JSArray> array) {
904-
Isolate* isolate = array->GetIsolate();
905-
HandleScope scope(isolate);
906-
int len = GetArrayLength(array);
907-
for (int i = 0; i < len; i++) {
908-
Handle<SharedFunctionInfo> info(
909-
SharedFunctionInfo::cast(
910-
*Object::GetElement(isolate, array, i).ToHandleChecked()));
911-
SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create(isolate);
912-
Handle<String> name_handle(String::cast(info->name()));
913-
info_wrapper.SetProperties(name_handle, info->start_position(),
914-
info->end_position(), info);
915-
SetElementSloppy(array, i, info_wrapper.GetJSArray());
916-
}
917-
}
918-
919-
920903
// Visitor that finds all references to a particular code object,
921904
// including "CODE_TARGET" references in other code objects and replaces
922905
// them on the fly.

src/debug/liveedit.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,6 @@ class LiveEdit : AllStatic {
8181
Handle<Script> script,
8282
Handle<String> source);
8383

84-
static void WrapSharedFunctionInfos(Handle<JSArray> array);
85-
8684
static void ReplaceFunctionCode(Handle<JSArray> new_compile_info_array,
8785
Handle<JSArray> shared_info_array);
8886

src/objects.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,16 @@ void JSObject::SetNormalizedProperty(Handle<JSObject> object,
598598
}
599599

600600

601+
bool Object::HasInPrototypeChain(Isolate* isolate, Object* target) {
602+
PrototypeIterator iter(isolate, this, PrototypeIterator::START_AT_RECEIVER);
603+
while (true) {
604+
iter.AdvanceIgnoringProxies();
605+
if (iter.IsAtEnd()) return false;
606+
if (iter.IsAtEnd(target)) return true;
607+
}
608+
}
609+
610+
601611
Map* Object::GetRootMap(Isolate* isolate) {
602612
DisallowHeapAllocation no_alloc;
603613
if (IsSmi()) {

src/objects.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,8 @@ class Object {
11651165
static inline Handle<Object> GetPrototypeSkipHiddenPrototypes(
11661166
Isolate* isolate, Handle<Object> receiver);
11671167

1168+
bool HasInPrototypeChain(Isolate* isolate, Object* object);
1169+
11681170
// Returns the permanent hash code associated with this object. May return
11691171
// undefined if not yet created.
11701172
Object* GetHash();

src/runtime/runtime-debug.cc

Lines changed: 54 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,156 +1360,61 @@ RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
13601360
}
13611361

13621362

1363-
// Helper function used by Runtime_DebugReferencedBy below.
1364-
static int DebugReferencedBy(HeapIterator* iterator, JSObject* target,
1365-
Object* instance_filter, int max_references,
1366-
FixedArray* instances, int instances_size,
1367-
JSFunction* arguments_function) {
1368-
Isolate* isolate = target->GetIsolate();
1369-
SealHandleScope shs(isolate);
1370-
DisallowHeapAllocation no_allocation;
1371-
1372-
// Iterate the heap.
1373-
int count = 0;
1374-
JSObject* last = NULL;
1375-
HeapObject* heap_obj = NULL;
1376-
while (((heap_obj = iterator->next()) != NULL) &&
1377-
(max_references == 0 || count < max_references)) {
1378-
// Only look at all JSObjects.
1379-
if (heap_obj->IsJSObject()) {
1380-
// Skip context extension objects and argument arrays as these are
1381-
// checked in the context of functions using them.
1382-
JSObject* obj = JSObject::cast(heap_obj);
1383-
if (obj->IsJSContextExtensionObject() ||
1384-
obj->map()->GetConstructor() == arguments_function) {
1385-
continue;
1386-
}
1387-
1388-
// Check if the JS object has a reference to the object looked for.
1389-
if (obj->ReferencesObject(target)) {
1390-
// Check instance filter if supplied. This is normally used to avoid
1391-
// references from mirror objects (see Runtime_IsInPrototypeChain).
1392-
if (!instance_filter->IsUndefined()) {
1393-
for (PrototypeIterator iter(isolate, obj); !iter.IsAtEnd();
1394-
iter.Advance()) {
1395-
if (iter.GetCurrent() == instance_filter) {
1396-
obj = NULL; // Don't add this object.
1397-
break;
1398-
}
1399-
}
1400-
}
1401-
1402-
// Do not expose the global object directly.
1403-
if (obj->IsJSGlobalObject()) {
1404-
obj = JSGlobalObject::cast(obj)->global_proxy();
1405-
}
1406-
1407-
if (obj != NULL) {
1408-
// Valid reference found add to instance array if supplied an update
1409-
// count.
1410-
if (instances != NULL && count < instances_size) {
1411-
instances->set(count, obj);
1412-
}
1413-
last = obj;
1414-
count++;
1415-
}
1416-
}
1417-
}
1418-
}
1419-
1420-
// Check for circular reference only. This can happen when the object is only
1421-
// referenced from mirrors and has a circular reference in which case the
1422-
// object is not really alive and would have been garbage collected if not
1423-
// referenced from the mirror.
1424-
if (count == 1 && last == target) {
1425-
count = 0;
1426-
}
1427-
1428-
// Return the number of referencing objects found.
1429-
return count;
1430-
}
1431-
1432-
14331363
// Scan the heap for objects with direct references to an object
14341364
// args[0]: the object to find references to
14351365
// args[1]: constructor function for instances to exclude (Mirror)
14361366
// args[2]: the the maximum number of objects to return
14371367
RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
14381368
HandleScope scope(isolate);
14391369
DCHECK(args.length() == 3);
1440-
1441-
// Check parameters.
14421370
CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
1443-
CONVERT_ARG_HANDLE_CHECKED(Object, instance_filter, 1);
1444-
RUNTIME_ASSERT(instance_filter->IsUndefined() ||
1445-
instance_filter->IsJSObject());
1371+
CONVERT_ARG_HANDLE_CHECKED(Object, filter, 1);
1372+
RUNTIME_ASSERT(filter->IsUndefined() || filter->IsJSObject());
14461373
CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
14471374
RUNTIME_ASSERT(max_references >= 0);
14481375

1449-
1450-
// Get the constructor function for context extension and arguments array.
1451-
Handle<JSFunction> arguments_function(
1452-
JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
1453-
1454-
// Get the number of referencing objects.
1455-
int count;
1456-
// First perform a full GC in order to avoid dead objects and to make the heap
1457-
// iterable.
1376+
List<Handle<JSObject> > instances;
14581377
Heap* heap = isolate->heap();
1459-
heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
1460-
{
1461-
HeapIterator heap_iterator(heap);
1462-
count = DebugReferencedBy(&heap_iterator, *target, *instance_filter,
1463-
max_references, NULL, 0, *arguments_function);
1464-
}
1465-
1466-
// Allocate an array to hold the result.
1467-
Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
1468-
1469-
// Fill the referencing objects.
14701378
{
1471-
HeapIterator heap_iterator(heap);
1472-
count = DebugReferencedBy(&heap_iterator, *target, *instance_filter,
1473-
max_references, *instances, count,
1474-
*arguments_function);
1475-
}
1476-
1477-
// Return result as JS array.
1478-
Handle<JSFunction> constructor = isolate->array_function();
1479-
1480-
Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
1481-
JSArray::SetContent(Handle<JSArray>::cast(result), instances);
1482-
return *result;
1483-
}
1484-
1485-
1486-
// Helper function used by Runtime_DebugConstructedBy below.
1487-
static int DebugConstructedBy(HeapIterator* iterator, JSFunction* constructor,
1488-
int max_references, FixedArray* instances,
1489-
int instances_size) {
1490-
DisallowHeapAllocation no_allocation;
1491-
1492-
// Iterate the heap.
1493-
int count = 0;
1494-
HeapObject* heap_obj = NULL;
1495-
while (((heap_obj = iterator->next()) != NULL) &&
1496-
(max_references == 0 || count < max_references)) {
1497-
// Only look at all JSObjects.
1498-
if (heap_obj->IsJSObject()) {
1379+
HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
1380+
// Get the constructor function for context extension and arguments array.
1381+
Object* arguments_fun = isolate->sloppy_arguments_map()->GetConstructor();
1382+
HeapObject* heap_obj;
1383+
while ((heap_obj = iterator.next())) {
1384+
if (!heap_obj->IsJSObject()) continue;
14991385
JSObject* obj = JSObject::cast(heap_obj);
1500-
if (obj->map()->GetConstructor() == constructor) {
1501-
// Valid reference found add to instance array if supplied an update
1502-
// count.
1503-
if (instances != NULL && count < instances_size) {
1504-
instances->set(count, obj);
1505-
}
1506-
count++;
1386+
if (obj->IsJSContextExtensionObject()) continue;
1387+
if (obj->map()->GetConstructor() == arguments_fun) continue;
1388+
if (!obj->ReferencesObject(*target)) continue;
1389+
// Check filter if supplied. This is normally used to avoid
1390+
// references from mirror objects.
1391+
if (!filter->IsUndefined() &&
1392+
obj->HasInPrototypeChain(isolate, *filter)) {
1393+
continue;
1394+
}
1395+
if (obj->IsJSGlobalObject()) {
1396+
obj = JSGlobalObject::cast(obj)->global_proxy();
15071397
}
1398+
instances.Add(Handle<JSObject>(obj));
1399+
if (instances.length() == max_references) break;
1400+
}
1401+
// Iterate the rest of the heap to satisfy HeapIterator constraints.
1402+
while (iterator.next()) {
15081403
}
15091404
}
15101405

1511-
// Return the number of referencing objects found.
1512-
return count;
1406+
Handle<FixedArray> result;
1407+
if (instances.length() == 1 && instances.last().is_identical_to(target)) {
1408+
// Check for circular reference only. This can happen when the object is
1409+
// only referenced from mirrors and has a circular reference in which case
1410+
// the object is not really alive and would have been garbage collected if
1411+
// not referenced from the mirror.
1412+
result = isolate->factory()->empty_fixed_array();
1413+
} else {
1414+
result = isolate->factory()->NewFixedArray(instances.length());
1415+
for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
1416+
}
1417+
return *isolate->factory()->NewJSArrayWithElements(result);
15131418
}
15141419

15151420

@@ -1519,40 +1424,31 @@ static int DebugConstructedBy(HeapIterator* iterator, JSFunction* constructor,
15191424
RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
15201425
HandleScope scope(isolate);
15211426
DCHECK(args.length() == 2);
1522-
1523-
1524-
// Check parameters.
15251427
CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
15261428
CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
15271429
RUNTIME_ASSERT(max_references >= 0);
15281430

1529-
// Get the number of referencing objects.
1530-
int count;
1531-
// First perform a full GC in order to avoid dead objects and to make the heap
1532-
// iterable.
1431+
List<Handle<JSObject> > instances;
15331432
Heap* heap = isolate->heap();
1534-
heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
1535-
{
1536-
HeapIterator heap_iterator(heap);
1537-
count = DebugConstructedBy(&heap_iterator, *constructor, max_references,
1538-
NULL, 0);
1539-
}
1540-
1541-
// Allocate an array to hold the result.
1542-
Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
1543-
1544-
// Fill the referencing objects.
15451433
{
1546-
HeapIterator heap_iterator2(heap);
1547-
count = DebugConstructedBy(&heap_iterator2, *constructor, max_references,
1548-
*instances, count);
1434+
HeapIterator iterator(heap, HeapIterator::kFilterUnreachable);
1435+
HeapObject* heap_obj;
1436+
while ((heap_obj = iterator.next())) {
1437+
if (!heap_obj->IsJSObject()) continue;
1438+
JSObject* obj = JSObject::cast(heap_obj);
1439+
if (obj->map()->GetConstructor() != *constructor) continue;
1440+
instances.Add(Handle<JSObject>(obj));
1441+
if (instances.length() == max_references) break;
1442+
}
1443+
// Iterate the rest of the heap to satisfy HeapIterator constraints.
1444+
while (iterator.next()) {
1445+
}
15491446
}
15501447

1551-
// Return result as JS array.
1552-
Handle<JSFunction> array_function = isolate->array_function();
1553-
Handle<JSObject> result = isolate->factory()->NewJSObject(array_function);
1554-
JSArray::SetContent(Handle<JSArray>::cast(result), instances);
1555-
return *result;
1448+
Handle<FixedArray> result =
1449+
isolate->factory()->NewFixedArray(instances.length());
1450+
for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]);
1451+
return *isolate->factory()->NewJSArrayWithElements(result);
15561452
}
15571453

15581454

src/runtime/runtime-liveedit.cc

Lines changed: 19 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,6 @@
1515
namespace v8 {
1616
namespace internal {
1717

18-
19-
static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
20-
Script* script,
21-
FixedArray* buffer) {
22-
DisallowHeapAllocation no_allocation;
23-
int counter = 0;
24-
int buffer_size = buffer->length();
25-
for (HeapObject* obj = iterator->next(); obj != NULL;
26-
obj = iterator->next()) {
27-
DCHECK(obj != NULL);
28-
if (!obj->IsSharedFunctionInfo()) {
29-
continue;
30-
}
31-
SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
32-
if (shared->script() != script) {
33-
continue;
34-
}
35-
if (counter < buffer_size) {
36-
buffer->set(counter, shared);
37-
}
38-
counter++;
39-
}
40-
return counter;
41-
}
42-
43-
4418
// For a script finds all SharedFunctionInfo's in the heap that points
4519
// to this script. Returns JSArray of SharedFunctionInfo wrapped
4620
// in OpaqueReferences.
@@ -53,32 +27,29 @@ RUNTIME_FUNCTION(Runtime_LiveEditFindSharedFunctionInfosForScript) {
5327
RUNTIME_ASSERT(script_value->value()->IsScript());
5428
Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
5529

56-
const int kBufferSize = 32;
57-
58-
Handle<FixedArray> array;
59-
array = isolate->factory()->NewFixedArray(kBufferSize);
60-
int number;
30+
List<Handle<SharedFunctionInfo> > found;
6131
Heap* heap = isolate->heap();
6232
{
63-
HeapIterator heap_iterator(heap);
64-
Script* scr = *script;
65-
FixedArray* arr = *array;
66-
number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
67-
}
68-
if (number > kBufferSize) {
69-
array = isolate->factory()->NewFixedArray(number);
70-
HeapIterator heap_iterator(heap);
71-
Script* scr = *script;
72-
FixedArray* arr = *array;
73-
FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
33+
HeapIterator iterator(heap);
34+
HeapObject* heap_obj;
35+
while ((heap_obj = iterator.next())) {
36+
if (!heap_obj->IsSharedFunctionInfo()) continue;
37+
SharedFunctionInfo* shared = SharedFunctionInfo::cast(heap_obj);
38+
if (shared->script() != *script) continue;
39+
found.Add(Handle<SharedFunctionInfo>(shared));
40+
}
7441
}
7542

76-
Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
77-
result->set_length(Smi::FromInt(number));
78-
79-
LiveEdit::WrapSharedFunctionInfos(result);
80-
81-
return *result;
43+
Handle<FixedArray> result = isolate->factory()->NewFixedArray(found.length());
44+
for (int i = 0; i < found.length(); ++i) {
45+
Handle<SharedFunctionInfo> shared = found[i];
46+
SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create(isolate);
47+
Handle<String> name(String::cast(shared->name()));
48+
info_wrapper.SetProperties(name, shared->start_position(),
49+
shared->end_position(), shared);
50+
result->set(i, *info_wrapper.GetJSArray());
51+
}
52+
return *isolate->factory()->NewJSArrayWithElements(result);
8253
}
8354

8455

0 commit comments

Comments
 (0)