|
1 /* |
|
2 * Copyright (c) 2017, 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 #include "precompiled.hpp" |
|
26 #include "classfile/symbolTable.hpp" |
|
27 #include "classfile/systemDictionary.hpp" |
|
28 #include "jfr/jni/jfrJavaCall.hpp" |
|
29 #include "jfr/jni/jfrJavaSupport.hpp" |
|
30 #include "memory/resourceArea.hpp" |
|
31 #include "runtime/handles.inline.hpp" |
|
32 #include "runtime/javaCalls.hpp" |
|
33 #include "utilities/globalDefinitions.hpp" |
|
34 |
|
35 #ifdef ASSERT |
|
36 static bool is_large_value(const JavaValue& value) { |
|
37 return value.get_type() == T_LONG || value.get_type() == T_DOUBLE; |
|
38 } |
|
39 #endif // ASSERT |
|
40 |
|
41 static Symbol* resolve(const char* str, TRAPS) { |
|
42 assert(str != NULL, "invariant"); |
|
43 return SymbolTable::lookup(str, (int)strlen(str), THREAD); |
|
44 } |
|
45 |
|
46 static Klass* resolve(Symbol* k_sym, TRAPS) { |
|
47 assert(k_sym != NULL, "invariant"); |
|
48 return SystemDictionary::resolve_or_fail(k_sym, true, THREAD); |
|
49 } |
|
50 |
|
51 JfrJavaArguments::Parameters::Parameters() : _storage_index(0), _java_stack_slots(0) { |
|
52 JavaValue value(T_VOID); |
|
53 push(value); |
|
54 } |
|
55 |
|
56 void JfrJavaArguments::Parameters::push(const JavaValue& value) { |
|
57 assert(_storage != NULL, "invariant"); |
|
58 assert(!is_large_value(value), "invariant"); |
|
59 assert(_storage_index < SIZE, "invariant"); |
|
60 _storage[_storage_index++] = value; |
|
61 _java_stack_slots++; |
|
62 } |
|
63 |
|
64 void JfrJavaArguments::Parameters::push_large(const JavaValue& value) { |
|
65 assert(_storage != NULL, "invariant"); |
|
66 assert(is_large_value(value), "invariant"); |
|
67 assert(_storage_index < SIZE, "invariant"); |
|
68 _storage[_storage_index++] = value; |
|
69 _java_stack_slots += 2; |
|
70 } |
|
71 |
|
72 void JfrJavaArguments::Parameters::set_receiver(const oop receiver) { |
|
73 assert(_storage != NULL, "invariant"); |
|
74 assert(receiver != NULL, "invariant"); |
|
75 JavaValue value(T_OBJECT); |
|
76 value.set_jobject((jobject)receiver); |
|
77 _storage[0] = value; |
|
78 } |
|
79 |
|
80 void JfrJavaArguments::Parameters::set_receiver(Handle receiver) { |
|
81 set_receiver(receiver()); |
|
82 } |
|
83 |
|
84 oop JfrJavaArguments::Parameters::receiver() const { |
|
85 assert(has_receiver(), "invariant"); |
|
86 assert(_storage[0].get_type() == T_OBJECT, "invariant"); |
|
87 return (oop)_storage[0].get_jobject(); |
|
88 } |
|
89 |
|
90 bool JfrJavaArguments::Parameters::has_receiver() const { |
|
91 assert(_storage != NULL, "invariant"); |
|
92 assert(_storage_index >= 1, "invariant"); |
|
93 assert(_java_stack_slots >= 1, "invariant"); |
|
94 return _storage[0].get_type() == T_OBJECT; |
|
95 } |
|
96 |
|
97 void JfrJavaArguments::Parameters::push_oop(const oop obj) { |
|
98 JavaValue value(T_OBJECT); |
|
99 value.set_jobject((jobject)obj); |
|
100 push(value); |
|
101 } |
|
102 |
|
103 void JfrJavaArguments::Parameters::push_oop(Handle h_obj) { |
|
104 push_oop(h_obj()); |
|
105 } |
|
106 |
|
107 void JfrJavaArguments::Parameters::push_jobject(jobject h) { |
|
108 JavaValue value(T_ADDRESS); |
|
109 value.set_jobject(h); |
|
110 push(value); |
|
111 } |
|
112 |
|
113 void JfrJavaArguments::Parameters::push_jint(jint i) { |
|
114 JavaValue value(T_INT); |
|
115 value.set_jint(i); |
|
116 push(value); |
|
117 } |
|
118 |
|
119 void JfrJavaArguments::Parameters::push_jfloat(jfloat f) { |
|
120 JavaValue value(T_FLOAT); |
|
121 value.set_jfloat(f); |
|
122 push(value); |
|
123 } |
|
124 |
|
125 void JfrJavaArguments::Parameters::push_jdouble(jdouble d) { |
|
126 JavaValue value(T_DOUBLE); |
|
127 value.set_jdouble(d); |
|
128 push_large(value); |
|
129 } |
|
130 |
|
131 void JfrJavaArguments::Parameters::push_jlong(jlong l) { |
|
132 JavaValue value(T_LONG); |
|
133 value.set_jlong(l); |
|
134 push_large(value); |
|
135 } |
|
136 |
|
137 // including receiver (even if there is none) |
|
138 inline int JfrJavaArguments::Parameters::length() const { |
|
139 assert(_storage_index >= 1, "invariant"); |
|
140 return _storage_index; |
|
141 } |
|
142 |
|
143 inline int JfrJavaArguments::Parameters::java_stack_slots() const { |
|
144 return _java_stack_slots; |
|
145 } |
|
146 |
|
147 const JavaValue& JfrJavaArguments::Parameters::values(int idx) const { |
|
148 assert(idx >= 0, "invariant"); |
|
149 assert(idx < SIZE, "invariant"); |
|
150 return _storage[idx]; |
|
151 } |
|
152 |
|
153 void JfrJavaArguments::Parameters::copy(JavaCallArguments& args, TRAPS) const { |
|
154 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); |
|
155 if (has_receiver()) { |
|
156 args.set_receiver(Handle(THREAD, receiver())); |
|
157 } |
|
158 for (int i = 1; i < length(); ++i) { |
|
159 switch(values(i).get_type()) { |
|
160 case T_BOOLEAN: |
|
161 case T_CHAR: |
|
162 case T_SHORT: |
|
163 case T_INT: |
|
164 args.push_int(values(i).get_jint()); |
|
165 break; |
|
166 case T_LONG: |
|
167 args.push_long(values(i).get_jlong()); |
|
168 break; |
|
169 case T_FLOAT: |
|
170 args.push_float(values(i).get_jfloat()); |
|
171 break; |
|
172 case T_DOUBLE: |
|
173 args.push_double(values(i).get_jdouble()); |
|
174 break; |
|
175 case T_OBJECT: |
|
176 args.push_oop(Handle(THREAD, (oop)values(i).get_jobject())); |
|
177 break; |
|
178 case T_ADDRESS: |
|
179 args.push_jobject(values(i).get_jobject()); |
|
180 break; |
|
181 default: |
|
182 ShouldNotReachHere(); |
|
183 } |
|
184 } |
|
185 } |
|
186 |
|
187 JfrJavaArguments::JfrJavaArguments(JavaValue* result) : _result(result), _klass(NULL), _name(NULL), _signature(NULL), _array_length(0) { |
|
188 assert(result != NULL, "invariant"); |
|
189 } |
|
190 |
|
191 JfrJavaArguments::JfrJavaArguments(JavaValue* result, const char* klass_name, const char* name, const char* signature, TRAPS) : |
|
192 _result(result), |
|
193 _klass(NULL), |
|
194 _name(NULL), |
|
195 _signature(NULL), |
|
196 _array_length(0) { |
|
197 assert(result != NULL, "invariant"); |
|
198 if (klass_name != NULL) { |
|
199 set_klass(klass_name, CHECK); |
|
200 } |
|
201 if (name != NULL) { |
|
202 set_name(name, CHECK); |
|
203 } |
|
204 if (signature != NULL) { |
|
205 set_signature(signature, THREAD); |
|
206 } |
|
207 } |
|
208 |
|
209 JfrJavaArguments::JfrJavaArguments(JavaValue* result, const Klass* klass, const Symbol* name, const Symbol* signature) : _result(result), |
|
210 _klass(NULL), |
|
211 _name(NULL), |
|
212 _signature(NULL), |
|
213 _array_length(0) { |
|
214 assert(result != NULL, "invariant"); |
|
215 if (klass != NULL) { |
|
216 set_klass(klass); |
|
217 } |
|
218 if (name != NULL) { |
|
219 set_name(name); |
|
220 } |
|
221 if (signature != NULL) { |
|
222 set_signature(signature); |
|
223 } |
|
224 } |
|
225 |
|
226 Klass* JfrJavaArguments::klass() const { |
|
227 assert(_klass != NULL, "invariant"); |
|
228 return const_cast<Klass*>(_klass); |
|
229 } |
|
230 |
|
231 void JfrJavaArguments::set_klass(const char* klass_name, TRAPS) { |
|
232 assert(klass_name != NULL, "invariant"); |
|
233 Symbol* const k_sym = resolve(klass_name, CHECK); |
|
234 assert(k_sym != NULL, "invariant"); |
|
235 const Klass* const klass = resolve(k_sym, CHECK); |
|
236 set_klass(klass); |
|
237 } |
|
238 |
|
239 void JfrJavaArguments::set_klass(const Klass* klass) { |
|
240 assert(klass != NULL, "invariant"); |
|
241 _klass = klass; |
|
242 } |
|
243 |
|
244 Symbol* JfrJavaArguments::name() const { |
|
245 assert(_name != NULL, "invariant"); |
|
246 return const_cast<Symbol*>(_name); |
|
247 } |
|
248 |
|
249 void JfrJavaArguments::set_name(const char* name, TRAPS) { |
|
250 assert(name != NULL, "invariant"); |
|
251 const Symbol* const sym = resolve(name, CHECK); |
|
252 set_name(sym); |
|
253 } |
|
254 |
|
255 void JfrJavaArguments::set_name(const Symbol* name) { |
|
256 assert(name != NULL, "invariant"); |
|
257 _name = name; |
|
258 } |
|
259 |
|
260 Symbol* JfrJavaArguments::signature() const { |
|
261 assert(_signature != NULL, "invariant"); |
|
262 return const_cast<Symbol*>(_signature); |
|
263 } |
|
264 |
|
265 void JfrJavaArguments::set_signature(const char* signature, TRAPS) { |
|
266 assert(signature != NULL, "invariant"); |
|
267 const Symbol* const sym = resolve(signature, CHECK); |
|
268 set_signature(sym); |
|
269 } |
|
270 |
|
271 void JfrJavaArguments::set_signature(const Symbol* signature) { |
|
272 assert(signature != NULL, "invariant"); |
|
273 _signature = signature; |
|
274 } |
|
275 |
|
276 int JfrJavaArguments::array_length() const { |
|
277 return _array_length; |
|
278 } |
|
279 |
|
280 void JfrJavaArguments::set_array_length(int length) { |
|
281 assert(length >= 0, "invariant"); |
|
282 _array_length = length; |
|
283 } |
|
284 |
|
285 JavaValue* JfrJavaArguments::result() const { |
|
286 assert(_result != NULL, "invariant"); |
|
287 return const_cast<JavaValue*>(_result); |
|
288 } |
|
289 |
|
290 int JfrJavaArguments::length() const { |
|
291 return _params.length(); |
|
292 } |
|
293 |
|
294 bool JfrJavaArguments::has_receiver() const { |
|
295 return _params.has_receiver(); |
|
296 } |
|
297 |
|
298 oop JfrJavaArguments::receiver() const { |
|
299 return _params.receiver(); |
|
300 } |
|
301 |
|
302 void JfrJavaArguments::set_receiver(const oop receiver) { |
|
303 _params.set_receiver(receiver); |
|
304 } |
|
305 |
|
306 void JfrJavaArguments::set_receiver(Handle receiver) { |
|
307 _params.set_receiver(receiver); |
|
308 } |
|
309 |
|
310 void JfrJavaArguments::push_oop(const oop obj) { |
|
311 _params.push_oop(obj); |
|
312 } |
|
313 |
|
314 void JfrJavaArguments::push_oop(Handle h_obj) { |
|
315 _params.push_oop(h_obj); |
|
316 } |
|
317 |
|
318 void JfrJavaArguments::push_jobject(jobject h) { |
|
319 _params.push_jobject(h); |
|
320 } |
|
321 |
|
322 void JfrJavaArguments::push_int(jint i) { |
|
323 _params.push_jint(i); |
|
324 } |
|
325 |
|
326 void JfrJavaArguments::push_float(jfloat f) { |
|
327 _params.push_jfloat(f); |
|
328 } |
|
329 |
|
330 void JfrJavaArguments::push_double(jdouble d) { |
|
331 _params.push_jdouble(d); |
|
332 } |
|
333 |
|
334 void JfrJavaArguments::push_long(jlong l) { |
|
335 _params.push_jlong(l); |
|
336 } |
|
337 |
|
338 const JavaValue& JfrJavaArguments::param(int idx) const { |
|
339 return _params.values(idx); |
|
340 } |
|
341 |
|
342 int JfrJavaArguments::java_call_arg_slots() const { |
|
343 return _params.java_stack_slots(); |
|
344 } |
|
345 |
|
346 void JfrJavaArguments::copy(JavaCallArguments& args, TRAPS) { |
|
347 _params.copy(args, THREAD); |
|
348 } |
|
349 |
|
350 void JfrJavaCall::call_static(JfrJavaArguments* args, TRAPS) { |
|
351 assert(args != NULL, "invariant"); |
|
352 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); |
|
353 ResourceMark rm(THREAD); |
|
354 HandleMark hm(THREAD); |
|
355 JavaCallArguments jcas(args->java_call_arg_slots()); |
|
356 args->copy(jcas, CHECK); |
|
357 JavaCalls::call_static(args->result(), args->klass(), args->name(), args->signature(), &jcas, THREAD); |
|
358 } |
|
359 |
|
360 void JfrJavaCall::call_special(JfrJavaArguments* args, TRAPS) { |
|
361 assert(args != NULL, "invariant"); |
|
362 assert(args->has_receiver(), "invariant"); |
|
363 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); |
|
364 ResourceMark rm(THREAD); |
|
365 HandleMark hm(THREAD); |
|
366 JavaCallArguments jcas(args->java_call_arg_slots()); |
|
367 args->copy(jcas, CHECK); |
|
368 JavaCalls::call_special(args->result(), args->klass(), args->name(), args->signature(), &jcas, THREAD); |
|
369 } |
|
370 |
|
371 void JfrJavaCall::call_virtual(JfrJavaArguments* args, TRAPS) { |
|
372 assert(args != NULL, "invariant"); |
|
373 assert(args->has_receiver(), "invariant"); |
|
374 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); |
|
375 ResourceMark rm(THREAD); |
|
376 HandleMark hm(THREAD); |
|
377 JavaCallArguments jcas(args->java_call_arg_slots()); |
|
378 args->copy(jcas, CHECK); |
|
379 JavaCalls::call_virtual(args->result(), args->klass(), args->name(), args->signature(), &jcas, THREAD); |
|
380 } |