Skip to content
Permalink
Browse files
8270179: Rename Amalloc_4
8270217: Fix Arena::Amalloc to check for overflow better

Reviewed-by: kbarrett, stuefe
  • Loading branch information
coleenp committed Jul 13, 2021
1 parent 375fc2a commit 460c4bb6ceeea20d21f41c9d62280c0b2bd747e7
Showing 17 changed files with 57 additions and 96 deletions.
@@ -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 @@ class Arena: public CHeapObj {
}
}
// 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);
@@ -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
@@ -72,7 +72,7 @@ class ZBarrierSetC2State : public ResourceObj {

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);
}

@@ -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
@@ -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


@@ -101,20 +101,17 @@ class Arena : public CHeapObj<mtNone> {
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 @@ class Arena : public CHeapObj<mtNone> {
// 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)
@@ -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
@@ -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;
}

@@ -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);
@@ -64,7 +64,7 @@ class MachOper : public ResourceObj {
// 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
@@ -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++) {
@@ -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);
@@ -238,7 +238,7 @@ class Node {

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;
}

1 comment on commit 460c4bb

@openjdk-notifier
Copy link

@openjdk-notifier openjdk-notifier bot commented on 460c4bb Jul 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.