1176 void Metaspace::initialize_class_space(ReservedSpace rs) { |
1170 void Metaspace::initialize_class_space(ReservedSpace rs) { |
1177 // The reserved space size may be bigger because of alignment, esp with UseLargePages |
1171 // The reserved space size may be bigger because of alignment, esp with UseLargePages |
1178 assert(rs.size() >= CompressedClassSpaceSize, |
1172 assert(rs.size() >= CompressedClassSpaceSize, |
1179 SIZE_FORMAT " != " SIZE_FORMAT, rs.size(), CompressedClassSpaceSize); |
1173 SIZE_FORMAT " != " SIZE_FORMAT, rs.size(), CompressedClassSpaceSize); |
1180 assert(using_class_space(), "Must be using class space"); |
1174 assert(using_class_space(), "Must be using class space"); |
1181 _class_space_list = new VirtualSpaceList(rs); |
1175 _class_space_list = new VirtualSpaceList("class space list", rs); |
1182 _chunk_manager_class = new ChunkManager(true/*is_class*/); |
1176 _chunk_manager_class = new ChunkManager("class space chunk manager", _class_space_list); |
1183 |
1177 |
1184 if (!_class_space_list->initialization_succeeded()) { |
|
1185 vm_exit_during_initialization("Failed to setup compressed class space virtual space list."); |
|
1186 } |
|
1187 } |
1178 } |
1188 |
1179 |
1189 #endif |
1180 #endif |
1190 |
1181 |
1191 void Metaspace::ergo_initialize() { |
1182 void Metaspace::ergo_initialize() { |
1260 } |
1256 } |
1261 |
1257 |
1262 if (DynamicDumpSharedSpaces && !UseSharedSpaces) { |
1258 if (DynamicDumpSharedSpaces && !UseSharedSpaces) { |
1263 vm_exit_during_initialization("DynamicDumpSharedSpaces is unsupported when base CDS archive is not loaded", NULL); |
1259 vm_exit_during_initialization("DynamicDumpSharedSpaces is unsupported when base CDS archive is not loaded", NULL); |
1264 } |
1260 } |
1265 |
|
1266 if (!DumpSharedSpaces && !UseSharedSpaces) |
|
1267 #endif // INCLUDE_CDS |
1261 #endif // INCLUDE_CDS |
1268 { |
1262 |
|
1263 // Initialize class space: |
|
1264 if (CDS_ONLY(!DumpSharedSpaces && !UseSharedSpaces) NOT_CDS(true)) { |
1269 #ifdef _LP64 |
1265 #ifdef _LP64 |
1270 if (using_class_space()) { |
1266 if (using_class_space()) { |
1271 char* base = (char*)align_up(Universe::heap()->reserved_region().end(), _reserve_alignment); |
1267 char* base = (char*)align_up(Universe::heap()->reserved_region().end(), _reserve_alignment); |
1272 allocate_metaspace_compressed_klass_ptrs(base, 0); |
1268 allocate_metaspace_compressed_klass_ptrs(base, 0); |
1273 } |
1269 } |
1274 #endif // _LP64 |
1270 #endif // _LP64 |
1275 } |
1271 } |
1276 |
1272 |
1277 // Initialize these before initializing the VirtualSpaceList |
1273 // Initialize non-class virtual space list, and its chunk manager: |
1278 _first_chunk_word_size = InitialBootClassLoaderMetaspaceSize / BytesPerWord; |
1274 _space_list = new VirtualSpaceList("Non-Class VirtualSpaceList"); |
1279 _first_chunk_word_size = align_word_size_up(_first_chunk_word_size); |
1275 _chunk_manager_metadata = new ChunkManager("Non-Class ChunkManager", _space_list); |
1280 // Make the first class chunk bigger than a medium chunk so it's not put |
|
1281 // on the medium chunk list. The next chunk will be small and progress |
|
1282 // from there. This size calculated by -version. |
|
1283 _first_class_chunk_word_size = MIN2((size_t)MediumChunk*6, |
|
1284 (CompressedClassSpaceSize/BytesPerWord)*2); |
|
1285 _first_class_chunk_word_size = align_word_size_up(_first_class_chunk_word_size); |
|
1286 // Arbitrarily set the initial virtual space to a multiple |
|
1287 // of the boot class loader size. |
|
1288 size_t word_size = VIRTUALSPACEMULTIPLIER * _first_chunk_word_size; |
|
1289 word_size = align_up(word_size, Metaspace::reserve_alignment_words()); |
|
1290 |
|
1291 // Initialize the list of virtual spaces. |
|
1292 _space_list = new VirtualSpaceList(word_size); |
|
1293 _chunk_manager_metadata = new ChunkManager(false/*metaspace*/); |
|
1294 |
|
1295 if (!_space_list->initialization_succeeded()) { |
|
1296 vm_exit_during_initialization("Unable to setup metadata virtual space list.", NULL); |
|
1297 } |
|
1298 |
1276 |
1299 _tracer = new MetaspaceTracer(); |
1277 _tracer = new MetaspaceTracer(); |
1300 |
1278 |
1301 _initialized = true; |
1279 _initialized = true; |
1302 |
1280 |
1458 } |
1436 } |
1459 |
1437 |
1460 return get_space_list(NonClassType)->contains(ptr); |
1438 return get_space_list(NonClassType)->contains(ptr); |
1461 } |
1439 } |
1462 |
1440 |
1463 // ClassLoaderMetaspace |
|
1464 |
|
1465 ClassLoaderMetaspace::ClassLoaderMetaspace(Mutex* lock, Metaspace::MetaspaceType type) |
|
1466 : _space_type(type) |
|
1467 , _lock(lock) |
|
1468 , _vsm(NULL) |
|
1469 , _class_vsm(NULL) |
|
1470 { |
|
1471 initialize(lock, type); |
|
1472 } |
|
1473 |
|
1474 ClassLoaderMetaspace::~ClassLoaderMetaspace() { |
|
1475 Metaspace::assert_not_frozen(); |
|
1476 DEBUG_ONLY(Atomic::inc(&g_internal_statistics.num_metaspace_deaths)); |
|
1477 delete _vsm; |
|
1478 if (Metaspace::using_class_space()) { |
|
1479 delete _class_vsm; |
|
1480 } |
|
1481 } |
|
1482 |
|
1483 void ClassLoaderMetaspace::initialize_first_chunk(Metaspace::MetaspaceType type, Metaspace::MetadataType mdtype) { |
|
1484 Metachunk* chunk = get_initialization_chunk(type, mdtype); |
|
1485 if (chunk != NULL) { |
|
1486 // Add to this manager's list of chunks in use and make it the current_chunk(). |
|
1487 get_space_manager(mdtype)->add_chunk(chunk, true); |
|
1488 } |
|
1489 } |
|
1490 |
|
1491 Metachunk* ClassLoaderMetaspace::get_initialization_chunk(Metaspace::MetaspaceType type, Metaspace::MetadataType mdtype) { |
|
1492 size_t chunk_word_size = get_space_manager(mdtype)->get_initial_chunk_size(type); |
|
1493 |
|
1494 // Get a chunk from the chunk freelist |
|
1495 Metachunk* chunk = Metaspace::get_chunk_manager(mdtype)->chunk_freelist_allocate(chunk_word_size); |
|
1496 |
|
1497 if (chunk == NULL) { |
|
1498 chunk = Metaspace::get_space_list(mdtype)->get_new_chunk(chunk_word_size, |
|
1499 get_space_manager(mdtype)->medium_chunk_bunch()); |
|
1500 } |
|
1501 |
|
1502 return chunk; |
|
1503 } |
|
1504 |
|
1505 void ClassLoaderMetaspace::initialize(Mutex* lock, Metaspace::MetaspaceType type) { |
|
1506 Metaspace::verify_global_initialization(); |
|
1507 |
|
1508 DEBUG_ONLY(Atomic::inc(&g_internal_statistics.num_metaspace_births)); |
|
1509 |
|
1510 // Allocate SpaceManager for metadata objects. |
|
1511 _vsm = new SpaceManager(Metaspace::NonClassType, type, lock); |
|
1512 |
|
1513 if (Metaspace::using_class_space()) { |
|
1514 // Allocate SpaceManager for classes. |
|
1515 _class_vsm = new SpaceManager(Metaspace::ClassType, type, lock); |
|
1516 } |
|
1517 |
|
1518 MutexLocker cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag); |
|
1519 |
|
1520 // Allocate chunk for metadata objects |
|
1521 initialize_first_chunk(type, Metaspace::NonClassType); |
|
1522 |
|
1523 // Allocate chunk for class metadata objects |
|
1524 if (Metaspace::using_class_space()) { |
|
1525 initialize_first_chunk(type, Metaspace::ClassType); |
|
1526 } |
|
1527 } |
|
1528 |
|
1529 MetaWord* ClassLoaderMetaspace::allocate(size_t word_size, Metaspace::MetadataType mdtype) { |
|
1530 Metaspace::assert_not_frozen(); |
|
1531 |
|
1532 DEBUG_ONLY(Atomic::inc(&g_internal_statistics.num_allocs)); |
|
1533 |
|
1534 // Don't use class_vsm() unless UseCompressedClassPointers is true. |
|
1535 if (Metaspace::is_class_space_allocation(mdtype)) { |
|
1536 return class_vsm()->allocate(word_size); |
|
1537 } else { |
|
1538 return vsm()->allocate(word_size); |
|
1539 } |
|
1540 } |
|
1541 |
|
1542 MetaWord* ClassLoaderMetaspace::expand_and_allocate(size_t word_size, Metaspace::MetadataType mdtype) { |
|
1543 Metaspace::assert_not_frozen(); |
|
1544 size_t delta_bytes = MetaspaceGC::delta_capacity_until_GC(word_size * BytesPerWord); |
|
1545 assert(delta_bytes > 0, "Must be"); |
|
1546 |
|
1547 size_t before = 0; |
|
1548 size_t after = 0; |
|
1549 bool can_retry = true; |
|
1550 MetaWord* res; |
|
1551 bool incremented; |
|
1552 |
|
1553 // Each thread increments the HWM at most once. Even if the thread fails to increment |
|
1554 // the HWM, an allocation is still attempted. This is because another thread must then |
|
1555 // have incremented the HWM and therefore the allocation might still succeed. |
|
1556 do { |
|
1557 incremented = MetaspaceGC::inc_capacity_until_GC(delta_bytes, &after, &before, &can_retry); |
|
1558 res = allocate(word_size, mdtype); |
|
1559 } while (!incremented && res == NULL && can_retry); |
|
1560 |
|
1561 if (incremented) { |
|
1562 Metaspace::tracer()->report_gc_threshold(before, after, |
|
1563 MetaspaceGCThresholdUpdater::ExpandAndAllocate); |
|
1564 log_trace(gc, metaspace)("Increase capacity to GC from " SIZE_FORMAT " to " SIZE_FORMAT, before, after); |
|
1565 } |
|
1566 |
|
1567 return res; |
|
1568 } |
|
1569 |
|
1570 size_t ClassLoaderMetaspace::allocated_blocks_bytes() const { |
|
1571 return (vsm()->used_words() + |
|
1572 (Metaspace::using_class_space() ? class_vsm()->used_words() : 0)) * BytesPerWord; |
|
1573 } |
|
1574 |
|
1575 size_t ClassLoaderMetaspace::allocated_chunks_bytes() const { |
|
1576 return (vsm()->capacity_words() + |
|
1577 (Metaspace::using_class_space() ? class_vsm()->capacity_words() : 0)) * BytesPerWord; |
|
1578 } |
|
1579 |
|
1580 void ClassLoaderMetaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) { |
|
1581 Metaspace::assert_not_frozen(); |
|
1582 assert(!SafepointSynchronize::is_at_safepoint() |
|
1583 || Thread::current()->is_VM_thread(), "should be the VM thread"); |
|
1584 |
|
1585 DEBUG_ONLY(Atomic::inc(&g_internal_statistics.num_external_deallocs)); |
|
1586 |
|
1587 MutexLocker ml(vsm()->lock(), Mutex::_no_safepoint_check_flag); |
|
1588 |
|
1589 if (is_class && Metaspace::using_class_space()) { |
|
1590 class_vsm()->deallocate(ptr, word_size); |
|
1591 } else { |
|
1592 vsm()->deallocate(ptr, word_size); |
|
1593 } |
|
1594 } |
|
1595 |
|
1596 size_t ClassLoaderMetaspace::class_chunk_size(size_t word_size) { |
|
1597 assert(Metaspace::using_class_space(), "Has to use class space"); |
|
1598 return class_vsm()->calc_chunk_size(word_size); |
|
1599 } |
|
1600 |
|
1601 void ClassLoaderMetaspace::print_on(outputStream* out) const { |
|
1602 // Print both class virtual space counts and metaspace. |
|
1603 if (Verbose) { |
|
1604 vsm()->print_on(out); |
|
1605 if (Metaspace::using_class_space()) { |
|
1606 class_vsm()->print_on(out); |
|
1607 } |
|
1608 } |
|
1609 } |
|
1610 |
|
1611 void ClassLoaderMetaspace::verify() { |
|
1612 vsm()->verify(); |
|
1613 if (Metaspace::using_class_space()) { |
|
1614 class_vsm()->verify(); |
|
1615 } |
|
1616 } |
|
1617 |
|
1618 void ClassLoaderMetaspace::add_to_statistics_locked(ClassLoaderMetaspaceStatistics* out) const { |
|
1619 assert_lock_strong(lock()); |
|
1620 vsm()->add_to_statistics_locked(&out->nonclass_sm_stats()); |
|
1621 if (Metaspace::using_class_space()) { |
|
1622 class_vsm()->add_to_statistics_locked(&out->class_sm_stats()); |
|
1623 } |
|
1624 } |
|
1625 |
|
1626 void ClassLoaderMetaspace::add_to_statistics(ClassLoaderMetaspaceStatistics* out) const { |
|
1627 MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag); |
|
1628 add_to_statistics_locked(out); |
|
1629 } |
|
1630 |
|
1631 /////////////// Unit tests /////////////// |
1441 /////////////// Unit tests /////////////// |
1632 |
1442 |
1633 struct chunkmanager_statistics_t { |
1443 struct chunkmanager_statistics_t { |
1634 int num_specialized_chunks; |
1444 int num_specialized_chunks; |
1635 int num_small_chunks; |
1445 int num_small_chunks; |