--- old/src/hotspot/share/utilities/ostream.cpp 2019-03-10 19:12:17.485015968 +0100 +++ new/src/hotspot/share/utilities/ostream.cpp 2019-03-10 19:12:17.269013940 +0100 @@ -938,58 +938,72 @@ } } -bufferedStream::bufferedStream(size_t initial_size, size_t bufmax) : outputStream() { - buffer_length = initial_size; - buffer = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal); - buffer_pos = 0; - buffer_fixed = false; - buffer_max = bufmax; -} - -bufferedStream::bufferedStream(char* fixed_buffer, size_t fixed_buffer_size, size_t bufmax) : outputStream() { - buffer_length = fixed_buffer_size; - buffer = fixed_buffer; - buffer_pos = 0; - buffer_fixed = true; - buffer_max = bufmax; +bufferedStream::bufferedStream(size_t initial_capacity, size_t max_capacity, size_t flush_threshold) + : outputStream(), + _buffer(NULL), + _pos(0), + _capacity(0), + _owned(true), + _max_capacity(max_capacity), + _flush_threshold(flush_threshold) +{ + assert(initial_capacity > 0 && max_capacity >= initial_capacity, "Sanity"); + _capacity = initial_capacity; + _buffer = NEW_C_HEAP_ARRAY(char, _capacity, mtInternal); +} + +bufferedStream::bufferedStream(char* fixed_buffer, size_t fixed_buffer_size, size_t flush_threshold) +: outputStream(), + _buffer(fixed_buffer), + _pos(0), + _capacity(fixed_buffer_size), + _owned(false), + _max_capacity(fixed_buffer_size), + _flush_threshold(flush_threshold) +{ } void bufferedStream::write(const char* s, size_t len) { - if(buffer_pos + len > buffer_max) { - flush(); + if(_pos + len > _flush_threshold) { + flush(); // Noop for bufferedStream. Flushes and resets for networkStream. } - size_t end = buffer_pos + len; - if (end >= buffer_length) { - if (buffer_fixed) { - // if buffer cannot resize, silently truncate - len = buffer_length - buffer_pos - 1; - } else { - // For small overruns, double the buffer. For larger ones, - // increase to the requested size. - if (end < buffer_length * 2) { - end = buffer_length * 2; - } - buffer = REALLOC_C_HEAP_ARRAY(char, buffer, end, mtInternal); - buffer_length = end; + size_t end = _pos + len; + if (end >= _capacity && _owned && _capacity < _max_capacity) { + // For small overruns, double the buffer. For larger ones, + // increase to the requested size. + if (end < _capacity * 2) { + end = _capacity * 2; + } + // Do not grow beyond max. + if (end > _max_capacity) { + end = _max_capacity; } + _buffer = REALLOC_C_HEAP_ARRAY(char, _buffer, end, mtInternal); + _capacity = end; } - memcpy(buffer + buffer_pos, s, len); - buffer_pos += len; - update_position(s, len); + + const size_t remaining = _capacity - _pos - 1; + len = MIN2(len, remaining); + if (len > 0) { + memcpy(_buffer + _pos, s, len); + _pos += len; + update_position(s, len); + } + } char* bufferedStream::as_string() { - char* copy = NEW_RESOURCE_ARRAY(char, buffer_pos+1); - strncpy(copy, buffer, buffer_pos); - copy[buffer_pos] = 0; // terminating null + char* copy = NEW_RESOURCE_ARRAY(char, _pos+1); + strncpy(copy, _buffer, _pos); + copy[_pos] = 0; // terminating null return copy; } bufferedStream::~bufferedStream() { - if (!buffer_fixed) { - FREE_C_HEAP_ARRAY(char, buffer); + if (_owned) { + FREE_C_HEAP_ARRAY(char, _buffer); } }