@@ -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
14371367RUNTIME_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,
15191424RUNTIME_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
0 commit comments