1 /* 2 * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_VM_JFR_WRITERS_JFRWRITERHOST_INLINE_HPP 26 #define SHARE_VM_JFR_WRITERS_JFRWRITERHOST_INLINE_HPP 27 28 #include "classfile/javaClasses.hpp" 29 #include "jfr/recorder/access/jfrOptionSet.hpp" 30 #include "jfr/recorder/checkpoint/constant/traceid/jfrTraceId.inline.hpp" 31 #include "jfr/utilities/jfrTraceTime.hpp" 32 #include "jfr/writers/jfrEncoding.hpp" 33 #include "jfr/writers/jfrWriterHost.hpp" 34 #include "memory/resourceArea.hpp" 35 #include "oops/oop.hpp" 36 #include "oops/symbol.hpp" 37 #include "oops/typeArrayOop.hpp" 38 39 inline bool compressed_integers() { 40 static const bool comp_integers = JfrOptionSet::compressed_integers(); 41 return comp_integers; 42 } 43 44 template <typename BE, typename IE, typename WriterPolicyImpl > 45 template <typename T> 46 inline void WriterHost<BE, IE, WriterPolicyImpl>::write_padded(T value) { 47 write_padded(&value, 1); 48 } 49 50 template <typename BE, typename IE, typename WriterPolicyImpl > 51 template <typename T> 52 inline void WriterHost<BE, IE, WriterPolicyImpl>::write_padded(const T* value, size_t len) { 53 assert(value != NULL, "invariant"); 54 assert(len > 0, "invariant"); 55 u1* const pos = ensure_size(sizeof(T) * len); 56 if (pos) { 57 this->set_current_pos(write_padded(value, len, pos)); 58 } 59 } 60 61 template <typename BE, typename IE, typename WriterPolicyImpl > 62 template <typename T> 63 inline u1* WriterHost<BE, IE, WriterPolicyImpl>::write_padded(const T* value, size_t len, u1* pos) { 64 assert(value != NULL, "invariant"); 65 assert(len > 0, "invariant"); 66 assert(pos != NULL, "invariant"); 67 return _compressed_integers ? IE::write_padded(value, len, pos) : BE::write_padded(value, len, pos); 68 } 69 70 template <typename BE, typename IE, typename WriterPolicyImpl > 71 template <typename T> 72 inline void WriterHost<BE, IE, WriterPolicyImpl>::write(const T* value, size_t len) { 73 assert(value != NULL, "invariant"); 74 assert(len > 0, "invariant"); 75 u1* const pos = ensure_size(sizeof(T) * len); 76 if (pos) { 77 this->set_current_pos(write(value, len, pos)); 78 } 79 } 80 81 template <typename BE, typename IE, typename WriterPolicyImpl > 82 template <typename T> 83 inline u1* WriterHost<BE, IE, WriterPolicyImpl>::write(const T* value, size_t len, u1* pos) { 84 assert(value != NULL, "invariant"); 85 assert(len > 0, "invariant"); 86 assert(pos != NULL, "invariant"); 87 return _compressed_integers ? IE::write(value, len, pos) : BE::write(value, len, pos); 88 } 89 90 template <typename BE, typename IE, typename WriterPolicyImpl> 91 void WriterHost<BE, IE, WriterPolicyImpl>::write_utf8(const char* value) { 92 if (NULL == value) { 93 // only write encoding byte indicating NULL string 94 write<u1>(NULL_STRING); 95 return; 96 } 97 write<u1>(UTF8); // designate encoding 98 const jint len = MIN2<jint>(max_jint, (jint)strlen(value)); 99 write(len); 100 if (len > 0) { 101 be_write(value, len); 102 } 103 } 104 105 template <typename BE, typename IE, typename WriterPolicyImpl> 106 void WriterHost<BE, IE, WriterPolicyImpl>::write_utf16(const jchar* value, jint len) { 107 assert(value != NULL, "invariant"); 108 write((u1)UTF16); // designate encoding 109 write(len); 110 if (len > 0) { 111 write(value, len); 112 } 113 } 114 115 template <typename BE, typename IE, typename WriterPolicyImpl > 116 template <typename T> 117 inline void WriterHost<BE, IE, WriterPolicyImpl>::be_write(T value) { 118 u1* const pos = ensure_size(sizeof(T)); 119 if (pos) { 120 this->set_current_pos(BE::be_write(&value, 1, pos)); 121 } 122 } 123 124 template <typename BE, typename IE, typename WriterPolicyImpl > 125 template <typename T> 126 inline void WriterHost<BE, IE, WriterPolicyImpl>::be_write(const T* value, size_t len) { 127 assert(value != NULL, "invariant"); 128 assert(len > 0, "invariant"); 129 u1* const pos = ensure_size(sizeof(T) * len); 130 if (pos) { 131 this->set_current_pos(BE::be_write(value, len, pos)); 132 } 133 } 134 135 template <typename BE, typename IE, typename WriterPolicyImpl > 136 template <typename StorageType> 137 inline WriterHost<BE, IE, WriterPolicyImpl>::WriterHost(StorageType* storage, Thread* thread) : 138 WriterPolicyImpl(storage, thread), 139 _compressed_integers(compressed_integers()) { 140 } 141 142 template <typename BE, typename IE, typename WriterPolicyImpl > 143 template <typename StorageType> 144 inline WriterHost<BE, IE, WriterPolicyImpl>::WriterHost(StorageType* storage, size_t size) : 145 WriterPolicyImpl(storage, size), 146 _compressed_integers(compressed_integers()) { 147 } 148 149 template <typename BE, typename IE, typename WriterPolicyImpl > 150 inline WriterHost<BE, IE, WriterPolicyImpl>::WriterHost(Thread* thread) : 151 WriterPolicyImpl(thread), 152 _compressed_integers(compressed_integers()) { 153 } 154 155 // Extra size added as a safety cushion when dimensioning memory. 156 // With varint encoding, the worst case is 157 // associated with writing negative values. 158 // For example, writing a negative s1 (-1) 159 // will encode as 0xff 0x0f (2 bytes). 160 // In this example, the sizeof(T) == 1 and length == 1, 161 // but the implementation will need to dimension 162 // 2 bytes for the encoding. 163 // Hopefully, negative values should be relatively rare. 164 static const size_t size_safety_cushion = 1; 165 166 template <typename BE, typename IE, typename WriterPolicyImpl> 167 inline u1* WriterHost<BE, IE, WriterPolicyImpl>::ensure_size(size_t requested) { 168 if (!this->is_valid()) { 169 // cancelled 170 return NULL; 171 } 172 if (this->available_size() < requested + size_safety_cushion) { 173 if (!this->accommodate(this->used_size(), requested + size_safety_cushion)) { 174 this->cancel(); 175 return NULL; 176 } 177 } 178 assert(requested + size_safety_cushion <= this->available_size(), "invariant"); 179 return this->current_pos(); 180 } 181 182 template <typename BE, typename IE, typename WriterPolicyImpl> 183 template <typename T> 184 inline void WriterHost<BE, IE, WriterPolicyImpl>::write(T value) { 185 write(&value, 1); 186 } 187 188 template <typename BE, typename IE, typename WriterPolicyImpl> 189 inline void WriterHost<BE, IE, WriterPolicyImpl>::write(bool value) { 190 be_write((u1)value); 191 } 192 193 template <typename BE, typename IE, typename WriterPolicyImpl> 194 inline void WriterHost<BE, IE, WriterPolicyImpl>::write(float value) { 195 be_write(*(u4*)&(value)); 196 } 197 198 template <typename BE, typename IE, typename WriterPolicyImpl> 199 inline void WriterHost<BE, IE, WriterPolicyImpl>::write(double value) { 200 be_write(*(uintptr_t*)&(value)); 201 } 202 203 template <typename BE, typename IE, typename WriterPolicyImpl> 204 inline void WriterHost<BE, IE, WriterPolicyImpl>::write(const char* value) { 205 // UTF-8, max_jint len 206 write_utf8(value); 207 } 208 209 template <typename BE, typename IE, typename WriterPolicyImpl> 210 inline void WriterHost<BE, IE, WriterPolicyImpl>::write(char* value) { 211 write(const_cast<const char*>(value)); 212 } 213 214 template <typename BE, typename IE, typename WriterPolicyImpl> 215 inline void WriterHost<BE, IE, WriterPolicyImpl>::write(jstring string) { 216 if (string == NULL) { 217 write<u1>(NULL_STRING); 218 return; 219 } 220 const oop string_oop = JNIHandles::resolve_external_guard(string); 221 assert(string_oop != NULL, "invariant"); 222 const size_t length = (size_t)java_lang_String::length(string_oop); 223 if (0 == length) { 224 write<u1>(EMPTY_STRING); 225 return; 226 } 227 const typeArrayOop value = java_lang_String::value(string_oop); 228 assert(value != NULL, "invariant"); 229 write<u1>(UTF16); 230 write<u4>((u4)length); 231 write(value->char_at_addr(0), length); 232 } 233 234 template <typename Writer, typename T> 235 inline void tag_write(Writer* w, const T* t) { 236 assert(w != NULL, "invariant"); 237 const traceid id = t == NULL ? 0 : JfrTraceId::use(t); 238 w->write(id); 239 } 240 241 template <typename BE, typename IE, typename WriterPolicyImpl> 242 void WriterHost<BE, IE, WriterPolicyImpl>::write(const ClassLoaderData* cld) { 243 tag_write(this, cld); 244 } 245 246 template <typename BE, typename IE, typename WriterPolicyImpl> 247 void WriterHost<BE, IE, WriterPolicyImpl>::write(const Klass* klass) { 248 tag_write(this, klass); 249 } 250 251 template <typename BE, typename IE, typename WriterPolicyImpl> 252 void WriterHost<BE, IE, WriterPolicyImpl>::write(const Method* method) { 253 tag_write(this, method); 254 } 255 256 template <typename BE, typename IE, typename WriterPolicyImpl> 257 void WriterHost<BE, IE, WriterPolicyImpl>::write(const Symbol* symbol) { 258 ResourceMark rm; 259 write_utf8(symbol != NULL ? symbol->as_C_string() : NULL); 260 } 261 262 template <typename BE, typename IE, typename WriterPolicyImpl> 263 void WriterHost<BE, IE, WriterPolicyImpl>::write(const Ticks& time) { 264 write((uintptr_t)JfrTraceTime::is_ft_enabled() ? time.ft_value() : time.value()); 265 } 266 267 template <typename BE, typename IE, typename WriterPolicyImpl> 268 void WriterHost<BE, IE, WriterPolicyImpl>::write(const Tickspan& time) { 269 write((uintptr_t)JfrTraceTime::is_ft_enabled() ? time.ft_value() : time.value()); 270 } 271 272 template <typename BE, typename IE, typename WriterPolicyImpl> 273 void WriterHost<BE, IE, WriterPolicyImpl>::bytes(const void* buf, size_t len) { 274 u1* const pos = this->ensure_size(len); 275 if (pos != NULL) { 276 WriterPolicyImpl::bytes(pos, buf, len); // WriterPolicyImpl responsible for position update 277 } 278 } 279 280 // UTF-8 for use with classfile/bytecodes 281 template <typename BE, typename IE, typename WriterPolicyImpl> 282 inline void WriterHost<BE, IE, WriterPolicyImpl>::write_utf8_u2_len(const char* value) { 283 u2 len = 0; 284 if (value != NULL) { 285 len = MIN2<u2>(max_jushort, (u2)strlen(value)); 286 } 287 write(len); 288 if (len > 0) { 289 be_write(value, len); 290 } 291 } 292 293 template <typename BE, typename IE, typename WriterPolicyImpl> 294 inline intptr_t WriterHost<BE, IE, WriterPolicyImpl>::reserve(size_t size) { 295 if (ensure_size(size) != NULL) { 296 intptr_t reserved_offset = this->current_offset(); 297 this->set_current_pos(size); 298 return reserved_offset; 299 } 300 this->cancel(); 301 return 0; 302 } 303 304 template <typename BE, typename IE, typename WriterPolicyImpl> 305 template <typename T> 306 inline void WriterHost<BE, IE, WriterPolicyImpl>::write_padded_at_offset(T value, intptr_t offset) { 307 if (this->is_valid()) { 308 const intptr_t current = this->current_offset(); 309 this->seek(offset); 310 write_padded(value); 311 this->seek(current); // restore 312 } 313 } 314 315 template <typename BE, typename IE, typename WriterPolicyImpl> 316 template <typename T> 317 inline void WriterHost<BE, IE, WriterPolicyImpl>::write_at_offset(T value, intptr_t offset) { 318 if (this->is_valid()) { 319 const intptr_t current = this->current_offset(); 320 this->seek(offset); 321 write(value); 322 this->seek(current); // restore 323 } 324 } 325 326 template <typename BE, typename IE, typename WriterPolicyImpl> 327 template <typename T> 328 inline void WriterHost<BE, IE, WriterPolicyImpl>::write_be_at_offset(T value, intptr_t offset) { 329 if (this->is_valid()) { 330 const intptr_t current = this->current_offset(); 331 this->seek(offset); 332 be_write(value); 333 this->seek(current); // restore 334 } 335 } 336 337 #endif // SHARE_VM_JFR_WRITERS_JFRWRITERHOST_INLINE_HPP 338