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_JFR_WRITERS_JFRWRITERHOST_INLINE_HPP |
26 | #define SHARE_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(*(u8*)&(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 int64_t WriterHost<BE, IE, WriterPolicyImpl>::reserve(size_t size) { |
321 | if (ensure_size(size) != NULL) { |
322 | const int64_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, int64_t offset) { |
333 | if (this->is_valid()) { |
334 | const int64_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, int64_t offset) { |
344 | if (this->is_valid()) { |
345 | const int64_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, int64_t offset) { |
355 | if (this->is_valid()) { |
356 | const int64_t current = this->current_offset(); |
357 | this->seek(offset); |
358 | be_write(value); |
359 | this->seek(current); // restore |
360 | } |
361 | } |
362 | |
363 | #endif // SHARE_JFR_WRITERS_JFRWRITERHOST_INLINE_HPP |
364 | |