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