8253779: Amalloc may be wasting space by overaligning

Reviewed-by: kbarrett, stuefe
This commit is contained in:
Coleen Phillimore 2021-07-11 18:15:59 +00:00
parent 68b6e11e48
commit ac75a53fc5
7 changed files with 23 additions and 41 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2021, 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
@ -72,7 +72,7 @@ public:
RegMask* live = (RegMask*)_live[node->_idx];
if (live == NULL) {
live = new (Compile::current()->comp_arena()->Amalloc_D(sizeof(RegMask))) RegMask();
live = new (Compile::current()->comp_arena()->Amalloc_4(sizeof(RegMask))) RegMask();
_live.map(node->_idx, (Node*)live);
}

View File

@ -27,19 +27,15 @@
#include "memory/allocation.hpp"
#include "runtime/globals.hpp"
#include "utilities/align.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/powerOfTwo.hpp"
#include <new>
// The byte alignment to be used by Arena::Amalloc. See bugid 4169348.
// Note: this value must be a power of 2
#define ARENA_AMALLOC_ALIGNMENT (2*BytesPerWord)
#define ARENA_ALIGN_M1 (((size_t)(ARENA_AMALLOC_ALIGNMENT)) - 1)
#define ARENA_ALIGN_MASK (~((size_t)ARENA_ALIGN_M1))
#define ARENA_ALIGN(x) ((((size_t)(x)) + ARENA_ALIGN_M1) & ARENA_ALIGN_MASK)
// The byte alignment to be used by Arena::Amalloc.
#define ARENA_AMALLOC_ALIGNMENT BytesPerLong
#define ARENA_ALIGN(x) (align_up((x), ARENA_AMALLOC_ALIGNMENT))
//------------------------------Chunk------------------------------------------
// Linked list of raw memory chunks
@ -136,28 +132,14 @@ protected:
void* operator new(size_t size, const std::nothrow_t& nothrow_constant, MEMFLAGS flags) throw();
void operator delete(void* p);
// Fast allocate in the arena. Common case is: pointer test + increment.
// Fast allocate in the arena. Common case aligns to the size of jlong which is 64 bits
// on both 32 and 64 bit platforms. Required for atomic jlong operations on 32 bits.
void* Amalloc(size_t x, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
assert(is_power_of_2(ARENA_AMALLOC_ALIGNMENT) , "should be a power of 2");
x = ARENA_ALIGN(x);
debug_only(if (UseMallocOnly) return malloc(x);)
if (!check_for_overflow(x, "Arena::Amalloc", alloc_failmode))
if (!check_for_overflow(x, "Arena::Amalloc", alloc_failmode)) {
return NULL;
if (_hwm + x > _max) {
return grow(x, alloc_failmode);
} else {
char *old = _hwm;
_hwm += x;
return old;
}
}
// Further assume size is padded out to words
void *Amalloc_4(size_t x, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
assert( (x&(sizeof(char*)-1)) == 0, "misaligned size" );
debug_only(if (UseMallocOnly) return malloc(x);)
if (!check_for_overflow(x, "Arena::Amalloc_4", alloc_failmode))
return NULL;
if (_hwm + x > _max) {
} else if (_hwm + x > _max) {
return grow(x, alloc_failmode);
} else {
char *old = _hwm;
@ -166,15 +148,15 @@ protected:
}
}
// Allocate with 'double' alignment. It is 8 bytes on sparc.
// In other cases Amalloc_D() should be the same as Amalloc_4().
void* Amalloc_D(size_t x, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
assert( (x&(sizeof(char*)-1)) == 0, "misaligned size" );
// Allocate in the arena, assuming the size has been aligned to size of pointer, which
// is 4 bytes on 32 bits, hence the name.
void* Amalloc_4(size_t x, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
assert(is_aligned(x, BytesPerWord), "misaligned size");
debug_only(if (UseMallocOnly) return malloc(x);)
if (!check_for_overflow(x, "Arena::Amalloc_D", alloc_failmode))
if (!check_for_overflow(x, "Arena::Amalloc_4", alloc_failmode)) {
return NULL;
if (_hwm + x > _max) {
return grow(x, alloc_failmode); // grow() returns a result aligned >= 8 bytes.
} else if (_hwm + x > _max) {
return grow(x, alloc_failmode);
} else {
char *old = _hwm;
_hwm += x;

View File

@ -64,7 +64,7 @@ public:
// Allocate right next to the MachNodes in the same arena
void *operator new(size_t x) throw() {
Compile* C = Compile::current();
return C->node_arena()->Amalloc_D(x);
return C->node_arena()->Amalloc_4(x);
}
// Opcode

View File

@ -442,7 +442,7 @@ static RegMask *init_input_masks( uint size, RegMask &ret_adr, RegMask &fp ) {
void Matcher::init_first_stack_mask() {
// Allocate storage for spill masks as masks for the appropriate load type.
RegMask *rms = (RegMask*)C->comp_arena()->Amalloc_D(sizeof(RegMask) * NOF_STACK_MASKS);
RegMask *rms = (RegMask*)C->comp_arena()->Amalloc_4(sizeof(RegMask) * NOF_STACK_MASKS);
// Initialize empty placeholder masks into the newly allocated arena
for (int i = 0; i < NOF_STACK_MASKS; i++) {

View File

@ -308,7 +308,7 @@ inline int Node::Init(int req) {
// Allocate memory for the necessary number of edges.
if (req > 0) {
// Allocate space for _in array to have double alignment.
_in = (Node **) ((char *) (C->node_arena()->Amalloc_D(req * sizeof(void*))));
_in = (Node **) ((char *) (C->node_arena()->Amalloc_4(req * sizeof(void*))));
}
// If there are default notes floating around, capture them:
Node_Notes* nn = C->default_node_notes();
@ -499,7 +499,7 @@ Node::Node(Node *n0, Node *n1, Node *n2, Node *n3,
Node *Node::clone() const {
Compile* C = Compile::current();
uint s = size_of(); // Size of inherited Node
Node *n = (Node*)C->node_arena()->Amalloc_D(size_of() + _max*sizeof(Node*));
Node *n = (Node*)C->node_arena()->Amalloc_4(size_of() + _max*sizeof(Node*));
Copy::conjoint_words_to_lower((HeapWord*)this, (HeapWord*)n, s);
// Set the new input pointer array
n->_in = (Node**)(((char*)n)+s);

View File

@ -239,7 +239,7 @@ public:
inline void* operator new(size_t x) throw() {
Compile* C = Compile::current();
Node* n = (Node*)C->node_arena()->Amalloc_D(x);
Node* n = (Node*)C->node_arena()->Amalloc_4(x);
return (void*)n;
}

View File

@ -189,7 +189,7 @@ public:
inline void* operator new( size_t x ) throw() {
Compile* compile = Compile::current();
compile->set_type_last_size(x);
return compile->type_arena()->Amalloc_D(x);
return compile->type_arena()->Amalloc_4(x);
}
inline void operator delete( void* ptr ) {
Compile* compile = Compile::current();