8270179: Rename Amalloc_4

8270217: Fix Arena::Amalloc to check for overflow better

Reviewed-by: kbarrett, stuefe
This commit is contained in:
Coleen Phillimore 2021-07-13 13:06:20 +00:00
parent 375fc2a2b2
commit 460c4bb6ce
17 changed files with 57 additions and 96 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 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
@ -118,8 +118,7 @@ public:
}
}
// Further assume size is padded out to words
// Warning: in LP64, Amalloc_4 is really Amalloc_8
void *Amalloc_4(size_t x) {
void *AmallocWords(size_t x) {
assert( (x&(sizeof(char*)-1)) == 0, "misaligned size" );
if (_hwm + x > _max) {
return grow(x);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 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
@ -74,7 +74,7 @@ void Dict::init() {
_size = 16; // Size is a power of 2
_cnt = 0; // Dictionary is empty
_bin = (bucket*)_arena->Amalloc_4(sizeof(bucket) * _size);
_bin = (bucket*)_arena->AmallocWords(sizeof(bucket) * _size);
memset(_bin, 0, sizeof(bucket) * _size);
}
@ -115,7 +115,7 @@ void Dict::doubhash(void) {
if( !j ) j = 1; // Handle zero-sized buckets
nb->_max = j<<1;
// Allocate worst case space for key-value pairs
nb->_keyvals = (const void**)_arena->Amalloc_4( sizeof(void *)*nb->_max*2 );
nb->_keyvals = (const void**)_arena->AmallocWords( sizeof(void *)*nb->_max*2 );
int nbcnt = 0;
for( j=0; j<b->_cnt; j++ ) { // Rehash all keys in this bucket
@ -138,11 +138,11 @@ void Dict::doubhash(void) {
//------------------------------Dict-----------------------------------------
// Deep copy a dictionary.
Dict::Dict( const Dict &d ) : _size(d._size), _cnt(d._cnt), _hash(d._hash),_cmp(d._cmp), _arena(d._arena) {
_bin = (bucket*)_arena->Amalloc_4(sizeof(bucket)*_size);
_bin = (bucket*)_arena->AmallocWords(sizeof(bucket)*_size);
memcpy( _bin, d._bin, sizeof(bucket)*_size );
for( int i=0; i<_size; i++ ) {
if( !_bin[i]._keyvals ) continue;
_bin[i]._keyvals=(const void**)_arena->Amalloc_4( sizeof(void *)*_bin[i]._max*2);
_bin[i]._keyvals=(const void**)_arena->AmallocWords( sizeof(void *)*_bin[i]._max*2);
memcpy( _bin[i]._keyvals, d._bin[i]._keyvals,_bin[i]._cnt*2*sizeof(void*));
}
}
@ -195,7 +195,7 @@ const void *Dict::Insert(const void *key, const void *val) {
if( b->_cnt == b->_max ) { // Must grow bucket?
if( !b->_keyvals ) {
b->_max = 2; // Initial bucket size
b->_keyvals = (const void**)_arena->Amalloc_4( sizeof(void *)*b->_max*2 );
b->_keyvals = (const void**)_arena->AmallocWords( sizeof(void *)*b->_max*2 );
} else {
b->_keyvals = (const void**)_arena->Arealloc( b->_keyvals, sizeof(void *)*b->_max*2, sizeof(void *)*b->_max*4 );
b->_max <<= 1; // Double bucket

View File

@ -72,7 +72,7 @@ public:
RegMask* live = (RegMask*)_live[node->_idx];
if (live == NULL) {
live = new (Compile::current()->comp_arena()->Amalloc_4(sizeof(RegMask))) RegMask();
live = new (Compile::current()->comp_arena()->AmallocWords(sizeof(RegMask))) RegMask();
_live.map(node->_idx, (Node*)live);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
@ -64,7 +64,7 @@ Dict::Dict(CmpKey initcmp, Hash inithash) : _arena(Thread::current()->resource_a
_size = 16; // Size is a power of 2
_cnt = 0; // Dictionary is empty
_bin = (bucket*)_arena->Amalloc_4(sizeof(bucket) * _size);
_bin = (bucket*)_arena->AmallocWords(sizeof(bucket) * _size);
memset((void*)_bin, 0, sizeof(bucket) * _size);
}
@ -74,20 +74,20 @@ Dict::Dict(CmpKey initcmp, Hash inithash, Arena* arena, int size)
_size = MAX2(16, round_up_power_of_2(size));
_cnt = 0; // Dictionary is empty
_bin = (bucket*)_arena->Amalloc_4(sizeof(bucket) * _size);
_bin = (bucket*)_arena->AmallocWords(sizeof(bucket) * _size);
memset((void*)_bin, 0, sizeof(bucket) * _size);
}
// Deep copy into arena of choice
Dict::Dict(const Dict &d, Arena* arena)
: _arena(arena), _size(d._size), _cnt(d._cnt), _hash(d._hash), _cmp(d._cmp) {
_bin = (bucket*)_arena->Amalloc_4(sizeof(bucket) * _size);
_bin = (bucket*)_arena->AmallocWords(sizeof(bucket) * _size);
memcpy((void*)_bin, (void*)d._bin, sizeof(bucket) * _size);
for (uint i = 0; i < _size; i++) {
if (!_bin[i]._keyvals) {
continue;
}
_bin[i]._keyvals = (void**)_arena->Amalloc_4(sizeof(void*) * _bin[i]._max * 2);
_bin[i]._keyvals = (void**)_arena->AmallocWords(sizeof(void*) * _bin[i]._max * 2);
memcpy(_bin[i]._keyvals, d._bin[i]._keyvals, _bin[i]._cnt * 2 * sizeof(void*));
}
}
@ -118,7 +118,7 @@ void Dict::doubhash() {
if (!j) { j = 1; } // Handle zero-sized buckets
nb->_max = j << 1;
// Allocate worst case space for key-value pairs
nb->_keyvals = (void**)_arena->Amalloc_4(sizeof(void* ) * nb->_max * 2);
nb->_keyvals = (void**)_arena->AmallocWords(sizeof(void* ) * nb->_max * 2);
uint nbcnt = 0;
for (j = 0; j < b->_cnt;) { // Rehash all keys in this bucket
@ -168,7 +168,7 @@ void*Dict::Insert(void* key, void* val, bool replace) {
if (b->_cnt == b->_max) { // Must grow bucket?
if (!b->_keyvals) {
b->_max = 2; // Initial bucket size
b->_keyvals = (void**)_arena->Amalloc_4(sizeof(void*) * b->_max * 2);
b->_keyvals = (void**)_arena->AmallocWords(sizeof(void*) * b->_max * 2);
} else {
b->_keyvals = (void**)_arena->Arealloc(b->_keyvals, sizeof(void*) * b->_max * 2, sizeof(void*) * b->_max * 4);
b->_max <<= 1; // Double bucket

View File

@ -337,10 +337,6 @@ size_t Arena::used() const {
return sum; // Return total consumed space.
}
void Arena::signal_out_of_memory(size_t sz, const char* whence) const {
vm_exit_out_of_memory(sz, OOM_MALLOC_ERROR, "%s", whence);
}
// Grow a new Chunk
void* Arena::grow(size_t x, AllocFailType alloc_failmode) {
// Get minimal required size. Either real big, or even bigger for giant objs
@ -453,22 +449,9 @@ bool Arena::contains( const void *ptr ) const {
void* Arena::malloc(size_t size) {
assert(UseMallocOnly, "shouldn't call");
// use malloc, but save pointer in res. area for later freeing
char** save = (char**)internal_malloc_4(sizeof(char*));
char** save = (char**)internal_amalloc(sizeof(char*));
return (*save = (char*)os::malloc(size, mtChunk));
}
// for debugging with UseMallocOnly
void* Arena::internal_malloc_4(size_t x) {
assert( (x&(sizeof(char*)-1)) == 0, "misaligned size" );
check_for_overflow(x, "Arena::internal_malloc_4");
if (_hwm + x > _max) {
return grow(x);
} else {
char *old = _hwm;
_hwm += x;
return old;
}
}
#endif

View File

@ -101,20 +101,17 @@ protected:
size_t _size_in_bytes; // Size of arena (used for native memory tracking)
debug_only(void* malloc(size_t size);)
debug_only(void* internal_malloc_4(size_t x);)
void signal_out_of_memory(size_t request, const char* whence) const;
bool check_for_overflow(size_t request, const char* whence,
AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) const {
if (UINTPTR_MAX - request < (uintptr_t)_hwm) {
if (alloc_failmode == AllocFailStrategy::RETURN_NULL) {
return false;
}
signal_out_of_memory(request, whence);
void* internal_amalloc(size_t x, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
assert(is_aligned(x, BytesPerWord), "misaligned size");
if (pointer_delta(_max, _hwm, 1) >= x) {
char *old = _hwm;
_hwm += x;
return old;
} else {
return grow(x, alloc_failmode);
}
return true;
}
}
public:
Arena(MEMFLAGS memflag);
@ -135,33 +132,17 @@ protected:
// 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) {
x = ARENA_ALIGN(x);
x = ARENA_ALIGN(x); // note for 32 bits this should align _hwm as well.
debug_only(if (UseMallocOnly) return malloc(x);)
if (!check_for_overflow(x, "Arena::Amalloc", alloc_failmode)) {
return NULL;
} else if (_hwm + x > _max) {
return grow(x, alloc_failmode);
} else {
char *old = _hwm;
_hwm += x;
return old;
}
return internal_amalloc(x, alloc_failmode);
}
// 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) {
void* AmallocWords(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_4", alloc_failmode)) {
return NULL;
} else if (_hwm + x > _max) {
return grow(x, alloc_failmode);
} else {
char *old = _hwm;
_hwm += x;
return old;
}
return internal_amalloc(x, alloc_failmode);
}
// Fast delete in area. Common case is: NOP (except for storage reclaimed)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
@ -34,7 +34,7 @@ inline char* ResourceArea::allocate_bytes(size_t size, AllocFailType alloc_failm
verify_has_resource_mark();
if (UseMallocOnly) {
// use malloc, but save pointer in res. area for later freeing
char** save = (char**)internal_malloc_4(sizeof(char*));
char** save = (char**)internal_amalloc(sizeof(char*));
return (*save = (char*)os::malloc(size, mtThread, CURRENT_PC));
}
#endif // ASSERT

View File

@ -89,7 +89,7 @@ void* Symbol::operator new(size_t sz, int len) throw() {
void* Symbol::operator new(size_t sz, int len, Arena* arena) throw() {
int alloc_size = size(len)*wordSize;
address res = (address)arena->Amalloc_4(alloc_size);
address res = (address)arena->AmallocWords(alloc_size);
return res;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 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
@ -58,7 +58,7 @@ void IndexSet::populate_free_list() {
Compile *compile = Compile::current();
BitBlock *free = (BitBlock*)compile->indexSet_free_block_list();
char *mem = (char*)arena()->Amalloc_4(sizeof(BitBlock) *
char *mem = (char*)arena()->AmallocWords(sizeof(BitBlock) *
bitblock_alloc_chunk_size + 32);
// Align the pointer to a 32 bit boundary.
@ -233,7 +233,7 @@ IndexSet::IndexSet (IndexSet *set) {
_blocks = _preallocated_block_list;
} else {
_blocks =
(IndexSet::BitBlock**) arena()->Amalloc_4(sizeof(IndexSet::BitBlock**) * _max_blocks);
(IndexSet::BitBlock**) arena()->AmallocWords(sizeof(IndexSet::BitBlock**) * _max_blocks);
}
for (uint i = 0; i < _max_blocks; i++) {
BitBlock *block = set->_blocks[i];
@ -263,7 +263,7 @@ void IndexSet::initialize(uint max_elements) {
if (_max_blocks <= preallocated_block_list_size) {
_blocks = _preallocated_block_list;
} else {
_blocks = (IndexSet::BitBlock**) arena()->Amalloc_4(sizeof(IndexSet::BitBlock*) * _max_blocks);
_blocks = (IndexSet::BitBlock**) arena()->AmallocWords(sizeof(IndexSet::BitBlock*) * _max_blocks);
}
for (uint i = 0; i < _max_blocks; i++) {
set_block(i, &_empty_block);
@ -288,7 +288,7 @@ void IndexSet::initialize(uint max_elements, Arena *arena) {
if (_max_blocks <= preallocated_block_list_size) {
_blocks = _preallocated_block_list;
} else {
_blocks = (IndexSet::BitBlock**) arena->Amalloc_4(sizeof(IndexSet::BitBlock*) * _max_blocks);
_blocks = (IndexSet::BitBlock**) arena->AmallocWords(sizeof(IndexSet::BitBlock*) * _max_blocks);
}
for (uint i = 0; i < _max_blocks; i++) {
set_block(i, &_empty_block);

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_4(x);
return C->node_arena()->AmallocWords(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_4(sizeof(RegMask) * NOF_STACK_MASKS);
RegMask *rms = (RegMask*)C->comp_arena()->AmallocWords(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_4(req * sizeof(void*))));
_in = (Node **) ((char *) (C->node_arena()->AmallocWords(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_4(size_of() + _max*sizeof(Node*));
Node *n = (Node*)C->node_arena()->AmallocWords(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

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

View File

@ -498,27 +498,27 @@ void Type::Initialize_shared(Compile* current) {
TypeLong::UINT = TypeLong::make(0,(jlong)max_juint,WidenMin);
TypeLong::TYPE_DOMAIN = TypeLong::LONG;
const Type **fboth =(const Type**)shared_type_arena->Amalloc_4(2*sizeof(Type*));
const Type **fboth =(const Type**)shared_type_arena->AmallocWords(2*sizeof(Type*));
fboth[0] = Type::CONTROL;
fboth[1] = Type::CONTROL;
TypeTuple::IFBOTH = TypeTuple::make( 2, fboth );
const Type **ffalse =(const Type**)shared_type_arena->Amalloc_4(2*sizeof(Type*));
const Type **ffalse =(const Type**)shared_type_arena->AmallocWords(2*sizeof(Type*));
ffalse[0] = Type::CONTROL;
ffalse[1] = Type::TOP;
TypeTuple::IFFALSE = TypeTuple::make( 2, ffalse );
const Type **fneither =(const Type**)shared_type_arena->Amalloc_4(2*sizeof(Type*));
const Type **fneither =(const Type**)shared_type_arena->AmallocWords(2*sizeof(Type*));
fneither[0] = Type::TOP;
fneither[1] = Type::TOP;
TypeTuple::IFNEITHER = TypeTuple::make( 2, fneither );
const Type **ftrue =(const Type**)shared_type_arena->Amalloc_4(2*sizeof(Type*));
const Type **ftrue =(const Type**)shared_type_arena->AmallocWords(2*sizeof(Type*));
ftrue[0] = Type::TOP;
ftrue[1] = Type::CONTROL;
TypeTuple::IFTRUE = TypeTuple::make( 2, ftrue );
const Type **floop =(const Type**)shared_type_arena->Amalloc_4(2*sizeof(Type*));
const Type **floop =(const Type**)shared_type_arena->AmallocWords(2*sizeof(Type*));
floop[0] = Type::CONTROL;
floop[1] = TypeInt::INT;
TypeTuple::LOOPBODY = TypeTuple::make( 2, floop );
@ -533,7 +533,7 @@ void Type::Initialize_shared(Compile* current) {
const Type **fmembar = TypeTuple::fields(0);
TypeTuple::MEMBAR = TypeTuple::make(TypeFunc::Parms+0, fmembar);
const Type **fsc = (const Type**)shared_type_arena->Amalloc_4(2*sizeof(Type*));
const Type **fsc = (const Type**)shared_type_arena->AmallocWords(2*sizeof(Type*));
fsc[0] = TypeInt::CC;
fsc[1] = Type::MEMORY;
TypeTuple::STORECONDITIONAL = TypeTuple::make(2, fsc);
@ -2056,7 +2056,7 @@ const TypeTuple *TypeTuple::make( uint cnt, const Type **fields ) {
// Subroutine call type with space allocated for argument types
// Memory for Control, I_O, Memory, FramePtr, and ReturnAdr is allocated implicitly
const Type **TypeTuple::fields( uint arg_cnt ) {
const Type **flds = (const Type **)(Compile::current()->type_arena()->Amalloc_4((TypeFunc::Parms+arg_cnt)*sizeof(Type*) ));
const Type **flds = (const Type **)(Compile::current()->type_arena()->AmallocWords((TypeFunc::Parms+arg_cnt)*sizeof(Type*) ));
flds[TypeFunc::Control ] = Type::CONTROL;
flds[TypeFunc::I_O ] = Type::ABIO;
flds[TypeFunc::Memory ] = Type::MEMORY;
@ -2084,7 +2084,7 @@ const Type *TypeTuple::xmeet( const Type *t ) const {
case Tuple: { // Meeting 2 signatures?
const TypeTuple *x = t->is_tuple();
assert( _cnt == x->_cnt, "" );
const Type **fields = (const Type **)(Compile::current()->type_arena()->Amalloc_4( _cnt*sizeof(Type*) ));
const Type **fields = (const Type **)(Compile::current()->type_arena()->AmallocWords( _cnt*sizeof(Type*) ));
for( uint i=0; i<_cnt; i++ )
fields[i] = field_at(i)->xmeet( x->field_at(i) );
return TypeTuple::make(_cnt,fields);
@ -2098,7 +2098,7 @@ const Type *TypeTuple::xmeet( const Type *t ) const {
//------------------------------xdual------------------------------------------
// Dual: compute field-by-field dual
const Type *TypeTuple::xdual() const {
const Type **fields = (const Type **)(Compile::current()->type_arena()->Amalloc_4( _cnt*sizeof(Type*) ));
const Type **fields = (const Type **)(Compile::current()->type_arena()->AmallocWords( _cnt*sizeof(Type*) ));
for( uint i=0; i<_cnt; i++ )
fields[i] = _fields[i]->dual();
return new TypeTuple(_cnt,fields);

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_4(x);
return compile->type_arena()->AmallocWords(x);
}
inline void operator delete( void* ptr ) {
Compile* compile = Compile::current();

View File

@ -453,7 +453,8 @@ const intx ObjectAlignmentInBytes = 8;
"Verify code cache on memory allocation/deallocation") \
\
develop(bool, UseMallocOnly, false, \
"Use only malloc/free for allocation (no resource area/arena)") \
"Use only malloc/free for allocation (no resource area/arena). " \
"Used to help diagnose memory stomping bugs.") \
\
develop(bool, ZapResourceArea, trueInDebug, \
"Zap freed resource/arena space with 0xABABABAB") \

View File

@ -192,11 +192,8 @@ class HandleArea: public Arena {
// Handle allocation
private:
oop* real_allocate_handle(oop obj) {
#ifdef ASSERT
oop* handle = (oop*) (UseMallocOnly ? internal_malloc_4(oopSize) : Amalloc_4(oopSize));
#else
oop* handle = (oop*) Amalloc_4(oopSize);
#endif
// Ignore UseMallocOnly by allocating only in arena.
oop* handle = (oop*)internal_amalloc(oopSize);
*handle = obj;
return handle;
}