1 /*
2  * Copyright (c) 2017, 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 #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
is_large_value(const JavaValue & value)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 
resolve(const char * str)41 static Symbol* resolve(const char* str) {
42   assert(str != NULL, "invariant");
43   return SymbolTable::new_symbol(str);
44 }
45 
resolve(Symbol * k_sym,TRAPS)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 
Parameters()51 JfrJavaArguments::Parameters::Parameters() : _storage_index(0), _java_stack_slots(0) {
52   JavaValue value(T_VOID);
53   push(value);
54 }
55 
push(const JavaValue & value)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 
push_large(const JavaValue & value)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 
set_receiver(const oop receiver)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(cast_from_oop<jobject>(receiver));
77   _storage[0] = value;
78 }
79 
set_receiver(Handle receiver)80 void JfrJavaArguments::Parameters::set_receiver(Handle receiver) {
81   set_receiver(receiver());
82 }
83 
receiver() const84 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 
has_receiver() const90 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 
push_oop(const oop obj)97 void JfrJavaArguments::Parameters::push_oop(const oop obj) {
98   JavaValue value(T_OBJECT);
99   value.set_jobject(cast_from_oop<jobject>(obj));
100   push(value);
101 }
102 
push_oop(Handle h_obj)103 void JfrJavaArguments::Parameters::push_oop(Handle h_obj) {
104   push_oop(h_obj());
105 }
106 
push_jobject(jobject h)107 void JfrJavaArguments::Parameters::push_jobject(jobject h) {
108   JavaValue value(T_ADDRESS);
109   value.set_jobject(h);
110   push(value);
111 }
112 
push_jint(jint i)113 void JfrJavaArguments::Parameters::push_jint(jint i) {
114   JavaValue value(T_INT);
115   value.set_jint(i);
116   push(value);
117 }
118 
push_jfloat(jfloat f)119 void JfrJavaArguments::Parameters::push_jfloat(jfloat f) {
120   JavaValue value(T_FLOAT);
121   value.set_jfloat(f);
122   push(value);
123 }
124 
push_jdouble(jdouble d)125 void JfrJavaArguments::Parameters::push_jdouble(jdouble d) {
126   JavaValue value(T_DOUBLE);
127   value.set_jdouble(d);
128   push_large(value);
129 }
130 
push_jlong(jlong l)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)
length() const138 inline int JfrJavaArguments::Parameters::length() const {
139   assert(_storage_index >= 1, "invariant");
140   return _storage_index;
141 }
142 
java_stack_slots() const143 inline int JfrJavaArguments::Parameters::java_stack_slots() const {
144   return _java_stack_slots;
145 }
146 
values(int idx) const147 const JavaValue& JfrJavaArguments::Parameters::values(int idx) const {
148   assert(idx >= 0, "invariant");
149   assert(idx < SIZE, "invariant");
150   return _storage[idx];
151 }
152 
copy(JavaCallArguments & args,TRAPS) const153 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 
JfrJavaArguments(JavaValue * result)187 JfrJavaArguments::JfrJavaArguments(JavaValue* result) : _result(result), _klass(NULL), _name(NULL), _signature(NULL), _array_length(-1) {
188   assert(result != NULL, "invariant");
189 }
190 
JfrJavaArguments(JavaValue * result,const char * klass_name,const char * name,const char * signature,TRAPS)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(-1) {
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);
203   }
204   if (signature != NULL) {
205     set_signature(signature);
206   }
207 }
208 
JfrJavaArguments(JavaValue * result,const Klass * klass,const Symbol * name,const Symbol * signature)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(-1) {
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 
klass() const226 Klass* JfrJavaArguments::klass() const {
227   assert(_klass != NULL, "invariant");
228   return const_cast<Klass*>(_klass);
229 }
230 
set_klass(const char * klass_name,TRAPS)231 void JfrJavaArguments::set_klass(const char* klass_name, TRAPS) {
232   assert(klass_name != NULL, "invariant");
233   Symbol* const k_sym = resolve(klass_name);
234   assert(k_sym != NULL, "invariant");
235   const Klass* const klass = resolve(k_sym, CHECK);
236   set_klass(klass);
237 }
238 
set_klass(const Klass * klass)239 void JfrJavaArguments::set_klass(const Klass* klass) {
240   assert(klass != NULL, "invariant");
241   _klass = klass;
242 }
243 
name() const244 Symbol* JfrJavaArguments::name() const {
245   assert(_name != NULL, "invariant");
246   return const_cast<Symbol*>(_name);
247 }
248 
set_name(const char * name)249 void JfrJavaArguments::set_name(const char* name) {
250   assert(name != NULL, "invariant");
251   const Symbol* const sym = resolve(name);
252   set_name(sym);
253 }
254 
set_name(const Symbol * name)255 void JfrJavaArguments::set_name(const Symbol* name) {
256   assert(name != NULL, "invariant");
257   _name = name;
258 }
259 
signature() const260 Symbol* JfrJavaArguments::signature() const {
261   assert(_signature != NULL, "invariant");
262   return const_cast<Symbol*>(_signature);
263 }
264 
set_signature(const char * signature)265 void JfrJavaArguments::set_signature(const char* signature) {
266   assert(signature != NULL, "invariant");
267   const Symbol* const sym = resolve(signature);
268   set_signature(sym);
269 }
270 
set_signature(const Symbol * signature)271 void JfrJavaArguments::set_signature(const Symbol* signature) {
272   assert(signature != NULL, "invariant");
273   _signature = signature;
274 }
275 
array_length() const276 int JfrJavaArguments::array_length() const {
277   return _array_length;
278 }
279 
set_array_length(int length)280 void JfrJavaArguments::set_array_length(int length) {
281   assert(length >= 0, "invariant");
282   _array_length = length;
283 }
284 
result() const285 JavaValue* JfrJavaArguments::result() const {
286   assert(_result != NULL, "invariant");
287   return const_cast<JavaValue*>(_result);
288 }
289 
length() const290 int JfrJavaArguments::length() const {
291   return _params.length();
292 }
293 
has_receiver() const294 bool JfrJavaArguments::has_receiver() const {
295   return _params.has_receiver();
296 }
297 
receiver() const298 oop JfrJavaArguments::receiver() const {
299   return _params.receiver();
300 }
301 
set_receiver(const oop receiver)302 void JfrJavaArguments::set_receiver(const oop receiver) {
303   _params.set_receiver(receiver);
304 }
305 
set_receiver(Handle receiver)306 void JfrJavaArguments::set_receiver(Handle receiver) {
307   _params.set_receiver(receiver);
308 }
309 
push_oop(const oop obj)310 void JfrJavaArguments::push_oop(const oop obj) {
311   _params.push_oop(obj);
312 }
313 
push_oop(Handle h_obj)314 void JfrJavaArguments::push_oop(Handle h_obj) {
315   _params.push_oop(h_obj);
316 }
317 
push_jobject(jobject h)318 void JfrJavaArguments::push_jobject(jobject h) {
319   _params.push_jobject(h);
320 }
321 
push_int(jint i)322 void JfrJavaArguments::push_int(jint i) {
323   _params.push_jint(i);
324 }
325 
push_float(jfloat f)326 void JfrJavaArguments::push_float(jfloat f) {
327   _params.push_jfloat(f);
328 }
329 
push_double(jdouble d)330 void JfrJavaArguments::push_double(jdouble d) {
331   _params.push_jdouble(d);
332 }
333 
push_long(jlong l)334 void JfrJavaArguments::push_long(jlong l) {
335   _params.push_jlong(l);
336 }
337 
param(int idx) const338 const JavaValue& JfrJavaArguments::param(int idx) const {
339   return _params.values(idx);
340 }
341 
java_call_arg_slots() const342 int JfrJavaArguments::java_call_arg_slots() const {
343   return _params.java_stack_slots();
344 }
345 
copy(JavaCallArguments & args,TRAPS)346 void JfrJavaArguments::copy(JavaCallArguments& args, TRAPS) {
347   _params.copy(args, THREAD);
348 }
349 
call_static(JfrJavaArguments * args,TRAPS)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 
call_special(JfrJavaArguments * args,TRAPS)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 
call_virtual(JfrJavaArguments * args,TRAPS)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 }
381