/* * 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/checkpoint/types/traceid/jfrTraceId.inline.hpp" #include "jfr/recorder/service/jfrOptionSet.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" - XXX 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(*(u8*)&(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 = false; 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); } // XXX // 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((u8)JfrTime::is_ft_enabled() ? time.ft_value() : time.value()); } template void WriterHost::write(const Tickspan& time) { write((u8)JfrTime::is_ft_enabled() ? time.ft_value() : time.value()); } template void WriterHost::write(const JfrTicks& time) { write((u8)time.value()); } template void WriterHost::write(const JfrTickspan& time) { write((u8)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