--- old/src/hotspot/share/gc/g1/g1CollectedHeap.cpp 2018-05-16 17:25:40.308131111 +0200 +++ new/src/hotspot/share/gc/g1/g1CollectedHeap.cpp 2018-05-16 17:25:40.002121700 +0200 @@ -1611,6 +1611,9 @@ const uint max_region_idx = (1U << (sizeof(RegionIdx_t)*BitsPerByte-1)) - 1; guarantee((max_regions() - 1) <= max_region_idx, "too many regions"); + // The G1FromCardCache reserves card with value 0 as "invalid", so the heap must not + // start within the first card. + guarantee(g1_rs.base() >= (char*)G1CardTable::card_size, "Java heap must not start within the first card."); // Also create a G1 rem set. _g1_rem_set = new G1RemSet(this, _card_table, _hot_card_cache); _g1_rem_set->initialize(max_capacity(), max_regions()); --- old/src/hotspot/share/gc/g1/g1FromCardCache.cpp 2018-05-16 17:25:41.578170168 +0200 +++ new/src/hotspot/share/gc/g1/g1FromCardCache.cpp 2018-05-16 17:25:41.273160788 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,9 @@ num_par_rem_sets, &_static_mem_size); - invalidate(0, _max_regions); + if (AlwaysPreTouch) { + invalidate(0, _max_regions); + } } void G1FromCardCache::invalidate(uint start_idx, size_t new_num_regions) { --- old/src/hotspot/share/gc/g1/g1FromCardCache.hpp 2018-05-16 17:25:42.808207996 +0200 +++ new/src/hotspot/share/gc/g1/g1FromCardCache.hpp 2018-05-16 17:25:42.500198523 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ // G1FromCardCache remembers the most recently processed card on the heap on // a per-region and per-thread basis. class G1FromCardCache : public AllStatic { - private: +private: // Array of card indices. Indexed by heap region (rows) and thread (columns) to minimize // thread contention. // This order minimizes the time to clear all entries for a given region during region @@ -49,9 +49,12 @@ } #endif - public: - static const uintptr_t InvalidCard = UINTPTR_MAX; + // This card index indicates "no card for that entry" yet. This allows us to use the OS + // lazy backing of memory with zero-filled pages to avoid initial actual memory use. + // This means that the heap must not contain card zero. + static const uintptr_t InvalidCard = 0; +public: static void clear(uint region_idx); // Returns true if the given card is in the cache at the given location, or --- old/src/hotspot/share/gc/g1/g1RegionMarkStatsCache.cpp 2018-05-16 17:25:44.037245792 +0200 +++ new/src/hotspot/share/gc/g1/g1RegionMarkStatsCache.cpp 2018-05-16 17:25:43.732236412 +0200 @@ -36,9 +36,6 @@ guarantee(is_power_of_2(num_cache_entries), "Number of cache entries must be power of two, but is %u", num_cache_entries); _cache = NEW_C_HEAP_ARRAY(G1RegionMarkStatsCacheEntry, _num_cache_entries, mtGC); - for (uint i = 0; i < _num_cache_entries; i++) { - _cache[i].clear(); - } _num_cache_entries_mask = _num_cache_entries - 1; } --- old/src/hotspot/share/memory/padded.hpp 2018-05-16 17:25:45.256283281 +0200 +++ new/src/hotspot/share/memory/padded.hpp 2018-05-16 17:25:44.948273809 +0200 @@ -104,6 +104,8 @@ public: // Creates an aligned padded 2D array. // The memory cannot be deleted since the raw memory chunk is not returned. + // Always uses mmap to reserve memory. Only the first few pages with the index to + // the rows are touched. Allocation size should be "large" to cover page overhead. static T** create_unfreeable(uint rows, uint columns, size_t* allocation_size = NULL); }; --- old/src/hotspot/share/memory/padded.inline.hpp 2018-05-16 17:25:46.461320340 +0200 +++ new/src/hotspot/share/memory/padded.inline.hpp 2018-05-16 17:25:46.157310991 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,9 +62,8 @@ size_t total_size = table_size + rows * row_size + alignment; // Allocate a chunk of memory large enough to allow alignment of the chunk. - void* chunk = AllocateHeap(total_size, flags); + void* chunk = MmapArrayAllocator::allocate(total_size, flags); // Clear the allocated memory. - memset(chunk, 0, total_size); // Align the chunk of memory. T** result = (T**)align_up(chunk, alignment); void* data_start = (void*)((uintptr_t)result + table_size);