--- a/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp Sun Oct 15 22:54:03 2017 +0200
+++ b/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp Mon Sep 04 19:50:01 2017 +0200
@@ -3575,20 +3575,6 @@
#undef __
}
-static inline void generate_satb_log_enqueue_if_necessary(bool with_frame) {
- if (with_frame) {
- if (satb_log_enqueue_with_frame == 0) {
- generate_satb_log_enqueue(with_frame);
- assert(satb_log_enqueue_with_frame != 0, "postcondition.");
- }
- } else {
- if (satb_log_enqueue_frameless == 0) {
- generate_satb_log_enqueue(with_frame);
- assert(satb_log_enqueue_frameless != 0, "postcondition.");
- }
- }
-}
-
void MacroAssembler::g1_write_barrier_pre(Register obj,
Register index,
int offset,
@@ -3658,13 +3644,9 @@
"Or we need to think harder.");
if (pre_val->is_global() && !preserve_o_regs) {
- generate_satb_log_enqueue_if_necessary(true); // with frame
-
call(satb_log_enqueue_with_frame);
delayed()->mov(pre_val, O0);
} else {
- generate_satb_log_enqueue_if_necessary(false); // frameless
-
save_frame(0);
call(satb_log_enqueue_frameless);
delayed()->mov(pre_val->after_save(), O0);
@@ -3768,15 +3750,6 @@
}
-static inline void
-generate_dirty_card_log_enqueue_if_necessary(jbyte* byte_map_base) {
- if (dirty_card_log_enqueue == 0) {
- generate_dirty_card_log_enqueue(byte_map_base);
- assert(dirty_card_log_enqueue != 0, "postcondition.");
- }
-}
-
-
void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val, Register tmp) {
Label filtered;
@@ -3806,7 +3779,6 @@
} else {
post_filter_masm->nop();
}
- generate_dirty_card_log_enqueue_if_necessary(bs->byte_map_base);
save_frame(0);
call(dirty_card_log_enqueue);
if (use_scr) {
@@ -3819,6 +3791,28 @@
bind(filtered);
}
+// Called from init_globals() after universe_init() and before interpreter_init()
+void g1_barrier_stubs_init() {
+ CollectedHeap* heap = Universe::heap();
+ if (heap->kind() == CollectedHeap::G1CollectedHeap) {
+ // Only needed for G1
+ if (dirty_card_log_enqueue == 0) {
+ G1SATBCardTableLoggingModRefBS* bs =
+ barrier_set_cast<G1SATBCardTableLoggingModRefBS>(heap->barrier_set());
+ generate_dirty_card_log_enqueue(bs->byte_map_base);
+ assert(dirty_card_log_enqueue != 0, "postcondition.");
+ }
+ if (satb_log_enqueue_with_frame == 0) {
+ generate_satb_log_enqueue(true);
+ assert(satb_log_enqueue_with_frame != 0, "postcondition.");
+ }
+ if (satb_log_enqueue_frameless == 0) {
+ generate_satb_log_enqueue(false);
+ assert(satb_log_enqueue_frameless != 0, "postcondition.");
+ }
+ }
+}
+
#endif // INCLUDE_ALL_GCS
///////////////////////////////////////////////////////////////////////////////////
--- a/src/hotspot/share/code/codeBlob.hpp Sun Oct 15 22:54:03 2017 +0200
+++ b/src/hotspot/share/code/codeBlob.hpp Mon Sep 04 19:50:01 2017 +0200
@@ -156,6 +156,13 @@
int relocation_size() const { return (address) relocation_end() - (address) relocation_begin(); }
int content_size() const { return content_end() - content_begin(); }
int code_size() const { return code_end() - code_begin(); }
+ // Only used from CodeCache::free_unused_tail() after the Interpreter blob was trimmed
+ void adjust_size(size_t used) {
+ _size = (int)used;
+ _data_offset = (int)used;
+ _code_end = (address)this + used;
+ _data_end = (address)this + used;
+ }
// Containment
bool blob_contains(address addr) const { return header_begin() <= addr && addr < data_end(); }
--- a/src/hotspot/share/code/codeCache.cpp Sun Oct 15 22:54:03 2017 +0200
+++ b/src/hotspot/share/code/codeCache.cpp Mon Sep 04 19:50:01 2017 +0200
@@ -569,6 +569,21 @@
assert(heap->blob_count() >= 0, "sanity check");
}
+void CodeCache::free_unused_tail(CodeBlob* cb, size_t used) {
+ assert_locked_or_safepoint(CodeCache_lock);
+ guarantee(cb->is_buffer_blob() && strncmp("Interpreter", cb->name(), 11) == 0, "Only possible for interpreter!");
+ print_trace("free_unused_tail", cb);
+
+ // We also have to account for the extra space (i.e. header) used by the CodeBlob
+ // which provides the memory (see BufferBlob::create() in codeBlob.cpp).
+ used += CodeBlob::align_code_offset(cb->header_size());
+
+ // Get heap for given CodeBlob and deallocate its unused tail
+ get_code_heap(cb)->deallocate_tail(cb, used);
+ // Adjust the sizes of the CodeBlob
+ cb->adjust_size(used);
+}
+
void CodeCache::commit(CodeBlob* cb) {
// this is called by nmethod::nmethod, which must already own CodeCache_lock
assert_locked_or_safepoint(CodeCache_lock);
--- a/src/hotspot/share/code/codeCache.hpp Sun Oct 15 22:54:03 2017 +0200
+++ b/src/hotspot/share/code/codeCache.hpp Mon Sep 04 19:50:01 2017 +0200
@@ -143,6 +143,7 @@
static int alignment_unit(); // guaranteed alignment of all CodeBlobs
static int alignment_offset(); // guaranteed offset of first CodeBlob byte within alignment unit (i.e., allocation header)
static void free(CodeBlob* cb); // frees a CodeBlob
+ static void free_unused_tail(CodeBlob* cb, size_t used); // frees the unused tail of a CodeBlob (only used by TemplateInterpreter::initialize())
static bool contains(void *p); // returns whether p is included
static bool contains(nmethod* nm); // returns whether nm is included
static void blobs_do(void f(CodeBlob* cb)); // iterates over all CodeBlobs
--- a/src/hotspot/share/code/stubs.cpp Sun Oct 15 22:54:03 2017 +0200
+++ b/src/hotspot/share/code/stubs.cpp Mon Sep 04 19:50:01 2017 +0200
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "code/codeBlob.hpp"
+#include "code/codeCache.hpp"
#include "code/stubs.hpp"
#include "memory/allocation.inline.hpp"
#include "oops/oop.inline.hpp"
@@ -89,6 +90,13 @@
Unimplemented();
}
+void StubQueue::deallocate_unused_tail() {
+ CodeBlob* blob = CodeCache::find_blob((void*)_stub_buffer);
+ CodeCache::free_unused_tail(blob, used_space());
+ // Update the limits to the new, trimmed CodeBlob size
+ _buffer_size = blob->content_size();
+ _buffer_limit = blob->content_size();
+}
Stub* StubQueue::stub_containing(address pc) const {
if (contains(pc)) {
--- a/src/hotspot/share/code/stubs.hpp Sun Oct 15 22:54:03 2017 +0200
+++ b/src/hotspot/share/code/stubs.hpp Mon Sep 04 19:50:01 2017 +0200
@@ -201,12 +201,15 @@
void remove_first(int n); // remove the first n stubs in the queue
void remove_all(); // remove all stubs in the queue
+ void deallocate_unused_tail(); // deallocate the unused tail of the underlying CodeBlob
+ // only used from TemplateInterpreter::initialize()
// Iteration
static void queues_do(void f(StubQueue* s)); // call f with each StubQueue
void stubs_do(void f(Stub* s)); // call f with all stubs
Stub* first() const { return number_of_stubs() > 0 ? stub_at(_queue_begin) : NULL; }
Stub* next(Stub* s) const { int i = index_of(s) + stub_size(s);
- if (i == _buffer_limit) i = 0;
+ // Only wrap around in the non-contiguous case (see stubss.cpp)
+ if (i == _buffer_limit && _queue_end < _buffer_limit) i = 0;
return (i == _queue_end) ? NULL : stub_at(i);
}
--- a/src/hotspot/share/interpreter/templateInterpreter.cpp Sun Oct 15 22:54:03 2017 +0200
+++ b/src/hotspot/share/interpreter/templateInterpreter.cpp Mon Sep 04 19:50:01 2017 +0200
@@ -54,6 +54,8 @@
_code = new StubQueue(new InterpreterCodeletInterface, code_size, NULL,
"Interpreter");
TemplateInterpreterGenerator g(_code);
+ // Free the unused memory not occupied by the interpreter and the stubs
+ _code->deallocate_unused_tail();
}
if (PrintInterpreter) {
--- a/src/hotspot/share/memory/heap.cpp Sun Oct 15 22:54:03 2017 +0200
+++ b/src/hotspot/share/memory/heap.cpp Mon Sep 04 19:50:01 2017 +0200
@@ -222,6 +222,20 @@
}
}
+void CodeHeap::deallocate_tail(void* p, size_t used_size) {
+ assert(p == find_start(p), "illegal deallocation");
+ // Find start of HeapBlock
+ HeapBlock* b = (((HeapBlock *)p) - 1);
+ assert(b->allocated_space() == p, "sanity check");
+ size_t used_number_of_segments = size_to_segments(used_size + header_size());
+ size_t actual_number_of_segments = b->length();
+ guarantee(used_number_of_segments <= actual_number_of_segments, "Must be!");
+ guarantee(b == block_at(_next_segment - actual_number_of_segments), "Intermediate allocation!");
+ size_t number_of_segments_to_deallocate = actual_number_of_segments - used_number_of_segments;
+ _next_segment -= number_of_segments_to_deallocate;
+ mark_segmap_as_free(_next_segment, _next_segment + number_of_segments_to_deallocate);
+ b->initialize(used_number_of_segments);
+}
void CodeHeap::deallocate(void* p) {
assert(p == find_start(p), "illegal deallocation");
--- a/src/hotspot/share/memory/heap.hpp Sun Oct 15 22:54:03 2017 +0200
+++ b/src/hotspot/share/memory/heap.hpp Mon Sep 04 19:50:01 2017 +0200
@@ -147,6 +147,12 @@
// Memory allocation
void* allocate (size_t size); // Allocate 'size' bytes in the code cache or return NULL
void deallocate(void* p); // Deallocate memory
+ // Free the tail of segments allocated by the last call to 'allocate()' which exceed 'used_size'.
+ // ATTENTION: this is only safe to use if there was no other call to 'allocate()' after
+ // 'p' was allocated. Only intended for freeing memory which would be otherwise
+ // wasted after the interpreter generation because we don't know the interpreter size
+ // beforehand and we also can't easily relocate the interpreter to a new location.
+ void deallocate_tail(void* p, size_t used_size);
// Attributes
char* low_boundary() const { return _memory.low_boundary(); }
--- a/src/hotspot/share/runtime/init.cpp Sun Oct 15 22:54:03 2017 +0200
+++ b/src/hotspot/share/runtime/init.cpp Mon Sep 04 19:50:01 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -58,6 +58,10 @@
void os_init_globals(); // depends on VM_Version_init, before universe_init
void stubRoutines_init1();
jint universe_init(); // depends on codeCache_init and stubRoutines_init
+#if INCLUDE_ALL_GCS
+// depends on universe_init, must be before interpreter_init (currently only on SPARC)
+void g1_barrier_stubs_init() NOT_SPARC({});
+#endif
void interpreter_init(); // before any methods loaded
void invocationCounter_init(); // before any methods loaded
void marksweep_init();
@@ -112,7 +116,10 @@
if (status != JNI_OK)
return status;
- interpreter_init(); // before any methods loaded
+#if INCLUDE_ALL_GCS
+ g1_barrier_stubs_init(); // depends on universe_init, must be before interpreter_init
+#endif
+ interpreter_init(); // before any methods loaded
invocationCounter_init(); // before any methods loaded
marksweep_init();
accessFlags_init();