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 |