Mercurial > hg > graal-jvmci-8
comparison src/share/vm/graal/graalVMToInterpreter.cpp @ 5747:120820e30baa
added basic high-level interpreter support to HotSpot
author | Christian Haeubl <haeubl@ssw.jku.at> |
---|---|
date | Tue, 03 Jul 2012 16:56:40 +0200 |
parents | |
children | 8d0a6bceb112 |
comparison
equal
deleted
inserted
replaced
5746:17d2c3b72762 | 5747:120820e30baa |
---|---|
1 /* | |
2 * Copyright (c) 2012, 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 #include "precompiled.hpp" | |
25 #include "graal/graalVMToInterpreter.hpp" | |
26 #include "graal/graalInterpreterToVM.hpp" | |
27 #include "classfile/systemDictionary.hpp" | |
28 #include "classfile/vmSymbols.hpp" | |
29 #include "graal/graalCompiler.hpp" | |
30 | |
31 #ifdef HIGH_LEVEL_INTERPRETER | |
32 | |
33 // those are *global* handles | |
34 jobject VMToInterpreter::_interpreterPermObject = NULL; | |
35 jobject VMToInterpreter::_interpreterPermKlass = NULL; | |
36 | |
37 class JavaArgumentBoxer : public SignatureIterator { | |
38 protected: | |
39 JavaCallArguments* _args; | |
40 Thread* _thread; | |
41 objArrayHandle _obj_array; | |
42 int _index; | |
43 int _position; | |
44 | |
45 public: | |
46 JavaArgumentBoxer(Symbol* signature, objArrayHandle obj_array, JavaCallArguments* args, bool is_static, TRAPS) : SignatureIterator(signature) { | |
47 _obj_array = obj_array; | |
48 _args = args; | |
49 _index = _position = 0; | |
50 _thread = THREAD; | |
51 if (!is_static) { | |
52 push(next_object(T_OBJECT)); | |
53 } | |
54 iterate(); | |
55 assert(_index == _obj_array->length(), "arg count mismatch with signature"); | |
56 } | |
57 | |
58 inline void do_bool() { | |
59 if (!is_return_type()) { | |
60 jvalue value; | |
61 value.z = (jboolean)_args->get_int(_position); | |
62 push(java_lang_boxing_object::create(T_BOOLEAN, &value, _thread)); | |
63 } | |
64 } | |
65 inline void do_char() { | |
66 if (!is_return_type()) { | |
67 jvalue value; | |
68 value.c = (jchar)_args->get_int(_position); | |
69 push(java_lang_boxing_object::create(T_CHAR, &value, _thread)); | |
70 } | |
71 } | |
72 inline void do_short() { | |
73 if (!is_return_type()) { | |
74 jvalue value; | |
75 value.s = (jshort)_args->get_int(_position); | |
76 push(java_lang_boxing_object::create(T_SHORT, &value, _thread)); | |
77 } | |
78 } | |
79 inline void do_byte() { | |
80 if (!is_return_type()) { | |
81 jvalue value; | |
82 value.b = (jbyte)_args->get_int(_position); | |
83 push(java_lang_boxing_object::create(T_BYTE, &value, _thread)); | |
84 } | |
85 } | |
86 inline void do_int() { | |
87 if (!is_return_type()) { | |
88 jvalue value; | |
89 value.i = (jint)_args->get_int(_position); | |
90 push(java_lang_boxing_object::create(T_INT, &value, _thread)); | |
91 } | |
92 } | |
93 | |
94 inline void do_long() { | |
95 if (!is_return_type()) { | |
96 jvalue value; | |
97 value.j = (jlong)_args->get_long(_position); | |
98 push(java_lang_boxing_object::create(T_LONG, &value, _thread)); | |
99 } | |
100 } | |
101 | |
102 inline void do_float() { | |
103 if (!is_return_type()) { | |
104 jvalue value; | |
105 value.f = (jfloat)_args->get_float(_position); | |
106 push(java_lang_boxing_object::create(T_FLOAT, &value, _thread)); | |
107 } | |
108 } | |
109 | |
110 inline void do_double() { | |
111 if (!is_return_type()) { | |
112 jvalue value; | |
113 value.d = (jdouble)_args->get_double(_position); | |
114 push(java_lang_boxing_object::create(T_DOUBLE, &value, _thread)); | |
115 } | |
116 } | |
117 | |
118 inline void do_object(int begin, int end) { if (!is_return_type()) push(next_object(T_OBJECT)); } | |
119 inline void do_array(int begin, int end) { if (!is_return_type()) push(next_object(T_ARRAY)); } | |
120 inline void do_void() { } | |
121 | |
122 inline oop next_object(BasicType type) { | |
123 assert(type == T_OBJECT || type == T_ARRAY, "must be"); | |
124 return *(_args->get_raw_oop(_position)); | |
125 } | |
126 | |
127 inline void push(oop obj) { | |
128 _obj_array->obj_at_put(_index, obj); | |
129 _index++; | |
130 } | |
131 }; | |
132 | |
133 bool VMToInterpreter::allocate_interpreter(const char* interpreter_class_name, const char* interpreter_arguments, TRAPS) { | |
134 assert(_interpreterPermObject == NULL && _interpreterPermKlass == NULL, "no need to allocate twice"); | |
135 | |
136 HandleMark hm; | |
137 // load the interpreter class using its fully qualified class name | |
138 Symbol* class_name = SymbolTable::lookup(interpreter_class_name, (int)strlen(interpreter_class_name), CHECK_false); | |
139 instanceKlassHandle interpreter_klass = SystemDictionary::resolve_or_null(class_name, SystemDictionary::java_system_loader(), NULL, CHECK_false); | |
140 if (interpreter_klass.is_null()) { | |
141 tty->print_cr("Could not load HighLevelInterpreterClass '%s'", interpreter_class_name); | |
142 return false; | |
143 } | |
144 | |
145 // allocate an interpreter instance | |
146 interpreter_klass->initialize(CHECK_false); | |
147 instanceHandle interpreter_instance = interpreter_klass->allocate_instance_handle(CHECK_false); | |
148 | |
149 // initialize the interpreter instance | |
150 Handle args; | |
151 if (interpreter_arguments != NULL) { | |
152 args = java_lang_String::create_from_platform_dependent_str(interpreter_arguments, CHECK_false); | |
153 } | |
154 | |
155 JavaValue result(T_BOOLEAN); | |
156 JavaCalls::call_virtual(&result, interpreter_instance, interpreter_klass, vmSymbols::initialize_name(), vmSymbols::setOption_signature(), args, CHECK_false); | |
157 if (result.get_jboolean() != JNI_TRUE) { | |
158 tty->print_cr("Could not invoke '%s::initialize(String)'", interpreter_class_name); | |
159 return false; | |
160 } | |
161 | |
162 // store the instance globally and keep it alive | |
163 _interpreterPermObject = JNIHandles::make_global(interpreter_instance); | |
164 _interpreterPermKlass = JNIHandles::make_global(interpreter_klass); | |
165 | |
166 // register the native functions that are needed by the interpreter | |
167 { | |
168 assert(THREAD->is_Java_thread(), "must be"); | |
169 JavaThread* thread = (JavaThread*) THREAD; | |
170 ThreadToNativeFromVM trans(thread); | |
171 JNIEnv *env = thread->jni_environment(); | |
172 jclass klass = env->FindClass("com/oracle/graal/hotspot/HotSpotRuntimeInterpreterInterface"); | |
173 if (klass == NULL) { | |
174 tty->print_cr("Could not find class HotSpotRuntimeInterpreterInterface"); | |
175 return false; | |
176 } | |
177 env->RegisterNatives(klass, InterpreterToVM_methods, InterpreterToVM_methods_count()); | |
178 if (thread->has_pending_exception()) { | |
179 tty->print_cr("Could not register HotSpotRuntimeInterpreterInterface native methods"); | |
180 return false; | |
181 } | |
182 } | |
183 | |
184 return true; | |
185 } | |
186 | |
187 Handle VMToInterpreter::interpreter_instance() { | |
188 return Handle(JNIHandles::resolve_non_null(_interpreterPermObject)); | |
189 } | |
190 | |
191 KlassHandle VMToInterpreter::interpreter_klass() { | |
192 return KlassHandle(JNIHandles::resolve_non_null(_interpreterPermKlass)); | |
193 } | |
194 | |
195 void VMToInterpreter::execute(JavaValue* result, methodHandle* m, JavaCallArguments* args, BasicType expected_result_type, TRAPS) { | |
196 assert(interpreter_instance().not_null(), "must be allocated before the first call"); | |
197 assert(THREAD->is_Java_thread(), "must be"); | |
198 assert(m != NULL, "must be"); | |
199 assert(args != NULL, "must be"); | |
200 | |
201 JavaThread* thread = (JavaThread*)THREAD; | |
202 methodHandle method = *m; | |
203 int parameter_count = ArgumentCount(method->signature()).size() + (method->is_static() ? 0 : 1); | |
204 objArrayHandle args_array = oopFactory::new_objArray(SystemDictionary::Object_klass(), parameter_count, CHECK); | |
205 JavaArgumentBoxer jab(method->signature(), args_array, args, method->is_static(), thread); | |
206 Handle hotspot_method = GraalCompiler::createHotSpotResolvedJavaMethod(method, CHECK); | |
207 | |
208 JavaValue boxed_result(T_OBJECT); | |
209 JavaCallArguments boxed_args; | |
210 boxed_args.set_receiver(interpreter_instance()); | |
211 boxed_args.push_oop(hotspot_method); | |
212 boxed_args.push_oop(args_array); | |
213 | |
214 #ifndef PRODUCT | |
215 if (PrintHighLevelInterpreterVMTransitions) { | |
216 ResourceMark m; | |
217 tty->print_cr("VM -> high level interpreter (%s)", method->name_and_sig_as_C_string()); | |
218 } | |
219 #endif | |
220 | |
221 thread->set_high_level_interpreter_in_vm(false); | |
222 JavaCalls::call_virtual(&boxed_result, interpreter_klass(), vmSymbols::interpreter_execute_name(), vmSymbols::interpreter_execute_signature(), &boxed_args, thread); | |
223 thread->set_high_level_interpreter_in_vm(true); | |
224 | |
225 #ifndef PRODUCT | |
226 if (PrintHighLevelInterpreterVMTransitions) { | |
227 ResourceMark m; | |
228 tty->print_cr("High level interpreter (%s) -> VM", method->name_and_sig_as_C_string()); | |
229 } | |
230 #endif | |
231 | |
232 if (HAS_PENDING_EXCEPTION) { | |
233 return; | |
234 } | |
235 | |
236 // unbox the result if necessary | |
237 if (is_java_primitive(expected_result_type)) { | |
238 unbox_primitive(&boxed_result, result); | |
239 } else if (expected_result_type == T_OBJECT || expected_result_type == T_ARRAY) { | |
240 result->set_jobject(result->get_jobject()); | |
241 } | |
242 } | |
243 | |
244 void VMToInterpreter::unbox_primitive(JavaValue* boxed, JavaValue* result) { | |
245 oop box = JNIHandles::resolve(boxed->get_jobject()); | |
246 | |
247 jvalue value; | |
248 BasicType type = java_lang_boxing_object::get_value(box, &value); | |
249 switch (type) { | |
250 case T_BOOLEAN: | |
251 result->set_jint(value.z); | |
252 break; | |
253 case T_CHAR: | |
254 result->set_jint(value.c); | |
255 break; | |
256 case T_FLOAT: | |
257 result->set_jfloat(value.f); | |
258 break; | |
259 case T_DOUBLE: | |
260 result->set_jdouble(value.d); | |
261 break; | |
262 case T_BYTE: | |
263 result->set_jint(value.b); | |
264 break; | |
265 case T_SHORT: | |
266 result->set_jint(value.s); | |
267 break; | |
268 case T_INT: | |
269 result->set_jint(value.i); | |
270 break; | |
271 case T_LONG: | |
272 result->set_jlong(value.j); | |
273 break; | |
274 default: | |
275 ShouldNotReachHere(); | |
276 break; | |
277 } | |
278 } | |
279 | |
280 #endif // HIGH_LEVEL_INTERPRETER |