| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
| 8 #include "src/debug/debug.h" | 8 #include "src/debug/debug.h" |
| 9 #include "src/debug/debug-evaluate.h" | 9 #include "src/debug/debug-evaluate.h" |
| 10 #include "src/debug/debug-frames.h" | 10 #include "src/debug/debug-frames.h" |
| (...skipping 1342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1353 } | 1353 } |
| 1354 | 1354 |
| 1355 // Return result as a JS array. | 1355 // Return result as a JS array. |
| 1356 Handle<JSObject> result = | 1356 Handle<JSObject> result = |
| 1357 isolate->factory()->NewJSObject(isolate->array_function()); | 1357 isolate->factory()->NewJSObject(isolate->array_function()); |
| 1358 JSArray::SetContent(Handle<JSArray>::cast(result), instances); | 1358 JSArray::SetContent(Handle<JSArray>::cast(result), instances); |
| 1359 return *result; | 1359 return *result; |
| 1360 } | 1360 } |
| 1361 | 1361 |
| 1362 | 1362 |
| 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 | |
| 1433 // Scan the heap for objects with direct references to an object | 1363 // Scan the heap for objects with direct references to an object |
| 1434 // args[0]: the object to find references to | 1364 // args[0]: the object to find references to |
| 1435 // args[1]: constructor function for instances to exclude (Mirror) | 1365 // args[1]: constructor function for instances to exclude (Mirror) |
| 1436 // args[2]: the the maximum number of objects to return | 1366 // args[2]: the the maximum number of objects to return |
| 1437 RUNTIME_FUNCTION(Runtime_DebugReferencedBy) { | 1367 RUNTIME_FUNCTION(Runtime_DebugReferencedBy) { |
| 1438 HandleScope scope(isolate); | 1368 HandleScope scope(isolate); |
| 1439 DCHECK(args.length() == 3); | 1369 DCHECK(args.length() == 3); |
| 1440 | |
| 1441 // Check parameters. | |
| 1442 CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0); | 1370 CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0); |
| 1443 CONVERT_ARG_HANDLE_CHECKED(Object, instance_filter, 1); | 1371 CONVERT_ARG_HANDLE_CHECKED(Object, filter, 1); |
| 1444 RUNTIME_ASSERT(instance_filter->IsUndefined() || | 1372 RUNTIME_ASSERT(filter->IsUndefined() || filter->IsJSObject()); |
| 1445 instance_filter->IsJSObject()); | |
| 1446 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]); | 1373 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]); |
| 1447 RUNTIME_ASSERT(max_references >= 0); | 1374 RUNTIME_ASSERT(max_references >= 0); |
| 1448 | 1375 |
| 1449 | 1376 List<Handle<JSObject> > instances; |
| 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. | |
| 1458 Heap* heap = isolate->heap(); | 1377 Heap* heap = isolate->heap(); |
| 1459 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy"); | |
| 1460 { | 1378 { |
| 1461 HeapIterator heap_iterator(heap); | 1379 HeapIterator iterator(heap, HeapIterator::kFilterUnreachable); |
| 1462 count = DebugReferencedBy(&heap_iterator, *target, *instance_filter, | 1380 // Get the constructor function for context extension and arguments array. |
| 1463 max_references, NULL, 0, *arguments_function); | 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; |
| 1385 JSObject* obj = JSObject::cast(heap_obj); |
| 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(); |
| 1397 } |
| 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()) { |
| 1403 } |
| 1464 } | 1404 } |
| 1465 | 1405 |
| 1466 // Allocate an array to hold the result. | 1406 Handle<FixedArray> result; |
| 1467 Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count); | 1407 if (instances.length() == 1 && instances.last().is_identical_to(target)) { |
| 1468 | 1408 // Check for circular reference only. This can happen when the object is |
| 1469 // Fill the referencing objects. | 1409 // only referenced from mirrors and has a circular reference in which case |
| 1470 { | 1410 // the object is not really alive and would have been garbage collected if |
| 1471 HeapIterator heap_iterator(heap); | 1411 // not referenced from the mirror. |
| 1472 count = DebugReferencedBy(&heap_iterator, *target, *instance_filter, | 1412 result = isolate->factory()->empty_fixed_array(); |
| 1473 max_references, *instances, count, | 1413 } else { |
| 1474 *arguments_function); | 1414 result = isolate->factory()->NewFixedArray(instances.length()); |
| 1415 for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]); |
| 1475 } | 1416 } |
| 1476 | 1417 return *isolate->factory()->NewJSArrayWithElements(result); |
| 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 } | 1418 } |
| 1484 | 1419 |
| 1485 | 1420 |
| 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()) { | |
| 1499 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++; | |
| 1507 } | |
| 1508 } | |
| 1509 } | |
| 1510 | |
| 1511 // Return the number of referencing objects found. | |
| 1512 return count; | |
| 1513 } | |
| 1514 | |
| 1515 | |
| 1516 // Scan the heap for objects constructed by a specific function. | 1421 // Scan the heap for objects constructed by a specific function. |
| 1517 // args[0]: the constructor to find instances of | 1422 // args[0]: the constructor to find instances of |
| 1518 // args[1]: the the maximum number of objects to return | 1423 // args[1]: the the maximum number of objects to return |
| 1519 RUNTIME_FUNCTION(Runtime_DebugConstructedBy) { | 1424 RUNTIME_FUNCTION(Runtime_DebugConstructedBy) { |
| 1520 HandleScope scope(isolate); | 1425 HandleScope scope(isolate); |
| 1521 DCHECK(args.length() == 2); | 1426 DCHECK(args.length() == 2); |
| 1522 | |
| 1523 | |
| 1524 // Check parameters. | |
| 1525 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0); | 1427 CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0); |
| 1526 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]); | 1428 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]); |
| 1527 RUNTIME_ASSERT(max_references >= 0); | 1429 RUNTIME_ASSERT(max_references >= 0); |
| 1528 | 1430 |
| 1529 // Get the number of referencing objects. | 1431 List<Handle<JSObject> > instances; |
| 1530 int count; | |
| 1531 // First perform a full GC in order to avoid dead objects and to make the heap | |
| 1532 // iterable. | |
| 1533 Heap* heap = isolate->heap(); | 1432 Heap* heap = isolate->heap(); |
| 1534 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy"); | |
| 1535 { | 1433 { |
| 1536 HeapIterator heap_iterator(heap); | 1434 HeapIterator iterator(heap, HeapIterator::kFilterUnreachable); |
| 1537 count = DebugConstructedBy(&heap_iterator, *constructor, max_references, | 1435 HeapObject* heap_obj; |
| 1538 NULL, 0); | 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 } |
| 1539 } | 1446 } |
| 1540 | 1447 |
| 1541 // Allocate an array to hold the result. | 1448 Handle<FixedArray> result = |
| 1542 Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count); | 1449 isolate->factory()->NewFixedArray(instances.length()); |
| 1543 | 1450 for (int i = 0; i < instances.length(); ++i) result->set(i, *instances[i]); |
| 1544 // Fill the referencing objects. | 1451 return *isolate->factory()->NewJSArrayWithElements(result); |
| 1545 { | |
| 1546 HeapIterator heap_iterator2(heap); | |
| 1547 count = DebugConstructedBy(&heap_iterator2, *constructor, max_references, | |
| 1548 *instances, count); | |
| 1549 } | |
| 1550 | |
| 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; | |
| 1556 } | 1452 } |
| 1557 | 1453 |
| 1558 | 1454 |
| 1559 // Find the effective prototype object as returned by __proto__. | 1455 // Find the effective prototype object as returned by __proto__. |
| 1560 // args[0]: the object to find the prototype for. | 1456 // args[0]: the object to find the prototype for. |
| 1561 RUNTIME_FUNCTION(Runtime_DebugGetPrototype) { | 1457 RUNTIME_FUNCTION(Runtime_DebugGetPrototype) { |
| 1562 HandleScope shs(isolate); | 1458 HandleScope shs(isolate); |
| 1563 DCHECK(args.length() == 1); | 1459 DCHECK(args.length() == 1); |
| 1564 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); | 1460 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); |
| 1565 return *Object::GetPrototypeSkipHiddenPrototypes(isolate, obj); | 1461 return *Object::GetPrototypeSkipHiddenPrototypes(isolate, obj); |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1827 return *isolate->factory()->undefined_value(); | 1723 return *isolate->factory()->undefined_value(); |
| 1828 } | 1724 } |
| 1829 | 1725 |
| 1830 | 1726 |
| 1831 RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) { | 1727 RUNTIME_FUNCTION(Runtime_DebugBreakInOptimizedCode) { |
| 1832 UNIMPLEMENTED(); | 1728 UNIMPLEMENTED(); |
| 1833 return NULL; | 1729 return NULL; |
| 1834 } | 1730 } |
| 1835 } // namespace internal | 1731 } // namespace internal |
| 1836 } // namespace v8 | 1732 } // namespace v8 |
| OLD | NEW |