--- /dev/null 2017-11-09 09:38:01.297999907 +0100 +++ new/src/hotspot/share/jfr/writers/jfrWriterHost.inline.hpp 2018-04-09 15:31:57.429310973 +0200 @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2016, 2018, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_JFR_WRITERS_JFRWRITERHOST_INLINE_HPP +#define SHARE_VM_JFR_WRITERS_JFRWRITERHOST_INLINE_HPP + +#include "classfile/javaClasses.hpp" +#include "jfr/recorder/access/jfrOptionSet.hpp" +#include "jfr/recorder/checkpoint/constant/traceid/jfrTraceId.inline.hpp" +#include "jfr/utilities/jfrTraceTime.hpp" +#include "jfr/writers/jfrEncoding.hpp" +#include "jfr/writers/jfrWriterHost.hpp" +#include "memory/resourceArea.hpp" +#include "oops/oop.hpp" +#include "oops/symbol.hpp" +#include "oops/typeArrayOop.inline.hpp" + +inline bool compressed_integers() { + static const bool comp_integers = JfrOptionSet::compressed_integers(); + return comp_integers; +} + +template +template +inline void WriterHost::write_padded(T value) { + write_padded(&value, 1); +} + +template +template +inline void WriterHost::write_padded(const T* value, size_t len) { + assert(value != NULL, "invariant"); + assert(len > 0, "invariant"); + u1* const pos = ensure_size(sizeof(T) * len); + if (pos) { + this->set_current_pos(write_padded(value, len, pos)); + } +} + +template +template +inline u1* WriterHost::write_padded(const T* value, size_t len, u1* pos) { + assert(value != NULL, "invariant"); + assert(len > 0, "invariant"); + assert(pos != NULL, "invariant"); + return _compressed_integers ? IE::write_padded(value, len, pos) : BE::write_padded(value, len, pos); +} + +template +template +inline void WriterHost::write(const T* value, size_t len) { + assert(value != NULL, "invariant"); + assert(len > 0, "invariant"); + u1* const pos = ensure_size(sizeof(T) * len); + if (pos) { + this->set_current_pos(write(value, len, pos)); + } +} + +template +template +inline u1* WriterHost::write(const T* value, size_t len, u1* pos) { + assert(value != NULL, "invariant"); + assert(len > 0, "invariant"); + assert(pos != NULL, "invariant"); + return _compressed_integers ? IE::write(value, len, pos) : BE::write(value, len, pos); +} + +template +void WriterHost::write_utf8(const char* value) { + if (NULL == value) { + // only write encoding byte indicating NULL string + write(NULL_STRING); + return; + } + write(UTF8); // designate encoding + const jint len = MIN2(max_jint, (jint)strlen(value)); + write(len); + if (len > 0) { + be_write(value, len); + } +} + +template +void WriterHost::write_utf16(const jchar* value, jint len) { + assert(value != NULL, "invariant"); + write((u1)UTF16); // designate encoding + write(len); + if (len > 0) { + write(value, len); + } +} + +template +template +inline void WriterHost::be_write(T value) { + u1* const pos = ensure_size(sizeof(T)); + if (pos) { + this->set_current_pos(BE::be_write(&value, 1, pos)); + } +} + +template +template +inline void WriterHost::be_write(const T* value, size_t len) { + assert(value != NULL, "invariant"); + assert(len > 0, "invariant"); + u1* const pos = ensure_size(sizeof(T) * len); + if (pos) { + this->set_current_pos(BE::be_write(value, len, pos)); + } +} + +template +template +inline WriterHost::WriterHost(StorageType* storage, Thread* thread) : + WriterPolicyImpl(storage, thread), + _compressed_integers(compressed_integers()) { +} + +template +template +inline WriterHost::WriterHost(StorageType* storage, size_t size) : + WriterPolicyImpl(storage, size), + _compressed_integers(compressed_integers()) { +} + +template +inline WriterHost::WriterHost(Thread* thread) : + WriterPolicyImpl(thread), + _compressed_integers(compressed_integers()) { +} + +// Extra size added as a safety cushion when dimensioning memory. +// With varint encoding, the worst case is +// associated with writing negative values. +// For example, writing a negative s1 (-1) +// will encode as 0xff 0x0f (2 bytes). +// In this example, the sizeof(T) == 1 and length == 1, +// but the implementation will need to dimension +// 2 bytes for the encoding. +// Hopefully, negative values should be relatively rare. +static const size_t size_safety_cushion = 1; + +template +inline u1* WriterHost::ensure_size(size_t requested) { + if (!this->is_valid()) { + // cancelled + return NULL; + } + if (this->available_size() < requested + size_safety_cushion) { + if (!this->accommodate(this->used_size(), requested + size_safety_cushion)) { + this->cancel(); + return NULL; + } + } + assert(requested + size_safety_cushion <= this->available_size(), "invariant"); + return this->current_pos(); +} + +template +template +inline void WriterHost::write(T value) { + write(&value, 1); +} + +template +inline void WriterHost::write(bool value) { + be_write((u1)value); +} + +template +inline void WriterHost::write(float value) { + be_write(*(u4*)&(value)); +} + +template +inline void WriterHost::write(double value) { + be_write(*(uintptr_t*)&(value)); +} + +template +inline void WriterHost::write(const char* value) { + // UTF-8, max_jint len + write_utf8(value); +} + +template +inline void WriterHost::write(char* value) { + write(const_cast(value)); +} + +template +inline void WriterHost::write(jstring string) { + if (string == NULL) { + write(NULL_STRING); + return; + } + const oop string_oop = JNIHandles::resolve_external_guard(string); + assert(string_oop != NULL, "invariant"); + const size_t length = (size_t)java_lang_String::length(string_oop); + if (0 == length) { + write(EMPTY_STRING); + return; + } + const bool is_latin1_encoded = java_lang_String::is_latin1(string_oop); + const typeArrayOop value = java_lang_String::value(string_oop); + assert(value != NULL, "invariant"); + if (is_latin1_encoded) { + write(LATIN1); + write((u4)length); + be_write(value->byte_at_addr(0), length); + } else { + write(UTF16); + write((u4)length); + write(value->char_at_addr(0), length); + } +} + +template +inline void tag_write(Writer* w, const T* t) { + assert(w != NULL, "invariant"); + const traceid id = t == NULL ? 0 : JfrTraceId::use(t); + w->write(id); +} + +template +void WriterHost::write(const ClassLoaderData* cld) { + tag_write(this, cld); +} + +template +void WriterHost::write(const Klass* klass) { + tag_write(this, klass); +} + +template +void WriterHost::write(const Method* method) { + tag_write(this, method); +} + +template +void WriterHost::write(const ModuleEntry* module) { + tag_write(this, module); +} + +template +void WriterHost::write(const PackageEntry* package) { + tag_write(this, package); +} + +template +void WriterHost::write(const Symbol* symbol) { + ResourceMark rm; + write_utf8(symbol != NULL ? symbol->as_C_string() : NULL); +} + +template +void WriterHost::write(const Ticks& time) { + write((uintptr_t)JfrTraceTime::is_ft_enabled() ? time.ft_value() : time.value()); +} + +template +void WriterHost::write(const Tickspan& time) { + write((uintptr_t)JfrTraceTime::is_ft_enabled() ? time.ft_value() : time.value()); +} + +template +void WriterHost::bytes(const void* buf, size_t len) { + u1* const pos = this->ensure_size(len); + if (pos != NULL) { + WriterPolicyImpl::bytes(pos, buf, len); // WriterPolicyImpl responsible for position update + } +} + +// UTF-8 for use with classfile/bytecodes +template +inline void WriterHost::write_utf8_u2_len(const char* value) { + u2 len = 0; + if (value != NULL) { + len = MIN2(max_jushort, (u2)strlen(value)); + } + write(len); + if (len > 0) { + be_write(value, len); + } +} + +template +inline intptr_t WriterHost::reserve(size_t size) { + if (ensure_size(size) != NULL) { + intptr_t reserved_offset = this->current_offset(); + this->set_current_pos(size); + return reserved_offset; + } + this->cancel(); + return 0; +} + +template +template +inline void WriterHost::write_padded_at_offset(T value, intptr_t offset) { + if (this->is_valid()) { + const intptr_t current = this->current_offset(); + this->seek(offset); + write_padded(value); + this->seek(current); // restore + } +} + +template +template +inline void WriterHost::write_at_offset(T value, intptr_t offset) { + if (this->is_valid()) { + const intptr_t current = this->current_offset(); + this->seek(offset); + write(value); + this->seek(current); // restore + } +} + +template +template +inline void WriterHost::write_be_at_offset(T value, intptr_t offset) { + if (this->is_valid()) { + const intptr_t current = this->current_offset(); + this->seek(offset); + be_write(value); + this->seek(current); // restore + } +} + +#endif // SHARE_VM_JFR_WRITERS_JFRWRITERHOST_INLINE_HPP +