1 /*
   2  * Copyright (c) 2016, 2018, 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/checkpoint/types/traceid/jfrTraceId.inline.hpp"
  30 #include "jfr/recorder/service/jfrOptionSet.hpp"
  31 #include "jfr/writers/jfrEncoding.hpp"
  32 #include "jfr/writers/jfrWriterHost.hpp"
  33 #include "memory/resourceArea.hpp"
  34 #include "oops/oop.hpp"
  35 #include "oops/symbol.hpp"
  36 #include "oops/typeArrayOop.inline.hpp"
  37 
  38 inline bool compressed_integers() {
  39   static const bool comp_integers = JfrOptionSet::compressed_integers();
  40   return comp_integers;
  41 }
  42 
  43 template <typename BE, typename IE, typename WriterPolicyImpl >
  44 template <typename T>
  45 inline void WriterHost<BE, IE, WriterPolicyImpl>::write_padded(T value) {
  46   write_padded(&value, 1);
  47 }
  48 
  49 template <typename BE, typename IE, typename WriterPolicyImpl >
  50 template <typename T>
  51 inline void WriterHost<BE, IE, WriterPolicyImpl>::write_padded(const T* value, size_t len) {
  52   assert(value != NULL, "invariant");
  53   assert(len > 0, "invariant");
  54   u1* const pos = ensure_size(sizeof(T) * len);
  55   if (pos) {
  56     this->set_current_pos(write_padded(value, len, pos));
  57   }
  58 }
  59 
  60 template <typename BE, typename IE, typename WriterPolicyImpl >
  61 template <typename T>
  62 inline u1* WriterHost<BE, IE, WriterPolicyImpl>::write_padded(const T* value, size_t len, u1* pos) {
  63   assert(value != NULL, "invariant");
  64   assert(len > 0, "invariant");
  65   assert(pos != NULL, "invariant");
  66   return _compressed_integers ? IE::write_padded(value, len, pos) : BE::write_padded(value, len, pos);
  67 }
  68 
  69 template <typename BE, typename IE, typename WriterPolicyImpl >
  70 template <typename T>
  71 inline void WriterHost<BE, IE, WriterPolicyImpl>::write(const T* value, size_t len) {
  72   assert(value != NULL, "invariant");
  73   assert(len > 0, "invariant");
  74   u1* const pos = ensure_size(sizeof(T) * len);
  75   if (pos) {
  76     this->set_current_pos(write(value, len, pos));
  77   }
  78 }
  79 
  80 template <typename BE, typename IE, typename WriterPolicyImpl >
  81 template <typename T>
  82 inline u1* WriterHost<BE, IE, WriterPolicyImpl>::write(const T* value, size_t len, u1* pos) {
  83   assert(value != NULL, "invariant");
  84   assert(len > 0, "invariant");
  85   assert(pos != NULL, "invariant");
  86   return _compressed_integers ? IE::write(value, len, pos) : BE::write(value, len, pos);
  87 }
  88 
  89 template <typename BE, typename IE, typename WriterPolicyImpl>
  90 void WriterHost<BE, IE, WriterPolicyImpl>::write_utf8(const char* value) {
  91   if (NULL == value) {
  92     // only write encoding byte indicating NULL string
  93     write<u1>(NULL_STRING);
  94     return;
  95   }
  96   write<u1>(UTF8); // designate encoding
  97   const jint len = MIN2<jint>(max_jint, (jint)strlen(value));
  98   write(len);
  99   if (len > 0) {
 100     be_write(value, len);
 101   }
 102 }
 103 
 104 template <typename BE, typename IE, typename WriterPolicyImpl>
 105 void WriterHost<BE, IE, WriterPolicyImpl>::write_utf16(const jchar* value, jint len) {
 106   assert(value != NULL, "invariant");
 107   write((u1)UTF16); // designate encoding
 108   write(len);
 109   if (len > 0) {
 110     write(value, len);
 111   }
 112 }
 113 
 114 template <typename BE, typename IE, typename WriterPolicyImpl >
 115 template <typename T>
 116 inline void WriterHost<BE, IE, WriterPolicyImpl>::be_write(T value) {
 117   u1* const pos = ensure_size(sizeof(T));
 118   if (pos) {
 119     this->set_current_pos(BE::be_write(&value, 1, pos));
 120   }
 121 }
 122 
 123 template <typename BE, typename IE, typename WriterPolicyImpl >
 124 template <typename T>
 125 inline void WriterHost<BE, IE, WriterPolicyImpl>::be_write(const T* value, size_t len) {
 126   assert(value != NULL, "invariant");
 127   assert(len > 0, "invariant");
 128   u1* const pos = ensure_size(sizeof(T) * len);
 129   if (pos) {
 130     this->set_current_pos(BE::be_write(value, len, pos));
 131   }
 132 }
 133 
 134 template <typename BE, typename IE, typename WriterPolicyImpl >
 135 template <typename StorageType>
 136 inline WriterHost<BE, IE, WriterPolicyImpl>::WriterHost(StorageType* storage, Thread* thread) :
 137   WriterPolicyImpl(storage, thread),
 138   _compressed_integers(compressed_integers()) {
 139 }
 140 
 141 template <typename BE, typename IE, typename WriterPolicyImpl >
 142 template <typename StorageType>
 143 inline WriterHost<BE, IE, WriterPolicyImpl>::WriterHost(StorageType* storage, size_t size) :
 144   WriterPolicyImpl(storage, size),
 145   _compressed_integers(compressed_integers()) {
 146 }
 147 
 148 template <typename BE, typename IE, typename WriterPolicyImpl >
 149 inline WriterHost<BE, IE, WriterPolicyImpl>::WriterHost(Thread* thread) :
 150   WriterPolicyImpl(thread),
 151   _compressed_integers(compressed_integers()) {
 152 }
 153 
 154 // Extra size added as a safety cushion when dimensioning memory.
 155 // With varint encoding, the worst case is
 156 // associated with writing negative values.
 157 // For example, writing a negative s1 (-1)
 158 // will encode as 0xff 0x0f (2 bytes).
 159 // In this example, the sizeof(T) == 1 and length == 1,
 160 // but the implementation will need to dimension
 161 // 2 bytes for the encoding.
 162 // Hopefully, negative values should be relatively rare.
 163 static const size_t size_safety_cushion = 1;
 164 
 165 template <typename BE, typename IE, typename WriterPolicyImpl>
 166 inline u1* WriterHost<BE, IE, WriterPolicyImpl>::ensure_size(size_t requested) {
 167   if (!this->is_valid()) {
 168     // cancelled
 169     return NULL;
 170   }
 171   if (this->available_size() < requested + size_safety_cushion) {
 172     if (!this->accommodate(this->used_size(), requested + size_safety_cushion)) {
 173       this->cancel();
 174       return NULL;
 175     }
 176   }
 177   assert(requested + size_safety_cushion <= this->available_size(), "invariant");
 178   return this->current_pos();
 179 }
 180 
 181 template <typename BE, typename IE, typename WriterPolicyImpl>
 182 template <typename T>
 183 inline void WriterHost<BE, IE, WriterPolicyImpl>::write(T value) {
 184   write(&value, 1);
 185 }
 186 
 187 template <typename BE, typename IE, typename WriterPolicyImpl>
 188 inline void WriterHost<BE, IE, WriterPolicyImpl>::write(bool value) {
 189   be_write((u1)value);
 190 }
 191 
 192 template <typename BE, typename IE, typename WriterPolicyImpl>
 193 inline void WriterHost<BE, IE, WriterPolicyImpl>::write(float value) {
 194   be_write(*(u4*)&(value));
 195 }
 196 
 197 template <typename BE, typename IE, typename WriterPolicyImpl>
 198 inline void WriterHost<BE, IE, WriterPolicyImpl>::write(double value) {
 199   be_write(*(uintptr_t*)&(value));
 200 }
 201 
 202 template <typename BE, typename IE, typename WriterPolicyImpl>
 203 inline void WriterHost<BE, IE, WriterPolicyImpl>::write(const char* value) {
 204   // UTF-8, max_jint len
 205   write_utf8(value);
 206 }
 207 
 208 template <typename BE, typename IE, typename WriterPolicyImpl>
 209 inline void WriterHost<BE, IE, WriterPolicyImpl>::write(char* value) {
 210   write(const_cast<const char*>(value));
 211 }
 212 
 213 template <typename BE, typename IE, typename WriterPolicyImpl>
 214 inline void WriterHost<BE, IE, WriterPolicyImpl>::write(jstring string) {
 215   if (string == NULL) {
 216     write<u1>(NULL_STRING);
 217     return;
 218   }
 219   const oop string_oop = JNIHandles::resolve_external_guard(string);
 220   assert(string_oop != NULL, "invariant");
 221   const size_t length = (size_t)java_lang_String::length(string_oop);
 222   if (0 == length) {
 223     write<u1>(EMPTY_STRING);
 224     return;
 225   }
 226   const bool is_latin1_encoded = java_lang_String::is_latin1(string_oop);
 227   const typeArrayOop value = java_lang_String::value(string_oop);
 228   assert(value != NULL, "invariant");
 229   if (is_latin1_encoded) {
 230     write<u1>(LATIN1);
 231     write<u4>((u4)length);
 232     be_write(value->byte_at_addr(0), length);
 233   } else {
 234     write<u1>(UTF16);
 235     write<u4>((u4)length);
 236     write(value->char_at_addr(0), length);
 237   }
 238 }
 239 
 240 template <typename Writer, typename T>
 241 inline void tag_write(Writer* w, const T* t) {
 242   assert(w != NULL, "invariant");
 243   const traceid id = t == NULL ? 0 : JfrTraceId::use(t);
 244   w->write(id);
 245 }
 246 
 247 template <typename BE, typename IE, typename WriterPolicyImpl>
 248 void WriterHost<BE, IE, WriterPolicyImpl>::write(const ClassLoaderData* cld) {
 249   tag_write(this, cld);
 250 }
 251 
 252 template <typename BE, typename IE, typename WriterPolicyImpl>
 253 void WriterHost<BE, IE, WriterPolicyImpl>::write(const Klass* klass) {
 254   tag_write(this, klass);
 255 }
 256 
 257 template <typename BE, typename IE, typename WriterPolicyImpl>
 258 void WriterHost<BE, IE, WriterPolicyImpl>::write(const Method* method) {
 259   tag_write(this, method);
 260 }
 261 
 262 template <typename BE, typename IE, typename WriterPolicyImpl>
 263 void WriterHost<BE, IE, WriterPolicyImpl>::write(const ModuleEntry* module) {
 264   tag_write(this, module);
 265 }
 266 
 267 template <typename BE, typename IE, typename WriterPolicyImpl>
 268 void WriterHost<BE, IE, WriterPolicyImpl>::write(const PackageEntry* package) {
 269   tag_write(this, package);
 270 }
 271 
 272 template <typename BE, typename IE, typename WriterPolicyImpl>
 273 void WriterHost<BE, IE, WriterPolicyImpl>::write(const Symbol* symbol) {
 274   ResourceMark rm;
 275   write_utf8(symbol != NULL ? symbol->as_C_string() : NULL);
 276 }
 277 
 278 template <typename BE, typename IE, typename WriterPolicyImpl>
 279 void WriterHost<BE, IE, WriterPolicyImpl>::write(const Ticks& time) {
 280   write((uintptr_t)JfrTime::is_ft_enabled() ? time.ft_value() : time.value());
 281 }
 282 
 283 template <typename BE, typename IE, typename WriterPolicyImpl>
 284 void WriterHost<BE, IE, WriterPolicyImpl>::write(const Tickspan& time) {
 285   write((uintptr_t)JfrTime::is_ft_enabled() ? time.ft_value() : time.value());
 286 }
 287 
 288 template <typename BE, typename IE, typename WriterPolicyImpl>
 289 void WriterHost<BE, IE, WriterPolicyImpl>::write(const JfrTicks& time) {
 290   write((uintptr_t)time.value());
 291 }
 292 
 293 template <typename BE, typename IE, typename WriterPolicyImpl>
 294 void WriterHost<BE, IE, WriterPolicyImpl>::write(const JfrTickspan& time) {
 295   write((uintptr_t)time.value());
 296 }
 297 
 298 template <typename BE, typename IE, typename WriterPolicyImpl>
 299 void WriterHost<BE, IE, WriterPolicyImpl>::bytes(const void* buf, size_t len) {
 300   u1* const pos = this->ensure_size(len);
 301   if (pos != NULL) {
 302     WriterPolicyImpl::bytes(pos, buf, len); // WriterPolicyImpl responsible for position update
 303   }
 304 }
 305 
 306 // UTF-8 for use with classfile/bytecodes
 307 template <typename BE, typename IE, typename WriterPolicyImpl>
 308 inline void WriterHost<BE, IE, WriterPolicyImpl>::write_utf8_u2_len(const char* value) {
 309   u2 len = 0;
 310   if (value != NULL) {
 311     len = MIN2<u2>(max_jushort, (u2)strlen(value));
 312   }
 313   write(len);
 314   if (len > 0) {
 315     be_write(value, len);
 316   }
 317 }
 318 
 319 template <typename BE, typename IE, typename WriterPolicyImpl>
 320 inline intptr_t WriterHost<BE, IE, WriterPolicyImpl>::reserve(size_t size) {
 321   if (ensure_size(size) != NULL) {
 322     intptr_t reserved_offset = this->current_offset();
 323     this->set_current_pos(size);
 324     return reserved_offset;
 325   }
 326   this->cancel();
 327   return 0;
 328 }
 329 
 330 template <typename BE, typename IE, typename WriterPolicyImpl>
 331 template <typename T>
 332 inline void WriterHost<BE, IE, WriterPolicyImpl>::write_padded_at_offset(T value, intptr_t offset) {
 333   if (this->is_valid()) {
 334     const intptr_t current = this->current_offset();
 335     this->seek(offset);
 336     write_padded(value);
 337     this->seek(current); // restore
 338   }
 339 }
 340 
 341 template <typename BE, typename IE, typename WriterPolicyImpl>
 342 template <typename T>
 343 inline void WriterHost<BE, IE, WriterPolicyImpl>::write_at_offset(T value, intptr_t offset) {
 344   if (this->is_valid()) {
 345     const intptr_t current = this->current_offset();
 346     this->seek(offset);
 347     write(value);
 348     this->seek(current); // restore
 349   }
 350 }
 351 
 352 template <typename BE, typename IE, typename WriterPolicyImpl>
 353 template <typename T>
 354 inline void WriterHost<BE, IE, WriterPolicyImpl>::write_be_at_offset(T value, intptr_t offset) {
 355   if (this->is_valid()) {
 356     const intptr_t current = this->current_offset();
 357     this->seek(offset);
 358     be_write(value);
 359     this->seek(current); // restore
 360   }
 361 }
 362 
 363 #endif // SHARE_VM_JFR_WRITERS_JFRWRITERHOST_INLINE_HPP
 364