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