Skip to content

Commit 4b88119

Browse files
author
Kim Barrett
committed
8253037: G1: Improve check for string dedup
Combine dedup enabled and is_string into a single test, using the already in-hand klass of the object. Reviewed-by: ayang, tschatzl
1 parent 2668d23 commit 4b88119

File tree

5 files changed

+31
-19
lines changed

5 files changed

+31
-19
lines changed

src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
2525
#ifndef SHARE_GC_G1_G1FULLGCMARKER_INLINE_HPP
2626
#define SHARE_GC_G1_G1FULLGCMARKER_INLINE_HPP
2727

28+
#include "classfile/javaClasses.inline.hpp"
2829
#include "gc/g1/g1Allocator.inline.hpp"
2930
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
3031
#include "gc/g1/g1FullGCMarker.hpp"
@@ -57,7 +58,8 @@ inline bool G1FullGCMarker::mark_object(oop obj) {
5758
}
5859

5960
// Check if deduplicatable string.
60-
if (G1StringDedup::is_enabled()) {
61+
if (G1StringDedup::is_enabled() &&
62+
java_lang_String::is_instance_inlined(obj)) {
6163
G1StringDedup::enqueue_from_mark(obj, _worker_id);
6264
}
6365
return true;

src/hotspot/share/gc/g1/g1ParScanThreadState.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
*/
2424

2525
#include "precompiled.hpp"
26+
#include "classfile/systemDictionary.hpp"
2627
#include "gc/g1/g1Allocator.inline.hpp"
2728
#include "gc/g1/g1CollectedHeap.inline.hpp"
2829
#include "gc/g1/g1CollectionSet.hpp"
@@ -75,10 +76,17 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h,
7576
_old_gen_is_full(false),
7677
_partial_objarray_chunk_size(ParGCArrayScanChunk),
7778
_partial_array_stepper(n_workers),
79+
_string_klass_or_null(G1StringDedup::is_enabled()
80+
? SystemDictionary::String_klass()
81+
: nullptr),
7882
_num_optional_regions(optional_cset_length),
7983
_numa(g1h->numa()),
8084
_obj_alloc_stat(NULL)
8185
{
86+
// Verify klass comparison with _string_klass_or_null is sufficient
87+
// to determine whether dedup is enabled and the object is a String.
88+
assert(SystemDictionary::String_klass()->is_final(), "precondition");
89+
8290
// We allocate number of young gen regions in the collection set plus one
8391
// entries, since entry 0 keeps track of surviving bytes for non-young regions.
8492
// We also add a few elements at the beginning and at the end in
@@ -510,7 +518,10 @@ oop G1ParScanThreadState::do_copy_to_survivor_space(G1HeapRegionAttr const regio
510518
return obj;
511519
}
512520

513-
if (G1StringDedup::is_enabled()) {
521+
// StringDedup::is_enabled() and java_lang_String::is_instance_inline
522+
// test of the obj, combined into a single comparison, using the klass
523+
// already in hand and avoiding the null check in is_instance.
524+
if (klass == _string_klass_or_null) {
514525
const bool is_from_young = region_attr.is_young();
515526
const bool is_to_young = dest_attr.is_young();
516527
assert(is_from_young == from_region->is_young(),

src/hotspot/share/gc/g1/g1ParScanThreadState.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class G1OopStarChunkedList;
4242
class G1PLABAllocator;
4343
class G1EvacuationRootClosures;
4444
class HeapRegion;
45+
class Klass;
4546
class outputStream;
4647

4748
class G1ParScanThreadState : public CHeapObj<mtGC> {
@@ -83,6 +84,8 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
8384
// Size (in elements) of a partial objArray task chunk.
8485
int _partial_objarray_chunk_size;
8586
PartialArrayTaskStepper _partial_array_stepper;
87+
// Used to check whether string dedup should be applied to an object.
88+
Klass* _string_klass_or_null;
8689

8790
G1RedirtyCardsQueue& redirty_cards_queue() { return _rdcq; }
8891
G1CardTable* ct() { return _ct; }

src/hotspot/share/gc/g1/g1StringDedup.cpp

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -41,29 +41,23 @@ void G1StringDedup::initialize() {
4141
}
4242

4343
bool G1StringDedup::is_candidate_from_mark(oop obj) {
44-
if (java_lang_String::is_instance_inlined(obj)) {
45-
bool from_young = G1CollectedHeap::heap()->heap_region_containing(obj)->is_young();
46-
if (from_young && obj->age() < StringDeduplicationAgeThreshold) {
47-
// Candidate found. String is being evacuated from young to old but has not
48-
// reached the deduplication age threshold, i.e. has not previously been a
49-
// candidate during its life in the young generation.
50-
return true;
51-
}
52-
}
53-
54-
// Not a candidate
55-
return false;
44+
bool from_young = G1CollectedHeap::heap()->heap_region_containing(obj)->is_young();
45+
// Candidate if string is being evacuated from young to old but has not
46+
// reached the deduplication age threshold, i.e. has not previously been a
47+
// candidate during its life in the young generation.
48+
return from_young && (obj->age() < StringDeduplicationAgeThreshold);
5649
}
5750

5851
void G1StringDedup::enqueue_from_mark(oop java_string, uint worker_id) {
5952
assert(is_enabled(), "String deduplication not enabled");
53+
assert(java_lang_String::is_instance(java_string), "not a String");
6054
if (is_candidate_from_mark(java_string)) {
6155
G1StringDedupQueue::push(worker_id, java_string);
6256
}
6357
}
6458

6559
bool G1StringDedup::is_candidate_from_evacuation(bool from_young, bool to_young, oop obj) {
66-
if (from_young && java_lang_String::is_instance_inlined(obj)) {
60+
if (from_young) {
6761
if (to_young && obj->age() == StringDeduplicationAgeThreshold) {
6862
// Candidate found. String is being evacuated from young to young and just
6963
// reached the deduplication age threshold.
@@ -83,6 +77,7 @@ bool G1StringDedup::is_candidate_from_evacuation(bool from_young, bool to_young,
8377

8478
void G1StringDedup::enqueue_from_evacuation(bool from_young, bool to_young, uint worker_id, oop java_string) {
8579
assert(is_enabled(), "String deduplication not enabled");
80+
assert(java_lang_String::is_instance(java_string), "not a String");
8681
if (is_candidate_from_evacuation(from_young, to_young, java_string)) {
8782
G1StringDedupQueue::push(worker_id, java_string);
8883
}

src/hotspot/share/gc/g1/g1StringDedup.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ class G1StringDedup : public StringDedup {
6565

6666
// Candidate selection policies, returns true if the given object is
6767
// candidate for string deduplication.
68-
static bool is_candidate_from_mark(oop obj);
69-
static bool is_candidate_from_evacuation(bool from_young, bool to_young, oop obj);
68+
static bool is_candidate_from_mark(oop java_string);
69+
static bool is_candidate_from_evacuation(bool from_young, bool to_young, oop java_string);
7070

7171
public:
7272
// Initialize string deduplication.
@@ -75,6 +75,7 @@ class G1StringDedup : public StringDedup {
7575
// Enqueues a deduplication candidate for later processing by the deduplication
7676
// thread. Before enqueuing, these functions apply the appropriate candidate
7777
// selection policy to filters out non-candidates.
78+
// Precondition for both is that java_string is a String.
7879
static void enqueue_from_mark(oop java_string, uint worker_id);
7980
static void enqueue_from_evacuation(bool from_young, bool to_young,
8081
unsigned int queue, oop java_string);

0 commit comments

Comments
 (0)