Mercurial > hg > graal-jvmci-8
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalVMToInterpreter.cpp Tue Jul 03 16:56:40 2012 +0200 @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "graal/graalVMToInterpreter.hpp" +#include "graal/graalInterpreterToVM.hpp" +#include "classfile/systemDictionary.hpp" +#include "classfile/vmSymbols.hpp" +#include "graal/graalCompiler.hpp" + +#ifdef HIGH_LEVEL_INTERPRETER + +// those are *global* handles +jobject VMToInterpreter::_interpreterPermObject = NULL; +jobject VMToInterpreter::_interpreterPermKlass = NULL; + +class JavaArgumentBoxer : public SignatureIterator { + protected: + JavaCallArguments* _args; + Thread* _thread; + objArrayHandle _obj_array; + int _index; + int _position; + + public: + JavaArgumentBoxer(Symbol* signature, objArrayHandle obj_array, JavaCallArguments* args, bool is_static, TRAPS) : SignatureIterator(signature) { + _obj_array = obj_array; + _args = args; + _index = _position = 0; + _thread = THREAD; + if (!is_static) { + push(next_object(T_OBJECT)); + } + iterate(); + assert(_index == _obj_array->length(), "arg count mismatch with signature"); + } + + inline void do_bool() { + if (!is_return_type()) { + jvalue value; + value.z = (jboolean)_args->get_int(_position); + push(java_lang_boxing_object::create(T_BOOLEAN, &value, _thread)); + } + } + inline void do_char() { + if (!is_return_type()) { + jvalue value; + value.c = (jchar)_args->get_int(_position); + push(java_lang_boxing_object::create(T_CHAR, &value, _thread)); + } + } + inline void do_short() { + if (!is_return_type()) { + jvalue value; + value.s = (jshort)_args->get_int(_position); + push(java_lang_boxing_object::create(T_SHORT, &value, _thread)); + } + } + inline void do_byte() { + if (!is_return_type()) { + jvalue value; + value.b = (jbyte)_args->get_int(_position); + push(java_lang_boxing_object::create(T_BYTE, &value, _thread)); + } + } + inline void do_int() { + if (!is_return_type()) { + jvalue value; + value.i = (jint)_args->get_int(_position); + push(java_lang_boxing_object::create(T_INT, &value, _thread)); + } + } + + inline void do_long() { + if (!is_return_type()) { + jvalue value; + value.j = (jlong)_args->get_long(_position); + push(java_lang_boxing_object::create(T_LONG, &value, _thread)); + } + } + + inline void do_float() { + if (!is_return_type()) { + jvalue value; + value.f = (jfloat)_args->get_float(_position); + push(java_lang_boxing_object::create(T_FLOAT, &value, _thread)); + } + } + + inline void do_double() { + if (!is_return_type()) { + jvalue value; + value.d = (jdouble)_args->get_double(_position); + push(java_lang_boxing_object::create(T_DOUBLE, &value, _thread)); + } + } + + inline void do_object(int begin, int end) { if (!is_return_type()) push(next_object(T_OBJECT)); } + inline void do_array(int begin, int end) { if (!is_return_type()) push(next_object(T_ARRAY)); } + inline void do_void() { } + + inline oop next_object(BasicType type) { + assert(type == T_OBJECT || type == T_ARRAY, "must be"); + return *(_args->get_raw_oop(_position)); + } + + inline void push(oop obj) { + _obj_array->obj_at_put(_index, obj); + _index++; + } +}; + +bool VMToInterpreter::allocate_interpreter(const char* interpreter_class_name, const char* interpreter_arguments, TRAPS) { + assert(_interpreterPermObject == NULL && _interpreterPermKlass == NULL, "no need to allocate twice"); + + HandleMark hm; + // load the interpreter class using its fully qualified class name + Symbol* class_name = SymbolTable::lookup(interpreter_class_name, (int)strlen(interpreter_class_name), CHECK_false); + instanceKlassHandle interpreter_klass = SystemDictionary::resolve_or_null(class_name, SystemDictionary::java_system_loader(), NULL, CHECK_false); + if (interpreter_klass.is_null()) { + tty->print_cr("Could not load HighLevelInterpreterClass '%s'", interpreter_class_name); + return false; + } + + // allocate an interpreter instance + interpreter_klass->initialize(CHECK_false); + instanceHandle interpreter_instance = interpreter_klass->allocate_instance_handle(CHECK_false); + + // initialize the interpreter instance + Handle args; + if (interpreter_arguments != NULL) { + args = java_lang_String::create_from_platform_dependent_str(interpreter_arguments, CHECK_false); + } + + JavaValue result(T_BOOLEAN); + JavaCalls::call_virtual(&result, interpreter_instance, interpreter_klass, vmSymbols::initialize_name(), vmSymbols::setOption_signature(), args, CHECK_false); + if (result.get_jboolean() != JNI_TRUE) { + tty->print_cr("Could not invoke '%s::initialize(String)'", interpreter_class_name); + return false; + } + + // store the instance globally and keep it alive + _interpreterPermObject = JNIHandles::make_global(interpreter_instance); + _interpreterPermKlass = JNIHandles::make_global(interpreter_klass); + + // register the native functions that are needed by the interpreter + { + assert(THREAD->is_Java_thread(), "must be"); + JavaThread* thread = (JavaThread*) THREAD; + ThreadToNativeFromVM trans(thread); + JNIEnv *env = thread->jni_environment(); + jclass klass = env->FindClass("com/oracle/graal/hotspot/HotSpotRuntimeInterpreterInterface"); + if (klass == NULL) { + tty->print_cr("Could not find class HotSpotRuntimeInterpreterInterface"); + return false; + } + env->RegisterNatives(klass, InterpreterToVM_methods, InterpreterToVM_methods_count()); + if (thread->has_pending_exception()) { + tty->print_cr("Could not register HotSpotRuntimeInterpreterInterface native methods"); + return false; + } + } + + return true; +} + +Handle VMToInterpreter::interpreter_instance() { + return Handle(JNIHandles::resolve_non_null(_interpreterPermObject)); +} + +KlassHandle VMToInterpreter::interpreter_klass() { + return KlassHandle(JNIHandles::resolve_non_null(_interpreterPermKlass)); +} + +void VMToInterpreter::execute(JavaValue* result, methodHandle* m, JavaCallArguments* args, BasicType expected_result_type, TRAPS) { + assert(interpreter_instance().not_null(), "must be allocated before the first call"); + assert(THREAD->is_Java_thread(), "must be"); + assert(m != NULL, "must be"); + assert(args != NULL, "must be"); + + JavaThread* thread = (JavaThread*)THREAD; + methodHandle method = *m; + int parameter_count = ArgumentCount(method->signature()).size() + (method->is_static() ? 0 : 1); + objArrayHandle args_array = oopFactory::new_objArray(SystemDictionary::Object_klass(), parameter_count, CHECK); + JavaArgumentBoxer jab(method->signature(), args_array, args, method->is_static(), thread); + Handle hotspot_method = GraalCompiler::createHotSpotResolvedJavaMethod(method, CHECK); + + JavaValue boxed_result(T_OBJECT); + JavaCallArguments boxed_args; + boxed_args.set_receiver(interpreter_instance()); + boxed_args.push_oop(hotspot_method); + boxed_args.push_oop(args_array); + +#ifndef PRODUCT + if (PrintHighLevelInterpreterVMTransitions) { + ResourceMark m; + tty->print_cr("VM -> high level interpreter (%s)", method->name_and_sig_as_C_string()); + } +#endif + + thread->set_high_level_interpreter_in_vm(false); + JavaCalls::call_virtual(&boxed_result, interpreter_klass(), vmSymbols::interpreter_execute_name(), vmSymbols::interpreter_execute_signature(), &boxed_args, thread); + thread->set_high_level_interpreter_in_vm(true); + +#ifndef PRODUCT + if (PrintHighLevelInterpreterVMTransitions) { + ResourceMark m; + tty->print_cr("High level interpreter (%s) -> VM", method->name_and_sig_as_C_string()); + } +#endif + + if (HAS_PENDING_EXCEPTION) { + return; + } + + // unbox the result if necessary + if (is_java_primitive(expected_result_type)) { + unbox_primitive(&boxed_result, result); + } else if (expected_result_type == T_OBJECT || expected_result_type == T_ARRAY) { + result->set_jobject(result->get_jobject()); + } +} + +void VMToInterpreter::unbox_primitive(JavaValue* boxed, JavaValue* result) { + oop box = JNIHandles::resolve(boxed->get_jobject()); + + jvalue value; + BasicType type = java_lang_boxing_object::get_value(box, &value); + switch (type) { + case T_BOOLEAN: + result->set_jint(value.z); + break; + case T_CHAR: + result->set_jint(value.c); + break; + case T_FLOAT: + result->set_jfloat(value.f); + break; + case T_DOUBLE: + result->set_jdouble(value.d); + break; + case T_BYTE: + result->set_jint(value.b); + break; + case T_SHORT: + result->set_jint(value.s); + break; + case T_INT: + result->set_jint(value.i); + break; + case T_LONG: + result->set_jlong(value.j); + break; + default: + ShouldNotReachHere(); + break; + } +} + +#endif // HIGH_LEVEL_INTERPRETER