Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files
8247755: Leaner and more versatile GrowableArray classes
Reviewed-by: kbarrett, coleenp
  • Loading branch information
stefank committed Jun 24, 2020
1 parent 9d6aa42 commit ef3b0ec567c47c73f9c4dff1d39de2657bb7af72
Show file tree
Hide file tree
Showing 13 changed files with 1,117 additions and 346 deletions.
@@ -347,6 +347,12 @@ class SymbolClosure : public StackObj {
}
};

template <typename E>
class CompareClosure : public Closure {
public:
virtual int do_compare(const E&, const E&) = 0;
};

// Dispatches to the non-virtual functions if OopClosureType has
// a concrete implementation, otherwise a virtual call is taken.
class Devirtualizer {
@@ -456,10 +456,10 @@ void MetaspaceShared::post_initialize(TRAPS) {
}
}

static GrowableArray<Handle>* _extra_interned_strings = NULL;
static GrowableArrayCHeap<Handle, mtClassShared>* _extra_interned_strings = NULL;

void MetaspaceShared::read_extra_data(const char* filename, TRAPS) {
_extra_interned_strings = new (ResourceObj::C_HEAP, mtClassShared) GrowableArray<Handle>(10000, mtClassShared);
_extra_interned_strings = new GrowableArrayCHeap<Handle, mtClassShared>(10000);

HashtableTextDump reader(filename);
reader.check_version("VERSION: 1.0");
@@ -3307,7 +3307,7 @@ class ScopedVMInitArgs : public StackObj {
// allocated memory is deleted by the destructor. If this method
// returns anything other than JNI_OK, then this object is in a
// partially constructed state, and should be abandoned.
jint set_args(GrowableArray<JavaVMOption>* options) {
jint set_args(const GrowableArrayView<JavaVMOption>* options) {
_is_set = true;
JavaVMOption* options_arr = NEW_C_HEAP_ARRAY_RETURN_NULL(
JavaVMOption, options->length(), mtArguments);
@@ -3365,23 +3365,21 @@ class ScopedVMInitArgs : public StackObj {
assert(vm_options_file_pos != -1, "vm_options_file_pos should be set");

int length = args->nOptions + args_to_insert->nOptions - 1;
GrowableArray<JavaVMOption> *options = new (ResourceObj::C_HEAP, mtArguments)
GrowableArray<JavaVMOption>(length, mtArguments); // Construct new option array
// Construct new option array
GrowableArrayCHeap<JavaVMOption, mtArguments> options(length);
for (int i = 0; i < args->nOptions; i++) {
if (i == vm_options_file_pos) {
// insert the new options starting at the same place as the
// -XX:VMOptionsFile option
for (int j = 0; j < args_to_insert->nOptions; j++) {
options->push(args_to_insert->options[j]);
options.push(args_to_insert->options[j]);
}
} else {
options->push(args->options[i]);
options.push(args->options[i]);
}
}
// make into options array
jint result = set_args(options);
delete options;
return result;
return set_args(&options);
}
};

@@ -3478,7 +3476,8 @@ jint Arguments::parse_vm_options_file(const char* file_name, ScopedVMInitArgs* v
}

jint Arguments::parse_options_buffer(const char* name, char* buffer, const size_t buf_len, ScopedVMInitArgs* vm_args) {
GrowableArray<JavaVMOption> *options = new (ResourceObj::C_HEAP, mtArguments) GrowableArray<JavaVMOption>(2, mtArguments); // Construct option array
// Construct option array
GrowableArrayCHeap<JavaVMOption, mtArguments> options(2);

// some pointers to help with parsing
char *buffer_end = buffer + buf_len;
@@ -3518,7 +3517,6 @@ jint Arguments::parse_options_buffer(const char* name, char* buffer, const size_
// did not see closing quote
jio_fprintf(defaultStream::error_stream(),
"Unmatched quote in %s\n", name);
delete options;
return JNI_ERR;
}
} else {
@@ -3534,16 +3532,13 @@ jint Arguments::parse_options_buffer(const char* name, char* buffer, const size_
option.optionString = opt_hd;
option.extraInfo = NULL;

options->append(option); // Fill in option
options.append(option); // Fill in option

rd++; // Advance to next character
}

// Fill out JavaVMInitArgs structure.
jint status = vm_args->set_args(options);

delete options;
return status;
return vm_args->set_args(&options);
}

jint Arguments::set_shared_spaces_flags_and_archive_paths() {
@@ -532,9 +532,8 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
/* GrowableArrays */ \
/*******************/ \
\
nonstatic_field(GenericGrowableArray, _len, int) \
nonstatic_field(GenericGrowableArray, _max, int) \
nonstatic_field(GenericGrowableArray, _arena, Arena*) \
nonstatic_field(GrowableArrayBase, _len, int) \
nonstatic_field(GrowableArrayBase, _max, int) \
nonstatic_field(GrowableArray<int>, _data, int*) \
\
/********************************/ \
@@ -1339,7 +1338,7 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
declare_toplevel_type(SystemDictionary) \
declare_toplevel_type(vmSymbols) \
\
declare_toplevel_type(GenericGrowableArray) \
declare_toplevel_type(GrowableArrayBase) \
declare_toplevel_type(GrowableArray<int>) \
declare_toplevel_type(Arena) \
declare_type(ResourceArea, Arena) \
@@ -432,6 +432,11 @@ inline size_t pointer_delta(const MetaWord* left, const MetaWord* right) {
#define CAST_TO_FN_PTR(func_type, value) (reinterpret_cast<func_type>(value))
#define CAST_FROM_FN_PTR(new_type, func_ptr) ((new_type)((address_word)(func_ptr)))

// Need the correct linkage to call qsort without warnings
extern "C" {
typedef int (*_sort_Fn)(const void *, const void *);
}

// Unsigned byte types for os and stream.hpp

// Unsigned one, two, four and eigth byte quantities used for describing
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020, 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
@@ -28,36 +28,65 @@
#include "runtime/thread.inline.hpp"
#include "utilities/growableArray.hpp"

void* GrowableArrayResourceAllocator::allocate(int max, int elementSize) {
assert(max >= 0, "integer overflow");
size_t byte_size = elementSize * (size_t) max;

return (void*)resource_allocate_bytes(byte_size);
}

void* GrowableArrayArenaAllocator::allocate(int max, int element_size, Arena* arena) {
assert(max >= 0, "integer overflow");
size_t byte_size = element_size * (size_t) max;

return arena->Amalloc(byte_size);
}

void* GrowableArrayCHeapAllocator::allocate(int max, int element_size, MEMFLAGS memflags) {
assert(max >= 0, "integer overflow");
size_t byte_size = element_size * (size_t) max;

// memory type has to be specified for C heap allocation
assert(memflags != mtNone, "memory type not specified for C heap object");
return (void*)AllocateHeap(byte_size, memflags);
}

void GrowableArrayCHeapAllocator::deallocate(void* elements) {
FreeHeap(elements);
}

#ifdef ASSERT
void GenericGrowableArray::set_nesting() {
if (on_stack()) {
_nesting = Thread::current()->resource_area()->nesting();
}

GrowableArrayNestingCheck::GrowableArrayNestingCheck(bool on_stack) :
_nesting(on_stack ? Thread::current()->resource_area()->nesting() : 0) {
}

void GenericGrowableArray::check_nesting() {
void GrowableArrayNestingCheck::on_stack_alloc() const {
// Check for insidious allocation bug: if a GrowableArray overflows, the
// grown array must be allocated under the same ResourceMark as the original.
// Otherwise, the _data array will be deallocated too early.
if (on_stack() &&
_nesting != Thread::current()->resource_area()->nesting()) {
if (_nesting != Thread::current()->resource_area()->nesting()) {
fatal("allocation bug: GrowableArray could grow within nested ResourceMark");
}
}
#endif

void* GenericGrowableArray::raw_allocate(int elementSize) {
assert(_max >= 0, "integer overflow");
size_t byte_size = elementSize * (size_t) _max;
if (on_stack()) {
return (void*)resource_allocate_bytes(byte_size);
} else if (on_C_heap()) {
return (void*)AllocateHeap(byte_size, _memflags);
} else {
return _arena->Amalloc(byte_size);

void GrowableArrayMetadata::init_checks(const GrowableArrayBase* array) const {
// Stack allocated arrays support all three element allocation locations
if (array->allocated_on_stack()) {
return;
}

// Otherwise there's a strict one-to-one mapping
assert(on_C_heap() == array->allocated_on_C_heap(),
"growable array must be C heap allocated if elements are");
assert(on_stack() == array->allocated_on_res_area(),
"growable array must be resource allocated if elements are");
assert(on_arena() == array->allocated_on_arena(),
"growable array must be arena allocated if elements are");
}

void GenericGrowableArray::free_C_heap(void* elements) {
FreeHeap(elements);
void GrowableArrayMetadata::on_stack_alloc_check() const {
_nesting_check.on_stack_alloc();
}

#endif // ASSERT

0 comments on commit ef3b0ec

Please sign in to comment.