# HG changeset patch # User Lukas Stadler # Date 1321619650 -3600 # Node ID 5c8fc9f0596093dacd48d0e8b0c9ce5bd137fdfc # Parent 1976ebe361c2f03194cc8b60128a046aca6d666b# Parent 6e1abd79e7c8e13d1448142795b1d398824102e8 Merge diff -r 1976ebe361c2 -r 5c8fc9f05960 domake --- a/domake Fri Nov 18 11:55:00 2011 +0100 +++ b/domake Fri Nov 18 13:34:10 2011 +0100 @@ -49,8 +49,8 @@ pushd $graal_home/make # the piping magic runs stderr through grep and removes the complaints about Xusage.txt files -ARCH_DATA_MODEL=64 LANG=C HOTSPOT_BUILD_JOBS=4 ALT_BOOTDIR=$JDK7 INSTALL=y make productgraal 3>&1 1>&2 2>&3 | grep -v Xusage[.]txt -ARCH_DATA_MODEL=64 LANG=C HOTSPOT_BUILD_JOBS=4 ALT_BOOTDIR=$JDK7G INSTALL=y make jvmggraal 3>&1 1>&2 2>&3 | grep -v Xusage[.]txt +ARCH_DATA_MODEL=64 LANG=C HOTSPOT_BUILD_JOBS=3 ALT_BOOTDIR=$JDK7 INSTALL=y make productgraal 3>&1 1>&2 2>&3 | grep -v Xusage[.]txt +ARCH_DATA_MODEL=64 LANG=C HOTSPOT_BUILD_JOBS=3 ALT_BOOTDIR=$JDK7G INSTALL=y make jvmggraal 3>&1 1>&2 2>&3 | grep -v Xusage[.]txt popd diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalCFGFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalCFGFilter.java Fri Nov 18 13:34:10 2011 +0100 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2011, 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. + * + */ +package com.sun.hotspot.igv.graal.filters; + +import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.filter.AbstractFilter; +import com.sun.hotspot.igv.graph.Connection; +import com.sun.hotspot.igv.graph.Diagram; +import com.sun.hotspot.igv.graph.Figure; +import com.sun.hotspot.igv.graph.InputSlot; +import java.awt.Color; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class GraalCFGFilter extends AbstractFilter { + + public String getName() { + return "Graal CFG Filter"; + } + + public void apply(Diagram d) { + Set
figuresToRemove = new HashSet
(); + Set connectionsToRemove = new HashSet(); + for (Figure f : d.getFigures()) { + final String prop = f.getProperties().get("probability"); + + if (prop == null) { + figuresToRemove.add(f); + } + } + d.removeAllFigures(figuresToRemove); + + for (Figure f : d.getFigures()) { + Properties p = f.getProperties(); + int predCount = Integer.parseInt(p.get("predecessorCount")); + for (InputSlot is : f.getInputSlots()) { + if (is.getPosition() >= predCount && !"EndNode".equals(is.getProperties().get("class"))) { + for (Connection c : is.getConnections()) { + if (!"EndNode".equals(c.getOutputSlot().getFigure().getProperties().get("class"))) { + connectionsToRemove.add(c); + } + } + } + } + } + + for (Connection c : connectionsToRemove) { + c.remove(); + System.out.println("rm " + c); + } + } +} diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/c1/c1_IR.hpp --- a/src/share/vm/c1/c1_IR.hpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/c1/c1_IR.hpp Fri Nov 18 13:34:10 2011 +0100 @@ -237,7 +237,7 @@ // reexecute allowed only for the topmost frame bool reexecute = topmost ? should_reexecute() : false; bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis. - recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, false, is_method_handle_invoke, return_oop, locvals, expvals, monvals); + recorder->describe_scope(pc_offset, (methodOop)scope()->method()->get_oop(), bci(), reexecute, false, is_method_handle_invoke, return_oop, locvals, expvals, monvals); } }; diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/c1/c1_LIRAssembler.cpp --- a/src/share/vm/c1/c1_LIRAssembler.cpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/c1/c1_LIRAssembler.cpp Fri Nov 18 13:34:10 2011 +0100 @@ -405,7 +405,7 @@ if (s == NULL) break; IRScope* scope = s->scope(); //Always pass false for reexecute since these ScopeDescs are never used for deopt - debug_info->describe_scope(pc_offset, scope->method(), s->bci(), false/*reexecute*/, false/*rethrow_exception*/); + debug_info->describe_scope(pc_offset, (methodOop)scope->method()->get_oop(), s->bci(), false/*reexecute*/, false/*rethrow_exception*/); } debug_info->end_non_safepoint(pc_offset); diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/ci/ciEnv.cpp --- a/src/share/vm/ci/ciEnv.cpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/ci/ciEnv.cpp Fri Nov 18 13:34:10 2011 +0100 @@ -204,7 +204,7 @@ _factory->cleanup(); JavaThread* current_thread = JavaThread::current(); _factory->remove_symbols(); - current_thread->set_env(NULL); + //current_thread->set_env(NULL); } // ------------------------------------------------------------------ diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/ci/ciMethod.cpp --- a/src/share/vm/ci/ciMethod.cpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/ci/ciMethod.cpp Fri Nov 18 13:34:10 2011 +0100 @@ -97,11 +97,12 @@ ciEnv *env = CURRENT_ENV; if (env->jvmti_can_hotswap_or_post_breakpoint() && can_be_compiled()) { // 6328518 check hotswap conditions under the right lock. - MutexLocker locker(Compile_lock); - if (Dependencies::check_evol_method(h_m()) != NULL) { - _is_c1_compilable = false; - _is_c2_compilable = false; - } + // TODO(tw): Check if we need that. + //MutexLocker locker(Compile_lock); + //if (Dependencies::check_evol_method(h_m()) != NULL) { + // _is_c1_compilable = false; + // _is_c2_compilable = false; + //} } else { CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops()); } diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/ci/ciObject.cpp --- a/src/share/vm/ci/ciObject.cpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/ci/ciObject.cpp Fri Nov 18 13:34:10 2011 +0100 @@ -73,12 +73,7 @@ ciObject::ciObject(Handle h) { ASSERT_IN_VM; if (ciObjectFactory::is_initialized()) { - if (UseGraal) { - _handle = JNIHandles::make_global(h); - _temp_global = true; - } else { - _handle = JNIHandles::make_local(h()); - } + _handle = JNIHandles::make_local(h()); } else { _handle = JNIHandles::make_global(h); } diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/ci/ciObjectFactory.cpp --- a/src/share/vm/ci/ciObjectFactory.cpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/ci/ciObjectFactory.cpp Fri Nov 18 13:34:10 2011 +0100 @@ -230,7 +230,9 @@ vmSymbols::SID sid = vmSymbols::find_sid(key); if (sid != vmSymbols::NO_SID) { // do not pollute the main cache with it - return vm_symbol_at(sid); + ciSymbol* result = vm_symbol_at(sid); + assert(result != NULL, ""); + return result; } assert(vmSymbols::find_sid(key) == vmSymbols::NO_SID, ""); diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/classfile/vmSymbols.hpp Fri Nov 18 13:34:10 2011 +0100 @@ -303,10 +303,11 @@ template(com_sun_cri_ci_CiKind, "com/sun/cri/ci/CiKind") \ template(com_sun_cri_ci_CiRuntimeCall, "com/sun/cri/ci/CiRuntimeCall") \ template(startCompiler_name, "startCompiler") \ + template(bootstrap_name, "bootstrap") \ template(shutdownCompiler_name, "shutdownCompiler") \ template(compileMethod_name, "compileMethod") \ template(pollJavaQueue_name, "pollJavaQueue") \ - template(compileMethod_signature, "(Lcom/oracle/max/graal/hotspot/HotSpotMethodResolved;I)V") \ + template(compileMethod_signature, "(Lcom/oracle/max/graal/hotspot/HotSpotMethodResolved;IZ)V") \ template(setOption_name, "setOption") \ template(setDefaultOptions_name, "setDefaultOptions") \ template(setOption_signature, "(Ljava/lang/String;)Z") \ @@ -456,6 +457,7 @@ template(void_long_signature, "()J") \ template(void_float_signature, "()F") \ template(void_double_signature, "()D") \ + template(bool_void_signature, "(Z)V") \ template(int_void_signature, "(I)V") \ template(int_int_signature, "(I)I") \ template(char_char_signature, "(C)C") \ diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/code/debugInfoRec.cpp --- a/src/share/vm/code/debugInfoRec.cpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/code/debugInfoRec.cpp Fri Nov 18 13:34:10 2011 +0100 @@ -280,7 +280,7 @@ // must call add_safepoint before: it sets PcDesc and this routine uses // the last PcDesc set void DebugInformationRecorder::describe_scope(int pc_offset, - ciMethod* method, + methodHandle method, int bci, bool reexecute, bool rethrow_exception, @@ -307,7 +307,7 @@ stream()->write_int(sender_stream_offset); // serialize scope - jobject method_enc = (method == NULL)? NULL: method->constant_encoding(); + jobject method_enc = JNIHandles::make_local(Thread::current(), method()); stream()->write_int(oop_recorder()->find_index(method_enc)); stream()->write_bci(bci); assert(method == NULL || diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/code/debugInfoRec.hpp --- a/src/share/vm/code/debugInfoRec.hpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/code/debugInfoRec.hpp Fri Nov 18 13:34:10 2011 +0100 @@ -98,7 +98,7 @@ // by add_non_safepoint, and the locals, expressions, and monitors // must all be null. void describe_scope(int pc_offset, - ciMethod* method, + methodHandle method, int bci, bool reexecute, bool rethrow_exception, diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/compiler/compileBroker.cpp Fri Nov 18 13:34:10 2011 +0100 @@ -591,8 +591,6 @@ _last = task->prev(); } - // (tw) Immediately set compiling flag. - JavaThread::current()->as_CompilerThread()->set_compiling(true); --_size; } @@ -657,70 +655,6 @@ } } -// Bootstrap the graal compiler. Compiles all methods until compile queue is empty and no compilation is active. -void CompileBroker::bootstrap_graal() { - HandleMark hm; - Thread* THREAD = Thread::current(); - tty->print_cr("Bootstrapping graal...."); - - GraalCompiler* compiler = GraalCompiler::instance(); - assert(compiler != NULL, "just checking"); - - jlong start = os::javaTimeMillis(); - add_method_to_queue(SystemDictionary::Object_klass(), vmSymbols::object_initializer_name(), vmSymbols::void_method_signature()); - add_method_to_queue(SystemDictionary::Object_klass(), vmSymbols::equals_name(), vmSymbols::object_boolean_signature()); - add_method_to_queue(SystemDictionary::String_klass(), vmSymbols::length_name(), vmSymbols::void_int_signature()); - add_method_to_queue(SystemDictionary::String_klass(), vmSymbols::object_initializer_name(), vmSymbols::void_method_signature()); - - int z = 0; - while (true) { - { - HandleMark hm; - ResourceMark rm; - MutexLocker locker(_c1_method_queue->lock(), Thread::current()); - if (_c1_method_queue->is_empty()) { - MutexLocker mu(Threads_lock); // grab Threads_lock - JavaThread* current = Threads::first(); - bool compiling = false; - while (current != NULL) { - if (current->is_Compiler_thread()) { - CompilerThread* comp_thread = current->as_CompilerThread(); - if (comp_thread->is_compiling()) { - if (TraceGraal >= 4) { - tty->print_cr("Compile queue empty, but following thread is still compiling:"); - comp_thread->print(); - } - compiling = true; - } - } - current = current->next(); - } - if (!compiling) { - break; - } - } - if (TraceGraal >= 5) { - _c1_method_queue->print(); - } - } - - { - //ThreadToNativeFromVM trans(JavaThread::current()); - os::sleep(THREAD, 10, true); - } - ++z; - } - - // Do a full garbage collection. - Universe::heap()->collect(GCCause::_java_lang_system_gc); - - jlong diff = os::javaTimeMillis() - start; - tty->print_cr("Finished bootstrap in %d ms", diff); - if (CITime) CompileBroker::print_times(); - tty->print_cr("==========================================================================="); -} - - void CompileBroker::notify_java_queue() { HandleMark hm; ResourceMark rm; @@ -1111,7 +1045,7 @@ { MutexLocker locker(queue->lock(), THREAD); - if (Thread::current()->is_Compiler_thread() && CompilerThread::current()->is_compiling() && !BackgroundCompilation) { + if (JavaThread::current()->is_compiling() && !BackgroundCompilation) { TRACE_graal_1("Recursive compile %s!", method->name_and_sig_as_C_string()); method->set_not_compilable(); @@ -1182,16 +1116,23 @@ // and in that case it's best to protect both the testing (here) of // these bits, and their updating (here and elsewhere) under a // common lock. - task = create_compile_task(queue, + /*task = create_compile_task(queue, compile_id, method, osr_bci, comp_level, hot_method, hot_count, comment, - blocking); + blocking);*/ } - if (blocking) { + if (!JavaThread::current()->is_compiling()) { + method->set_queued_for_compilation(); + GraalCompiler::instance()->compile_method(method, osr_bci, blocking); + } else { + // Recursive compile request => ignore. + } + + /*if (blocking) { wait_for_completion(task); - } + }*/ } @@ -1574,17 +1515,9 @@ log->stamp(); log->end_elem(); } - - if (UseGraal) { - thread->set_compiling(true); // Prevent recursive compilations while the compiler is initializing. - ThreadToNativeFromVM trans(JavaThread::current()); - GraalCompiler::instance()->initialize(); - } while (true) { { - // Unset compiling flag. - thread->set_compiling(false); // We need this HandleMark to avoid leaking VM handles. HandleMark hm(thread); @@ -1809,12 +1742,13 @@ compiler(task->comp_level())->compile_method(&ci_env, target, osr_bci); - if (!ci_env.failing() && task->code() == NULL) { + // TODO (tw): Check if this is OK. + /*if (!ci_env.failing() && task->code() == NULL) { //assert(false, "compiler should always document failure"); // The compiler elected, without comment, not to register a result. // Do not attempt further compilations of this method. ci_env.record_method_not_compilable("compile failed", !TieredCompilation); - } + }*/ if (ci_env.failing()) { // Copy this bit to the enclosing block: diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/compiler/compileBroker.hpp --- a/src/share/vm/compiler/compileBroker.hpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/compiler/compileBroker.hpp Fri Nov 18 13:34:10 2011 +0100 @@ -404,7 +404,6 @@ static void print_compiler_threads_on(outputStream* st); - static void bootstrap_graal(); static void add_method_to_queue(klassOop k, Symbol* name, Symbol* signature); static void notify_java_queue(); diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Fri Nov 18 13:34:10 2011 +0100 @@ -27,6 +27,7 @@ #include "graal/graalJavaAccess.hpp" #include "graal/graalVMEntries.hpp" #include "graal/graalVmIds.hpp" +#include "graal/graalEnv.hpp" #include "c1/c1_Runtime1.hpp" #include "classfile/vmSymbols.hpp" #include "vmreg_x86.inline.hpp" @@ -232,38 +233,54 @@ // constructor used to create a method CodeInstaller::CodeInstaller(Handle target_method, nmethod*& nm, bool install_code) { _env = CURRENT_ENV; - ciMethod *ciMethodObject = NULL; - { - methodOop method = getMethodFromHotSpotMethod(HotSpotTargetMethod::method(target_method)); - ciMethodObject = (ciMethod *) _env->get_object(method); - _parameter_count = method->size_of_parameters(); - - No_Safepoint_Verifier no_safepoint; - - initialize_fields(target_method); - assert(_hotspot_method != NULL && _name == NULL, "installMethod needs NON-NULL method and NULL name"); - assert(_hotspot_method->is_a(HotSpotMethodResolved::klass()), "installMethod needs a HotSpotMethodResolved"); - + GraalCompiler::initialize_buffer_blob(); + CodeBuffer buffer(JavaThread::current()->get_buffer_blob()); + + _oop_recorder = new OopRecorder(_env->arena()); + _env->set_oop_recorder(_oop_recorder); + _env->set_dependencies(_dependencies); + _dependencies = new Dependencies(_env); + Handle assumptions_handle = CiTargetMethod::assumptions(HotSpotTargetMethod::targetMethod(target_method)); + if (!assumptions_handle.is_null()) { + objArrayHandle assumptions = (objArrayOop)CiAssumptions::list(assumptions_handle()); + for (int i = 0; i < assumptions->length(); ++i) { + Handle assumption = assumptions->obj_at(i); + if (!assumption.is_null()) { + if (assumption->is_a(CiAssumptions_ConcreteSubtype::klass())) { + assumption_ConcreteSubtype(assumption); + } else if (assumption->is_a(CiAssumptions_ConcreteMethod::klass())) { + assumption_ConcreteMethod(assumption); + } else { + assumption->print(); + fatal("unexpected Assumption subclass"); + } + } + } } - // (very) conservative estimate: each site needs a relocation - //CodeBuffer buffer("temp graal method", _total_size, _sites->length() * relocInfo::length_limit); - GraalCompiler::initialize_buffer_blob(); - CodeBuffer buffer(JavaThread::current()->get_buffer_blob()); - initialize_buffer(buffer); - process_exception_handlers(); + { + No_Safepoint_Verifier no_safepoint; + initialize_fields(target_method); + initialize_buffer(buffer); + process_exception_handlers(); + } int stack_slots = (_frame_size / HeapWordSize) + 2; // conversion to words, need to add two slots for ret address and frame pointer - ThreadToNativeFromVM t((JavaThread*) Thread::current()); - nm = _env->register_method(ciMethodObject, -1, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table, - &_implicit_exception_table, GraalCompiler::instance(), _env->comp_level(), false, false, install_code); + methodHandle method = getMethodFromHotSpotMethod(HotSpotTargetMethod::method(target_method)); + { + nm = GraalEnv::register_method(method, -1, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table, + &_implicit_exception_table, GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, false, false, install_code); + } + method->clear_queued_for_compilation(); } // constructor used to create a stub CodeInstaller::CodeInstaller(Handle target_method, jlong& id) { No_Safepoint_Verifier no_safepoint; _env = CURRENT_ENV; - + + _oop_recorder = new OopRecorder(_env->arena()); + _env->set_oop_recorder(_oop_recorder); initialize_fields(target_method); assert(_hotspot_method == NULL && _name != NULL, "installMethod needs NON-NULL name and NULL method"); @@ -281,14 +298,11 @@ void CodeInstaller::initialize_fields(Handle target_method) { _citarget_method = HotSpotTargetMethod::targetMethod(target_method); _hotspot_method = HotSpotTargetMethod::method(target_method); + if (_hotspot_method != NULL) { + _parameter_count = getMethodFromHotSpotMethod(_hotspot_method)->size_of_parameters(); + } _name = HotSpotTargetMethod::name(target_method); _sites = (arrayOop) HotSpotTargetMethod::sites(target_method); - oop assumptions = CiTargetMethod::assumptions(_citarget_method); - if (assumptions != NULL) { - _assumptions = (arrayOop) CiAssumptions::list(assumptions); - } else { - _assumptions = NULL; - } _exception_handlers = (arrayOop) HotSpotTargetMethod::exceptionHandlers(target_method); _code = (arrayOop) CiTargetMethod::targetCode(_citarget_method); @@ -312,15 +326,10 @@ buffer.initialize_stubs_size(256); buffer.initialize_consts_size(_constants_size); - _oop_recorder = new OopRecorder(_env->arena()); - _env->set_oop_recorder(_oop_recorder); _debug_recorder = new DebugInformationRecorder(_env->oop_recorder()); _debug_recorder->set_oopmaps(new OopMapSet()); - _dependencies = new Dependencies(_env); - - _env->set_oop_recorder(_oop_recorder); + _env->set_debug_info(_debug_recorder); - _env->set_dependencies(_dependencies); buffer.initialize_oop_recorder(_oop_recorder); _instructions = buffer.insts(); @@ -351,53 +360,32 @@ fatal("unexpected Site subclass"); } } - - - if (_assumptions != NULL) { - oop* assumptions = (oop*) _assumptions->base(T_OBJECT); - for (int i = 0; i < _assumptions->length(); ++i) { - oop assumption = assumptions[i]; - if (assumption != NULL) { - if (assumption->is_a(CiAssumptions_ConcreteSubtype::klass())) { - assumption_ConcreteSubtype(assumption); - } else if (assumption->is_a(CiAssumptions_ConcreteMethod::klass())) { - assumption_ConcreteMethod(assumption); - } else { - fatal("unexpected Assumption subclass"); - } - } - } - } } -void CodeInstaller::assumption_ConcreteSubtype(oop assumption) { - oop context_oop = CiAssumptions_ConcreteSubtype::context(assumption); - oop type_oop = CiAssumptions_ConcreteSubtype::subtype(assumption); +void CodeInstaller::assumption_ConcreteSubtype(Handle assumption) { + Handle context_handle = CiAssumptions_ConcreteSubtype::context(assumption); + Handle type_handle = CiAssumptions_ConcreteSubtype::subtype(assumption); - ciKlass* context = (ciKlass*) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(context_oop))); - ciKlass* type = (ciKlass*) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type_oop))); + ciKlass* context = (ciKlass*) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(context_handle))); + ciKlass* type = (ciKlass*) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type_handle))); _dependencies->assert_leaf_type(type); if (context != type) { assert(context->is_abstract(), ""); - ThreadToNativeFromVM trans(JavaThread::current()); _dependencies->assert_abstract_with_unique_concrete_subtype(context, type); } } -void CodeInstaller::assumption_ConcreteMethod(oop assumption) { - oop context_oop = CiAssumptions_ConcreteMethod::context(assumption); - oop method_oop = CiAssumptions_ConcreteMethod::method(assumption); - methodOop method = getMethodFromHotSpotMethod(method_oop); - methodOop context = getMethodFromHotSpotMethod(context_oop); +void CodeInstaller::assumption_ConcreteMethod(Handle assumption) { + Handle context_handle = CiAssumptions_ConcreteMethod::context(assumption); + Handle method_handle = CiAssumptions_ConcreteMethod::method(assumption); + methodHandle method = getMethodFromHotSpotMethod(method_handle()); + methodHandle context = getMethodFromHotSpotMethod(context_handle()); - ciMethod* m = (ciMethod*) CURRENT_ENV->get_object(method); - ciMethod* c = (ciMethod*) CURRENT_ENV->get_object(context); + ciMethod* m = (ciMethod*) CURRENT_ENV->get_object(method()); + ciMethod* c = (ciMethod*) CURRENT_ENV->get_object(context()); ciKlass* context_klass = c->holder(); - { - ThreadToNativeFromVM trans(JavaThread::current()); - _dependencies->assert_unique_concrete_method(context_klass, m); - } + _dependencies->assert_unique_concrete_method(context_klass, m); } void CodeInstaller::process_exception_handlers() { @@ -474,7 +462,6 @@ oop hotspot_method = CiCodePos::method(code_pos); methodOop method = getMethodFromHotSpotMethod(hotspot_method); - ciMethod *cimethod = (ciMethod *) _env->get_object(method); jint bci = CiCodePos::bci(code_pos); bool reexecute; if (bci == -1) { @@ -546,9 +533,9 @@ throw_exception = true; } - _debug_recorder->describe_scope(pc_offset, cimethod, bci, reexecute, throw_exception, false, false, locals_token, expressions_token, monitors_token); + _debug_recorder->describe_scope(pc_offset, method, bci, reexecute, throw_exception, false, false, locals_token, expressions_token, monitors_token); } else { - _debug_recorder->describe_scope(pc_offset, cimethod, bci, reexecute, false, false, false, NULL, NULL, NULL); + _debug_recorder->describe_scope(pc_offset, method, bci, reexecute, false, false, false, NULL, NULL, NULL); } } diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/graal/graalCodeInstaller.hpp --- a/src/share/vm/graal/graalCodeInstaller.hpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Fri Nov 18 13:34:10 2011 +0100 @@ -56,7 +56,6 @@ oop _hotspot_method; oop _name; arrayOop _sites; - arrayOop _assumptions; arrayOop _exception_handlers; CodeOffsets _offsets; @@ -97,8 +96,8 @@ // perform data and call relocation on the CodeBuffer void initialize_buffer(CodeBuffer& buffer); - void assumption_ConcreteSubtype(oop assumption); - void assumption_ConcreteMethod(oop assumption); + void assumption_ConcreteSubtype(Handle assumption); + void assumption_ConcreteMethod(Handle assumption); void site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site); void site_Call(CodeBuffer& buffer, jint pc_offset, oop site); diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/graal/graalCompiler.cpp Fri Nov 18 13:34:10 2011 +0100 @@ -27,6 +27,7 @@ #include "graal/graalVMExits.hpp" #include "graal/graalVMEntries.hpp" #include "graal/graalVmIds.hpp" +#include "graal/graalEnv.hpp" #include "c1/c1_Runtime1.hpp" #include "runtime/arguments.hpp" @@ -40,9 +41,9 @@ // Initialization void GraalCompiler::initialize() { - if (_initialized) return; - _initialized = true; - CompilerThread* THREAD = CompilerThread::current(); + + ThreadToNativeFromVM trans(JavaThread::current()); + JavaThread* THREAD = JavaThread::current(); TRACE_graal_1("GraalCompiler::initialize"); initialize_buffer_blob(); @@ -56,6 +57,8 @@ } env->RegisterNatives(klass, VMEntries_methods, VMEntries_methods_count()); + ResourceMark rm; + HandleMark hm; { VM_ENTRY_MARK; check_pending_exception("Could not register natives"); @@ -77,6 +80,12 @@ vm_abort(false); } } + VMExits::startCompiler(); + + _initialized = true; + if (BootstrapGraal) { + VMExits::bootstrap(); + } } } @@ -95,22 +104,28 @@ } } +void GraalCompiler::compile_method(methodHandle method, int entry_bci, jboolean blocking) { + EXCEPTION_CONTEXT + if (!_initialized) { + method->clear_queued_for_compilation(); + method->invocation_counter()->reset(); + method->backedge_counter()->reset(); + return; + } + assert(_initialized, "must already be initialized"); + ResourceMark rm; + ciEnv* current_env = JavaThread::current()->env(); + JavaThread::current()->set_env(NULL); + JavaThread::current()->set_compiling(true); + Handle hotspot_method = GraalCompiler::createHotSpotMethodResolved(method, CHECK); + VMExits::compileMethod(hotspot_method, entry_bci, blocking); + JavaThread::current()->set_compiling(false); + JavaThread::current()->set_env(current_env); +} + // Compilation entry point for methods void GraalCompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) { - assert(_initialized, "must already be initialized"); - VM_ENTRY_MARK; - ResourceMark rm; - HandleMark hm; - - TRACE_graal_2("GraalCompiler::compile_method"); - - CompilerThread::current()->set_compiling(true); - methodOop method = (methodOop) target->get_oop(); - Handle hotspot_method = GraalCompiler::createHotSpotMethodResolved(method, CHECK); - VMExits::compileMethod(hotspot_method, entry_bci); - CompilerThread::current()->set_compiling(false); - - TRACE_graal_2("GraalCompiler::compile_method exit"); + ShouldNotReachHere(); } void GraalCompiler::exit() { @@ -124,48 +139,67 @@ TRACE_graal_1("GraalCompiler::print_timers"); } -oop GraalCompiler::get_RiType(KlassHandle klass, KlassHandle accessor, TRAPS) { - if (klass->oop_is_instance_slow()) { - assert(instanceKlass::cast(klass())->is_initialized(), "unexpected unresolved klass"); - } else if (klass->oop_is_javaArray_slow()){ +Handle GraalCompiler::get_RiType(Symbol* klass_name, TRAPS) { + return VMExits::createRiTypeUnresolved(VmIds::toString(klass_name, THREAD), THREAD); +} + +Handle GraalCompiler::get_RiTypeFromSignature(constantPoolHandle cp, int index, KlassHandle loading_klass, TRAPS) { + + Symbol* signature = cp->symbol_at(index); + BasicType field_type = FieldType::basic_type(signature); + // If the field is a pointer type, get the klass of the + // field. + if (field_type == T_OBJECT || field_type == T_ARRAY) { + KlassHandle handle = GraalEnv::get_klass_by_name(loading_klass, signature, false); + if (handle.is_null()) { + return get_RiType(signature, CHECK_NULL); + } else { + return get_RiType(handle, CHECK_NULL); + } } else { - klass()->print(); - assert(false, "unexpected klass"); + return VMExits::createRiTypePrimitive(field_type, CHECK_NULL); } +} + +Handle GraalCompiler::get_RiType(constantPoolHandle cp, int index, KlassHandle loading_klass, TRAPS) { + bool is_accessible = false; + + KlassHandle klass = GraalEnv::get_klass_by_index(cp, index, is_accessible, loading_klass); + oop catch_class = NULL; + if (klass.is_null()) { + // We have to lock the cpool to keep the oop from being resolved + // while we are accessing it. + ObjectLocker ol(cp, THREAD); + + Symbol* klass_name = NULL; + constantTag tag = cp->tag_at(index); + if (tag.is_klass()) { + // The klass has been inserted into the constant pool + // very recently. + return GraalCompiler::get_RiType(cp->resolved_klass_at(index), CHECK_NULL); + } else if (tag.is_symbol()) { + klass_name = cp->symbol_at(index); + } else { + assert(cp->tag_at(index).is_unresolved_klass(), "wrong tag"); + klass_name = cp->unresolved_klass_at(index); + } + return GraalCompiler::get_RiType(klass_name, CHECK_NULL); + } else { + return GraalCompiler::get_RiType(klass, CHECK_NULL); + } +} + +Handle GraalCompiler::get_RiType(KlassHandle klass, TRAPS) { Handle name = VmIds::toString(klass->name(), THREAD); return createHotSpotTypeResolved(klass, name, CHECK_NULL); } - oop GraalCompiler::get_RiType(ciType *type, KlassHandle accessor, TRAPS) { - if (type->is_loaded()) { - if (type->is_primitive_type()) { - return VMExits::createRiTypePrimitive((int) type->basic_type(), THREAD); - } - KlassHandle klass = (klassOop) type->get_oop(); - Handle name = VmIds::toString(klass->name(), THREAD); - return createHotSpotTypeResolved(klass, name, CHECK_NULL); - } else { - Symbol* name = ((ciKlass *) type)->name()->get_symbol(); - return VMExits::createRiTypeUnresolved(VmIds::toString(name, THREAD), THREAD); - } +Handle GraalCompiler::get_RiField(int offset, int flags, Symbol* field_name, Handle field_holder, Handle field_type, Bytecodes::Code byteCode, TRAPS) { + Handle name = VmIds::toString(field_name, CHECK_NULL); + return VMExits::createRiField(field_holder, name, field_type, offset, flags, CHECK_NULL); } -oop GraalCompiler::get_RiField(ciField *field, ciInstanceKlass* accessor_klass, KlassHandle accessor, Bytecodes::Code byteCode, TRAPS) { - int offset; - if (byteCode != Bytecodes::_illegal) { - bool will_link = field->will_link_from_vm(accessor_klass, byteCode); - offset = (field->holder()->is_loaded() && will_link) ? field->offset() : -1; - } else { - offset = field->offset(); - } - Handle field_name = VmIds::toString(field->name()->get_symbol(), CHECK_0); - Handle field_holder = get_RiType(field->holder(), accessor, CHECK_0); - Handle field_type = get_RiType(field->type(), accessor, CHECK_0); - int flags = field->flags().as_int(); - return VMExits::createRiField(field_holder, field_name, field_type, offset, flags, THREAD); -} - -oop GraalCompiler::createHotSpotTypeResolved(KlassHandle klass, Handle name, TRAPS) { +Handle GraalCompiler::createHotSpotTypeResolved(KlassHandle klass, Handle name, TRAPS) { if (klass->graal_mirror() != NULL) { return klass->graal_mirror(); } @@ -177,6 +211,7 @@ HotSpotTypeResolved::set_compiler(obj, VMExits::compilerInstance()()); if (klass->oop_is_instance()) { + ResourceMark rm; instanceKlass* ik = (instanceKlass*)klass()->klass_part(); Handle full_name = java_lang_String::create_from_str(ik->signature_name(), CHECK_NULL); HotSpotType::set_name(obj, full_name()); @@ -204,10 +239,10 @@ klass->set_graal_mirror(obj()); - return obj(); + return obj; } -oop GraalCompiler::createHotSpotMethodResolved(methodHandle method, TRAPS) { +Handle GraalCompiler::createHotSpotMethodResolved(methodHandle method, TRAPS) { if (method->graal_mirror() != NULL) { assert(method->graal_mirror()->is_a(HotSpotMethodResolved::klass()), "unexpected class..."); return method->graal_mirror(); @@ -227,8 +262,8 @@ KlassHandle klass = method->method_holder(); Handle holder_name = VmIds::toString(klass->name(), CHECK_NULL); - oop holder = GraalCompiler::createHotSpotTypeResolved(klass, holder_name, CHECK_NULL); - HotSpotMethodResolved::set_holder(obj, holder); + Handle holder = GraalCompiler::createHotSpotTypeResolved(klass, holder_name, CHECK_NULL); + HotSpotMethodResolved::set_holder(obj, holder()); HotSpotMethodResolved::set_codeSize(obj, method->code_size()); HotSpotMethodResolved::set_accessFlags(obj, method->access_flags().as_int()); diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/graal/graalCompiler.hpp --- a/src/share/vm/graal/graalCompiler.hpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/graal/graalCompiler.hpp Fri Nov 18 13:34:10 2011 +0100 @@ -54,15 +54,19 @@ // Compilation entry point for methods virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci); + void compile_method(methodHandle target, int entry_bci, jboolean blocking); + // Print compilation timers and statistics virtual void print_timers(); + + static Handle get_RiTypeFromSignature(constantPoolHandle cp, int index, KlassHandle accessor, TRAPS); + static Handle get_RiType(constantPoolHandle cp, int index, KlassHandle accessor, TRAPS); + static Handle get_RiType(Symbol* klass_name, TRAPS); + static Handle get_RiType(KlassHandle klass, TRAPS); + static Handle get_RiField(int offset, int flags, Symbol* field_name, Handle field_holder, Handle field_type, Bytecodes::Code byteCode, TRAPS); - static oop get_RiType(KlassHandle klass, KlassHandle accessor, TRAPS); - static oop get_RiType(ciType *klass, KlassHandle accessor, TRAPS); - static oop get_RiField(ciField *ciField, ciInstanceKlass* accessor_klass, KlassHandle accessor, Bytecodes::Code byteCode, TRAPS); - - static oop createHotSpotTypeResolved(KlassHandle klass, Handle name, TRAPS); - static oop createHotSpotMethodResolved(methodHandle method, TRAPS); + static Handle createHotSpotTypeResolved(KlassHandle klass, Handle name, TRAPS); + static Handle createHotSpotMethodResolved(methodHandle method, TRAPS); void exit(); diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/graal/graalEnv.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalEnv.cpp Fri Nov 18 13:34:10 2011 +0100 @@ -0,0 +1,560 @@ +/* + * Copyright (c) 1999, 2011, 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/graalEnv.hpp" +#include "classfile/systemDictionary.hpp" +#include "classfile/vmSymbols.hpp" +#include "code/scopeDesc.hpp" +#include "compiler/compileBroker.hpp" +#include "compiler/compileLog.hpp" +#include "compiler/compilerOracle.hpp" +#include "interpreter/linkResolver.hpp" +#include "memory/allocation.inline.hpp" +#include "memory/oopFactory.hpp" +#include "memory/universe.inline.hpp" +#include "oops/methodDataOop.hpp" +#include "oops/objArrayKlass.hpp" +#include "prims/jvmtiExport.hpp" +#include "prims/methodHandleWalk.hpp" +#include "runtime/init.hpp" +#include "runtime/reflection.hpp" +#include "runtime/sharedRuntime.hpp" +#include "utilities/dtrace.hpp" +#include "c1/c1_Runtime1.hpp" + +// ------------------------------------------------------------------ +// ciEnv::check_klass_accessiblity +// +// Note: the logic of this method should mirror the logic of +// constantPoolOopDesc::verify_constant_pool_resolve. +bool GraalEnv::check_klass_accessibility(KlassHandle accessing_klass, KlassHandle resolved_klass) { + if (accessing_klass->oop_is_objArray()) { + accessing_klass = objArrayKlass::cast(accessing_klass())->bottom_klass(); + } + if (!accessing_klass->oop_is_instance()) { + return true; + } + + if (resolved_klass->oop_is_objArray()) { + // Find the element klass, if this is an array. + resolved_klass = objArrayKlass::cast(resolved_klass())->bottom_klass(); + } + if (resolved_klass->oop_is_instance()) { + return Reflection::verify_class_access(accessing_klass(), resolved_klass(), true); + } + return true; +} + +// ------------------------------------------------------------------ +// ciEnv::get_klass_by_name_impl +KlassHandle GraalEnv::get_klass_by_name_impl(KlassHandle accessing_klass, + constantPoolHandle cpool, + Symbol* sym, + bool require_local) { + EXCEPTION_CONTEXT; + + // Now we need to check the SystemDictionary + if (sym->byte_at(0) == 'L' && + sym->byte_at(sym->utf8_length()-1) == ';') { + // This is a name from a signature. Strip off the trimmings. + // Call recursive to keep scope of strippedsym. + TempNewSymbol strippedsym = SymbolTable::new_symbol(sym->as_utf8()+1, + sym->utf8_length()-2, + CHECK_(KlassHandle())); + return get_klass_by_name_impl(accessing_klass, cpool, strippedsym, require_local); + } + + Handle loader(THREAD, (oop)NULL); + Handle domain(THREAD, (oop)NULL); + if (!accessing_klass.is_null()) { + loader = Handle(THREAD, accessing_klass->class_loader()); + domain = Handle(THREAD, accessing_klass->protection_domain()); + } + + KlassHandle found_klass; + { + ttyUnlocker ttyul; // release tty lock to avoid ordering problems + MutexLocker ml(Compile_lock); + klassOop kls; + if (!require_local) { + kls = SystemDictionary::find_constrained_instance_or_array_klass(sym, loader, CHECK_(KlassHandle())); + } else { + kls = SystemDictionary::find_instance_or_array_klass(sym, loader, domain, CHECK_(KlassHandle())); + } + found_klass = KlassHandle(THREAD, kls); + } + + // If we fail to find an array klass, look again for its element type. + // The element type may be available either locally or via constraints. + // In either case, if we can find the element type in the system dictionary, + // we must build an array type around it. The CI requires array klasses + // to be loaded if their element klasses are loaded, except when memory + // is exhausted. + if (sym->byte_at(0) == '[' && + (sym->byte_at(1) == '[' || sym->byte_at(1) == 'L')) { + // We have an unloaded array. + // Build it on the fly if the element class exists. + TempNewSymbol elem_sym = SymbolTable::new_symbol(sym->as_utf8()+1, + sym->utf8_length()-1, + CHECK_(KlassHandle())); + + // Get element ciKlass recursively. + KlassHandle elem_klass = + get_klass_by_name_impl(accessing_klass, + cpool, + elem_sym, + require_local); + if (!elem_klass.is_null()) { + // Now make an array for it + return elem_klass->array_klass(CHECK_(KlassHandle())); + } + } + + if (found_klass.is_null() && !cpool.is_null() && cpool->has_preresolution()) { + // Look inside the constant pool for pre-resolved class entries. + for (int i = cpool->length() - 1; i >= 1; i--) { + if (cpool->tag_at(i).is_klass()) { + klassOop kls = cpool->resolved_klass_at(i); + if (Klass::cast(kls)->name() == sym) { + return kls; + } + } + } + } + + return found_klass(); +} + +// ------------------------------------------------------------------ +// ciEnv::get_klass_by_name +KlassHandle GraalEnv::get_klass_by_name(KlassHandle accessing_klass, + Symbol* klass_name, + bool require_local) { + ResourceMark rm; + return get_klass_by_name_impl(accessing_klass, + constantPoolHandle(), + klass_name, + require_local); +} + +// ------------------------------------------------------------------ +// ciEnv::get_klass_by_index_impl +// +// Implementation of get_klass_by_index. +KlassHandle GraalEnv::get_klass_by_index_impl(constantPoolHandle cpool, + int index, + bool& is_accessible, + KlassHandle accessor) { + EXCEPTION_CONTEXT; + KlassHandle klass (THREAD, constantPoolOopDesc::klass_at_if_loaded(cpool, index)); + Symbol* klass_name = NULL; + if (klass.is_null()) { + // The klass has not been inserted into the constant pool. + // Try to look it up by name. + { + // We have to lock the cpool to keep the oop from being resolved + // while we are accessing it. + ObjectLocker ol(cpool, THREAD); + + constantTag tag = cpool->tag_at(index); + if (tag.is_klass()) { + // The klass has been inserted into the constant pool + // very recently. + klass = KlassHandle(THREAD, cpool->resolved_klass_at(index)); + } else if (tag.is_symbol()) { + klass_name = cpool->symbol_at(index); + } else { + assert(cpool->tag_at(index).is_unresolved_klass(), "wrong tag"); + klass_name = cpool->unresolved_klass_at(index); + } + } + } + + if (klass.is_null()) { + // Not found in constant pool. Use the name to do the lookup. + KlassHandle k = get_klass_by_name_impl(accessor, + cpool, + klass_name, + false); + // Calculate accessibility the hard way. + if (k.is_null()) { + is_accessible = false; + } else if (k->class_loader() != accessor->class_loader() && + get_klass_by_name_impl(accessor, cpool, k->name(), true) == NULL) { + // Loaded only remotely. Not linked yet. + is_accessible = false; + } else { + // Linked locally, and we must also check public/private, etc. + is_accessible = check_klass_accessibility(accessor(), k()); + } + return k; + } + + // It is known to be accessible, since it was found in the constant pool. + is_accessible = true; + return klass; +} + +// ------------------------------------------------------------------ +// ciEnv::get_klass_by_index +// +// Get a klass from the constant pool. +KlassHandle GraalEnv::get_klass_by_index(constantPoolHandle cpool, + int index, + bool& is_accessible, + KlassHandle accessor) { + ResourceMark rm; + return get_klass_by_index_impl(cpool, index, is_accessible, accessor); +} + +// ------------------------------------------------------------------ +// ciEnv::get_field_by_index_impl +// +// Implementation of get_field_by_index. +// +// Implementation note: the results of field lookups are cached +// in the accessor klass. +void GraalEnv::get_field_by_index_impl(instanceKlassHandle klass, fieldDescriptor& field_desc, + int index) { + EXCEPTION_CONTEXT; + + assert(klass->is_linked(), "must be linked before using its constan-pool"); + + constantPoolHandle cpool(thread, klass->constants()); + + // Get the field's name, signature, and type. + Symbol* name = cpool->name_ref_at(index); + + int nt_index = cpool->name_and_type_ref_index_at(index); + int sig_index = cpool->signature_ref_index_at(nt_index); + Symbol* signature = cpool->symbol_at(sig_index); + + // Get the field's declared holder. + // + // Note: we actually create a ciInstanceKlass for this klass, + // even though we may not need to. + int holder_index = cpool->klass_ref_index_at(index); + bool holder_is_accessible; + KlassHandle declared_holder = get_klass_by_index(cpool, holder_index, + holder_is_accessible, + klass); + + // The declared holder of this field may not have been loaded. + // Bail out with partial field information. + if (!holder_is_accessible) { + return; + } + + + // Perform the field lookup. + klassOop canonical_holder = + instanceKlass::cast(declared_holder())->find_field(name, signature, &field_desc); + if (canonical_holder == NULL) { + return; + } + + assert(canonical_holder == field_desc.field_holder(), "just checking"); +} + +// ------------------------------------------------------------------ +// ciEnv::get_field_by_index +// +// Get a field by index from a klass's constant pool. +void GraalEnv::get_field_by_index(instanceKlassHandle accessor, fieldDescriptor& fd, + int index) { + ResourceMark rm; + return get_field_by_index_impl(accessor, fd, index); +} + +// ------------------------------------------------------------------ +// ciEnv::lookup_method +// +// Perform an appropriate method lookup based on accessor, holder, +// name, signature, and bytecode. +methodHandle GraalEnv::lookup_method(instanceKlassHandle h_accessor, + instanceKlassHandle h_holder, + Symbol* name, + Symbol* sig, + Bytecodes::Code bc) { + EXCEPTION_CONTEXT; + LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL)); + methodHandle dest_method; + switch (bc) { + case Bytecodes::_invokestatic: + dest_method = + LinkResolver::resolve_static_call_or_null(h_holder, name, sig, h_accessor); + break; + case Bytecodes::_invokespecial: + dest_method = + LinkResolver::resolve_special_call_or_null(h_holder, name, sig, h_accessor); + break; + case Bytecodes::_invokeinterface: + dest_method = + LinkResolver::linktime_resolve_interface_method_or_null(h_holder, name, sig, + h_accessor, true); + break; + case Bytecodes::_invokevirtual: + dest_method = + LinkResolver::linktime_resolve_virtual_method_or_null(h_holder, name, sig, + h_accessor, true); + break; + default: ShouldNotReachHere(); + } + + return dest_method; +} + + +// ------------------------------------------------------------------ +// ciEnv::get_method_by_index_impl +methodHandle GraalEnv::get_method_by_index_impl(constantPoolHandle cpool, + int index, Bytecodes::Code bc, + instanceKlassHandle accessor) { + int holder_index = cpool->klass_ref_index_at(index); + bool holder_is_accessible; + KlassHandle holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor); + + // Get the method's name and signature. + Symbol* name_sym = cpool->name_ref_at(index); + Symbol* sig_sym = cpool->signature_ref_at(index); + + if (holder_is_accessible) { // Our declared holder is loaded. + instanceKlassHandle lookup = get_instance_klass_for_declared_method_holder(holder); + methodHandle m = lookup_method(accessor, lookup, name_sym, sig_sym, bc); + if (!m.is_null() && + (bc == Bytecodes::_invokestatic + ? instanceKlass::cast(m->method_holder())->is_not_initialized() + : !instanceKlass::cast(m->method_holder())->is_loaded())) { + m = NULL; + } + if (!m.is_null()) { + // We found the method. + return m; + } + } + + // Either the declared holder was not loaded, or the method could + // not be found. Create a dummy ciMethod to represent the failed + // lookup. + + return NULL; +} + +// ------------------------------------------------------------------ +// ciEnv::get_instance_klass_for_declared_method_holder +instanceKlassHandle GraalEnv::get_instance_klass_for_declared_method_holder(KlassHandle method_holder) { + // For the case of .clone(), the method holder can be a ciArrayKlass + // instead of a ciInstanceKlass. For that case simply pretend that the + // declared holder is Object.clone since that's where the call will bottom out. + // A more correct fix would trickle out through many interfaces in CI, + // requiring ciInstanceKlass* to become ciKlass* and many more places would + // require checks to make sure the expected type was found. Given that this + // only occurs for clone() the more extensive fix seems like overkill so + // instead we simply smear the array type into Object. + if (method_holder->oop_is_instance()) { + return instanceKlassHandle(method_holder()); + } else if (method_holder->oop_is_array()) { + return instanceKlassHandle(SystemDictionary::Object_klass()); + } else { + ShouldNotReachHere(); + } + return NULL; +} + + +// ------------------------------------------------------------------ +// ciEnv::get_method_by_index +methodHandle GraalEnv::get_method_by_index(constantPoolHandle cpool, + int index, Bytecodes::Code bc, + instanceKlassHandle accessor) { + ResourceMark rm; + assert(bc != Bytecodes::_invokedynamic, "invokedynamic not yet supported"); + return get_method_by_index_impl(cpool, index, bc, accessor); +} + +// ------------------------------------------------------------------ +// ciEnv::check_for_system_dictionary_modification +// Check for changes to the system dictionary during compilation +// class loads, evolution, breakpoints +bool GraalEnv::check_for_system_dictionary_modification(Dependencies* dependencies) { + // Dependencies must be checked when the system dictionary changes. + // If logging is enabled all violated dependences will be recorded in + // the log. In debug mode check dependencies even if the system + // dictionary hasn't changed to verify that no invalid dependencies + // were inserted. Any violated dependences in this case are dumped to + // the tty. + + // TODO (tw): Always check dependency for now. + //bool counter_changed = system_dictionary_modification_counter_changed(); + //bool test_deps = counter_changed; + //DEBUG_ONLY(test_deps = true); + //if (!test_deps) return; + + for (Dependencies::DepStream deps(dependencies); deps.next(); ) { + klassOop witness = deps.check_dependency(); + if (witness != NULL) { + return false; + } + } + + return true; +} + +// ------------------------------------------------------------------ +// ciEnv::register_method +nmethod* GraalEnv::register_method(methodHandle& method, + int entry_bci, + CodeOffsets* offsets, + int orig_pc_offset, + CodeBuffer* code_buffer, + int frame_words, + OopMapSet* oop_map_set, + ExceptionHandlerTable* handler_table, + ImplicitExceptionTable* inc_table, + AbstractCompiler* compiler, + DebugInformationRecorder* debug_info, + Dependencies* dependencies, + CompileTask* task, + int compile_id, + bool has_debug_info, + bool has_unsafe_access, + bool install_code) { + EXCEPTION_CONTEXT; + nmethod* nm = NULL; + int comp_level = CompLevel_simple; + { + // To prevent compile queue updates. + MutexLocker locker(MethodCompileQueue_lock, THREAD); + + // Prevent SystemDictionary::add_to_hierarchy from running + // and invalidating our dependencies until we install this method. + MutexLocker ml(Compile_lock); + + // Encode the dependencies now, so we can check them right away. + dependencies->encode_content_bytes(); + + // Check for {class loads, evolution, breakpoints} during compilation + if (!check_for_system_dictionary_modification(dependencies)) { + // While not a true deoptimization, it is a preemptive decompile. + methodDataOop mdo = method()->method_data(); + if (mdo != NULL) { + mdo->inc_decompile_count(); + } + + // All buffers in the CodeBuffer are allocated in the CodeCache. + // If the code buffer is created on each compile attempt + // as in C2, then it must be freed. + //code_buffer->free_blob(); + return NULL; + } + + assert(offsets->value(CodeOffsets::Deopt) != -1, "must have deopt entry"); + assert(offsets->value(CodeOffsets::Exceptions) != -1, "must have exception entry"); + + nm = nmethod::new_nmethod(method, + compile_id, + entry_bci, + offsets, + orig_pc_offset, + debug_info, dependencies, code_buffer, + frame_words, oop_map_set, + handler_table, inc_table, + compiler, comp_level); + + // Free codeBlobs + //code_buffer->free_blob(); + + // stress test 6243940 by immediately making the method + // non-entrant behind the system's back. This has serious + // side effects on the code cache and is not meant for + // general stress testing + if (nm != NULL && StressNonEntrant) { + MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag); + NativeJump::patch_verified_entry(nm->entry_point(), nm->verified_entry_point(), + SharedRuntime::get_handle_wrong_method_stub()); + } + + if (nm == NULL) { + // The CodeCache is full. Print out warning and disable compilation. + { + MutexUnlocker ml(Compile_lock); + MutexUnlocker locker(MethodCompileQueue_lock); + CompileBroker::handle_full_code_cache(); + } + } else { + NOT_PRODUCT(nm->set_has_debug_info(has_debug_info); ) + nm->set_has_unsafe_access(has_unsafe_access); + + // Record successful registration. + // (Put nm into the task handle *before* publishing to the Java heap.) + if (task != NULL) task->set_code(nm); + + if (install_code) { + if (entry_bci == InvocationEntryBci) { + if (TieredCompilation) { + // If there is an old version we're done with it + nmethod* old = method->code(); + if (TraceMethodReplacement && old != NULL) { + ResourceMark rm; + char *method_name = method->name_and_sig_as_C_string(); + tty->print_cr("Replacing method %s", method_name); + } + if (old != NULL ) { + old->make_not_entrant(); + } + } + if (TraceNMethodInstalls ) { + ResourceMark rm; + char *method_name = method->name_and_sig_as_C_string(); + ttyLocker ttyl; + tty->print_cr("Installing method (%d) %s ", + comp_level, + method_name); + } + // Allow the code to be executed + method->set_code(method, nm); + } else { + if (TraceNMethodInstalls ) { + ResourceMark rm; + char *method_name = method->name_and_sig_as_C_string(); + ttyLocker ttyl; + tty->print_cr("Installing osr method (%d) %s @ %d", + comp_level, + method_name, + entry_bci); + } + instanceKlass::cast(method->method_holder())->add_osr_nmethod(nm); + + } + } + } + } + // JVMTI -- compiled method notification (must be done outside lock) + if (nm != NULL) { + nm->post_compiled_method_load_event(); + } + + return nm; +} \ No newline at end of file diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/graal/graalEnv.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalEnv.hpp Fri Nov 18 13:34:10 2011 +0100 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 1999, 2011, 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. + * + */ + +#ifndef SHARE_VM_GRAAL_GRAALENV_HPP +#define SHARE_VM_GRAAL_GRAALENV_HPP + +#include "classfile/systemDictionary.hpp" +#include "code/debugInfoRec.hpp" +#include "code/dependencies.hpp" +#include "code/exceptionHandlerTable.hpp" +#include "compiler/oopMap.hpp" +#include "runtime/thread.hpp" + +class CompileTask; + +// ciEnv +// +// This class is the top level broker for requests from the compiler +// to the VM. +class GraalEnv : AllStatic { + CI_PACKAGE_ACCESS_TO + + friend class CompileBroker; + friend class Dependencies; // for get_object, during logging + +public: + + // Look up a klass by name from a particular class loader (the accessor's). + // If require_local, result must be defined in that class loader, or NULL. + // If !require_local, a result from remote class loader may be reported, + // if sufficient class loader constraints exist such that initiating + // a class loading request from the given loader is bound to return + // the class defined in the remote loader (or throw an error). + // + // Return an unloaded klass if !require_local and no class at all is found. + // + // The CI treats a klass as loaded if it is consistently defined in + // another loader, even if it hasn't yet been loaded in all loaders + // that could potentially see it via delegation. + static KlassHandle get_klass_by_name(KlassHandle accessing_klass, + Symbol* klass_name, + bool require_local); + + // Constant pool access. + static KlassHandle get_klass_by_index(constantPoolHandle cpool, + int klass_index, + bool& is_accessible, + KlassHandle loading_klass); + static void get_field_by_index(instanceKlassHandle loading_klass, fieldDescriptor& fd, + int field_index); + static methodHandle get_method_by_index(constantPoolHandle cpool, + int method_index, Bytecodes::Code bc, + instanceKlassHandle loading_klass); + +private: + + // Implementation methods for loading and constant pool access. + static KlassHandle get_klass_by_name_impl(KlassHandle accessing_klass, + constantPoolHandle cpool, + Symbol* klass_name, + bool require_local); + static KlassHandle get_klass_by_index_impl(constantPoolHandle cpool, + int klass_index, + bool& is_accessible, + KlassHandle loading_klass); + static void get_field_by_index_impl(instanceKlassHandle loading_klass, fieldDescriptor& fd, + int field_index); + static methodHandle get_method_by_index_impl(constantPoolHandle cpool, + int method_index, Bytecodes::Code bc, + instanceKlassHandle loading_klass); + + // Helper methods + static bool check_klass_accessibility(KlassHandle accessing_klass, KlassHandle resolved_klassOop); + static methodHandle lookup_method(instanceKlassHandle accessor, + instanceKlassHandle holder, + Symbol* name, + Symbol* sig, + Bytecodes::Code bc); + + private: + + // Is this thread currently in the VM state? + static bool is_in_vm(); + + // Helper routine for determining the validity of a compilation + // with respect to concurrent class loading. + static bool check_for_system_dictionary_modification(Dependencies* target); + +public: + // Register the result of a compilation. + static nmethod* register_method(methodHandle& target, + int entry_bci, + CodeOffsets* offsets, + int orig_pc_offset, + CodeBuffer* code_buffer, + int frame_words, + OopMapSet* oop_map_set, + ExceptionHandlerTable* handler_table, + ImplicitExceptionTable* inc_table, + AbstractCompiler* compiler, + DebugInformationRecorder* debug_info, + Dependencies* dependencies, + CompileTask* task, + int compile_id, + bool has_debug_info = true, + bool has_unsafe_access = false, + bool install_code = true); + + static ciKlass* find_system_klass(ciSymbol* klass_name); + // Note: To find a class from its name string, use ciSymbol::make, + // but consider adding to vmSymbols.hpp instead. + + // converts the ciKlass* representing the holder of a method into a + // ciInstanceKlass*. This is needed since the holder of a method in + // the bytecodes could be an array type. Basically this converts + // array types into java/lang/Object and other types stay as they are. + static instanceKlassHandle get_instance_klass_for_declared_method_holder(KlassHandle klass); +}; + +#endif // SHARE_VM_GRAAL_GRAALENV_HPP diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/graal/graalJavaAccess.hpp Fri Nov 18 13:34:10 2011 +0100 @@ -240,10 +240,10 @@ #define FIELD(name, type, accessor) \ static int _##name##_offset; \ static type name(oop obj) { check(obj); return obj->accessor(_##name##_offset); } \ - static type name(Handle obj) { check(obj()); return obj->accessor(_##name##_offset); } \ + static type name(Handle& obj) { check(obj()); return obj->accessor(_##name##_offset); } \ static type name(jobject obj) { check(JNIHandles::resolve(obj)); return JNIHandles::resolve(obj)->accessor(_##name##_offset); } \ static void set_##name(oop obj, type x) { check(obj); obj->accessor##_put(_##name##_offset, x); } \ - static void set_##name(Handle obj, type x) { check(obj()); obj->accessor##_put(_##name##_offset, x); } \ + static void set_##name(Handle& obj, type x) { check(obj()); obj->accessor##_put(_##name##_offset, x); } \ static void set_##name(jobject obj, type x) { check(JNIHandles::resolve(obj)); JNIHandles::resolve(obj)->accessor##_put(_##name##_offset, x); } #define CHAR_FIELD(klass, name) FIELD(name, jchar, char_field) @@ -267,9 +267,9 @@ instanceKlass* ik = instanceKlass::cast(klassName::klass()); \ address addr = ik->static_field_addr(_##name##_offset - instanceMirrorKlass::offset_of_static_fields()); \ if (UseCompressedOops) { \ - oopDesc::encode_store_heap_oop((narrowOop *)addr, x); \ + oop_store((narrowOop *)addr, x); \ } else { \ - oopDesc::encode_store_heap_oop((oop*)addr, x); \ + oop_store((oop*)addr, x); \ } \ } COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD) diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/graal/graalVMEntries.cpp --- a/src/share/vm/graal/graalVMEntries.cpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/graal/graalVMEntries.cpp Fri Nov 18 13:34:10 2011 +0100 @@ -22,11 +22,13 @@ */ #include "precompiled.hpp" +#include "runtime/fieldDescriptor.hpp" #include "c1/c1_Runtime1.hpp" #include "ci/ciMethodData.hpp" #include "compiler/compileBroker.hpp" #include "graal/graalVMEntries.hpp" #include "graal/graalCompiler.hpp" +#include "graal/graalEnv.hpp" #include "graal/graalJavaAccess.hpp" #include "graal/graalCodeInstaller.hpp" #include "graal/graalVMExits.hpp" @@ -39,41 +41,7 @@ } methodOop getMethodFromHotSpotMethod(oop hotspot_method) { - oop reflected = HotSpotMethodResolved::javaMirror(hotspot_method); - assert(reflected != NULL, "NULL not expected"); - return (methodOop)reflected; - - // (tw) Cannot use reflection code, because then the compiler can dead lock with the user application (test using -Xcomp). - /* - // method is a handle to a java.lang.reflect.Method object - oop mirror = NULL; - int slot = 0; - - if (reflected->klass() == SystemDictionary::reflect_Constructor_klass()) { - mirror = java_lang_reflect_Constructor::clazz(reflected); - slot = java_lang_reflect_Constructor::slot(reflected); - } else { - assert(reflected->klass() == SystemDictionary::reflect_Method_klass(), "wrong type"); - mirror = java_lang_reflect_Method::clazz(reflected); - slot = java_lang_reflect_Method::slot(reflected); - } - klassOop k = java_lang_Class::as_klassOop(mirror); - - // Make sure class is initialized before handing id's out to methods -// assert(instanceKlass::cast(k)->is_initialized(), "only initialized classes expected"); - methodOop m = instanceKlass::cast(k)->method_with_idnum(slot); - assert(m != NULL, "deleted method?"); - return m;*/ -} - -oop getReflectedMethod(methodOop method, TRAPS) { - assert(method != NULL, "NULL not expected"); - - if (!method->is_initializer() || method->is_static()) { - return Reflection::new_method(method, true, true, CHECK_NULL); - } else { - return Reflection::new_constructor(method, CHECK_NULL); - } + return (methodOop)HotSpotMethodResolved::javaMirror(hotspot_method); } // public byte[] RiMethod_code(HotSpotResolvedMethod method); @@ -99,6 +67,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_1exceptionHandlers(JNIEnv *, jobject, jobject hotspot_method) { TRACE_graal_3("VMEntries::RiMethod_exceptionHandlers"); VM_ENTRY_MARK + ResourceMark rm; methodHandle method = getMethodFromHotSpotMethod(hotspot_method); typeArrayHandle handlers = method->exception_table(); int handler_count = handlers.is_null() ? 0 : handlers->length() / 4; @@ -120,12 +89,9 @@ HotSpotExceptionHandler::set_catchClass(entry, NULL); } else { constantPoolOop cp = instanceKlass::cast(method->method_holder())->constants(); - ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(method->method_holder()); - bool is_accessible = false; - ciKlass *klass = CURRENT_ENV->get_klass_by_index(cp, catch_class_index, is_accessible, loading_klass); - oop catch_class = GraalCompiler::get_RiType(klass, method->method_holder(), CHECK_NULL); - - HotSpotExceptionHandler::set_catchClass(entry, catch_class); + KlassHandle loading_klass = method->method_holder(); + Handle catch_class = GraalCompiler::get_RiType(cp, catch_class_index, loading_klass, CHECK_NULL); + HotSpotExceptionHandler::set_catchClass(entry, catch_class()); } array->obj_at_put(i, entry()); } @@ -170,8 +136,8 @@ int slot = java_lang_reflect_Method::slot(reflection_method); klassOop holder = java_lang_Class::as_klassOop(reflection_holder); methodOop method = instanceKlass::cast(holder)->method_with_idnum(slot); - oop ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); - return JNIHandles::make_local(THREAD, ret); + Handle ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); + return JNIHandles::make_local(THREAD, ret()); } // public boolean RiMethod_uniqueConcreteMethod(long vmId); @@ -179,9 +145,9 @@ TRACE_graal_3("VMEntries::RiMethod_uniqueConcreteMethod"); VM_ENTRY_MARK; - methodOop method = getMethodFromHotSpotMethod(hotspot_method); - klassOop holder = method->method_holder(); - if (holder->klass_part()->is_interface()) { + methodHandle method = getMethodFromHotSpotMethod(hotspot_method); + KlassHandle holder = method->method_holder(); + if (holder->is_interface()) { // Cannot trust interfaces. Because of: // interface I { void foo(); } // class A { public void foo() {} } @@ -191,47 +157,45 @@ // Would lead to identify C.foo() as the unique concrete method for I.foo() without seeing A.foo(). return false; } - methodOop unique_concrete; + methodHandle unique_concrete; { ResourceMark rm; MutexLocker locker(Compile_lock); - unique_concrete = Dependencies::find_unique_concrete_method(holder, method); + unique_concrete = Dependencies::find_unique_concrete_method(holder(), method()); } - if (unique_concrete == NULL) { + if (unique_concrete.is_null()) { return NULL; } else { - oop method_resolved = GraalCompiler::createHotSpotMethodResolved(unique_concrete, CHECK_NULL); - return JNIHandles::make_local(THREAD, method_resolved); + Handle method_resolved = GraalCompiler::createHotSpotMethodResolved(unique_concrete, CHECK_NULL); + return JNIHandles::make_local(THREAD, method_resolved()); } } // public native int RiMethod_invocationCount(long vmId); JNIEXPORT jint JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_1invocationCount(JNIEnv *, jobject, jobject hotspot_method) { TRACE_graal_3("VMEntries::RiMethod_invocationCount"); - methodOop method = getMethodFromHotSpotMethod(hotspot_method); - return method->invocation_count(); + return getMethodFromHotSpotMethod(hotspot_method)->invocation_count(); } // public native int RiMethod_exceptionProbability(long vmId, int bci); JNIEXPORT jint JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_2exceptionProbability(JNIEnv *, jobject, jobject hotspot_method, jint bci) { TRACE_graal_3("VMEntries::RiMethod_exceptionProbability"); - { - VM_ENTRY_MARK; - methodOop method = getMethodFromHotSpotMethod(hotspot_method); - methodDataOop method_data = method->method_data(); - if (method_data == NULL || !method_data->is_mature()) { - return -1; - } - ProfileData* data = method_data->bci_to_data(bci); - if (data == NULL) { - return 0; - } - uint trap = Deoptimization::trap_state_is_recompiled(data->trap_state())? 1: 0; - if (trap > 0) { - return 100; - } else { - return trap; - } + VM_ENTRY_MARK; + ResourceMark rm; + methodHandle method = getMethodFromHotSpotMethod(hotspot_method); + methodDataHandle method_data = method->method_data(); + if (method_data == NULL || !method_data->is_mature()) { + return -1; + } + ProfileData* data = method_data->bci_to_data(bci); + if (data == NULL) { + return 0; + } + uint trap = Deoptimization::trap_state_is_recompiled(data->trap_state())? 1: 0; + if (trap > 0) { + return 100; + } else { + return trap; } } @@ -264,93 +228,73 @@ // public native RiTypeProfile RiMethod_typeProfile(long vmId, int bci); JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_2typeProfile(JNIEnv *, jobject, jobject hotspot_method, jint bci) { TRACE_graal_3("VMEntries::RiMethod_typeProfile"); + VM_ENTRY_MARK; Handle obj; - { - VM_ENTRY_MARK; - methodHandle method = getMethodFromHotSpotMethod(hotspot_method); - if (strstr(method->name_and_sig_as_C_string(), "factor") != NULL) { -// tty->print_cr("here"); - } - if (bci == 123) { -// tty->print_cr("here2"); + + methodHandle method = getMethodFromHotSpotMethod(hotspot_method); + methodDataHandle method_data = method->method_data(); + if (method_data == NULL || !method_data->is_mature()) { + return NULL; + } + ResourceMark rm; + ProfileData* data = method_data->bci_to_data(bci); + if (data != NULL && data->is_ReceiverTypeData()) { + ReceiverTypeData* recv = data->as_ReceiverTypeData(); + GrowableArray receivers; + GrowableArray counts; + // determine morphism + uint total_count = 0; + for (uint i = 0; i < recv->row_limit(); i++) { + klassOop receiver = recv->receiver(i); + if (receiver == NULL) continue; + uint count = recv->receiver_count(i); + total_count += count; + receivers.append(receiver); + counts.append(count); } - methodDataHandle method_data = method->method_data(); - if (method_data == NULL || !method_data->is_mature()) { - return NULL; - } - ProfileData* data = method_data->bci_to_data(bci); - if (data != NULL && data->is_ReceiverTypeData()) { - ReceiverTypeData* recv = data->as_ReceiverTypeData(); - // determine morphism - int morphism = 0; - uint total_count = 0; - for (uint i = 0; i < recv->row_limit(); i++) { - klassOop receiver = recv->receiver(i); - if (receiver == NULL) continue; - morphism++; - total_count += recv->receiver_count(i); + + instanceKlass::cast(RiTypeProfile::klass())->initialize(CHECK_NULL); + obj = instanceKlass::cast(RiTypeProfile::klass())->allocate_instance(CHECK_NULL); + assert(obj() != NULL, "must succeed in allocating instance"); + + int count = MAX2(total_count, recv->count()); + RiTypeProfile::set_count(obj, scale_count(method_data(), count)); + RiTypeProfile::set_morphism(obj, receivers.length()); + + if (receivers.length() > 0) { + typeArrayHandle probabilities = oopFactory::new_typeArray(T_FLOAT, receivers.length(), CHECK_NULL); + objArrayHandle types = oopFactory::new_objArray(SystemDictionary::RiType_klass(), receivers.length(), CHECK_NULL); + for (int i = 0; i < receivers.length(); i++) { + KlassHandle receiver = receivers.at(i); + + float prob = counts.at(i) / (float) total_count; + Handle type = GraalCompiler::get_RiType(receiver, CHECK_NULL); + + probabilities->float_at_put(i, prob); + types->obj_at_put(i, type()); + } - instanceKlass::cast(RiTypeProfile::klass())->initialize(CHECK_NULL); - obj = instanceKlass::cast(RiTypeProfile::klass())->allocate_instance(CHECK_NULL); - assert(obj() != NULL, "must succeed in allocating instance"); - - int count = MAX2(total_count, recv->count()); - RiTypeProfile::set_count(obj, scale_count(method_data(), count)); - RiTypeProfile::set_morphism(obj, morphism); - - if (morphism > 0) { - typeArrayHandle probabilities = oopFactory::new_typeArray(T_FLOAT, morphism, CHECK_NULL); - objArrayHandle types = oopFactory::new_objArray(SystemDictionary::RiType_klass(), morphism, CHECK_NULL); - int pos = 0; - for (uint i = 0; i < recv->row_limit(); i++) { - KlassHandle receiver = recv->receiver(i); - if (receiver.is_null()) continue; - - float prob = recv->receiver_count(i) / (float) total_count; - oop type = GraalCompiler::get_RiType(receiver, KlassHandle(), CHECK_NULL); - - probabilities->float_at_put(pos, prob); - types->obj_at_put(pos, type); - - pos++; - } - - RiTypeProfile::set_probabilities(obj, probabilities()); - RiTypeProfile::set_types(obj, types()); - } else { - RiTypeProfile::set_probabilities(obj, NULL); - RiTypeProfile::set_types(obj, NULL); - } + RiTypeProfile::set_probabilities(obj, probabilities()); + RiTypeProfile::set_types(obj, types()); + } else { + RiTypeProfile::set_probabilities(obj, NULL); + RiTypeProfile::set_types(obj, NULL); } } - return JNIHandles::make_local(obj()); } JNIEXPORT jdouble JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_2branchProbability(JNIEnv *, jobject, jobject hotspot_method, jint bci) { TRACE_graal_3("VMEntries::RiMethod_typeProfile"); - ciMethodData* method_data; - ciMethod* cimethod; - { - VM_ENTRY_MARK; - assert(hotspot_method != NULL, "must not be null"); - methodOop method = getMethodFromHotSpotMethod(hotspot_method); - assert(method != NULL, "method not found"); - if (CURRENT_ENV == NULL) { - return -1; - } - assert(CURRENT_ENV != NULL, "current environment must be present"); - cimethod = (ciMethod*)CURRENT_ENV->get_object(method); - } - assert(cimethod != NULL, "cimethod not found"); - method_data = cimethod->method_data(); - - jfloat probability = -1; + ResourceMark rm; + methodHandle method = getMethodFromHotSpotMethod(hotspot_method); + methodDataHandle method_data = method->method_data(); if (method_data == NULL || !method_data->is_mature()) return -1; - - ciProfileData* data = method_data->bci_to_data(bci); + method_data->bci_to_data(bci); + + ProfileData* data = method_data->bci_to_data(bci); if (data == NULL || !data->is_JumpData()) return -1; // get taken and not taken values @@ -376,20 +320,14 @@ JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_2switchProbability(JNIEnv *, jobject, jobject hotspot_method, jint bci) { TRACE_graal_3("VMEntries::RiMethod_typeProfile"); - ciMethodData* method_data; - ciMethod* cimethod; - { - VM_ENTRY_MARK; - methodOop method = getMethodFromHotSpotMethod(hotspot_method); - cimethod = (ciMethod*)CURRENT_ENV->get_object(method); - } - method_data = cimethod->method_data(); - - jfloat probability = -1; + VM_ENTRY_MARK; + ResourceMark rm; + methodHandle method = getMethodFromHotSpotMethod(hotspot_method); + methodDataHandle method_data = method->method_data(); if (method_data == NULL || !method_data->is_mature()) return NULL; - ciProfileData* data = method_data->bci_to_data(bci); + ProfileData* data = method_data->bci_to_data(bci); if (data == NULL || !data->is_MultiBranchData()) return NULL; MultiBranchData* branch_data = data->as_MultiBranchData(); @@ -411,27 +349,24 @@ // We also check that individual counters are positive first, otherwise the sum can become positive. if (sum < 10 * (cases + 3)) return NULL; - { - VM_ENTRY_MARK; - typeArrayOop probability = oopFactory::new_typeArray(T_DOUBLE, cases + 1, CHECK_NULL); - for (int i = 0; i < cases + 1; i++) { - probability->double_at_put(i, counts->at(i) / (double) sum); - } - return JNIHandles::make_local(probability); + typeArrayOop probability = oopFactory::new_typeArray(T_DOUBLE, cases + 1, CHECK_NULL); + for (int i = 0; i < cases + 1; i++) { + probability->double_at_put(i, counts->at(i) / (double) sum); } + return JNIHandles::make_local(probability); } // public native boolean RiMethod_hasCompiledCode(HotSpotMethodResolved method); JNIEXPORT jboolean JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_1hasCompiledCode(JNIEnv *, jobject, jobject hotspot_method) { TRACE_graal_3("VMEntries::RiMethod_hasCompiledCode"); - methodOop method = getMethodFromHotSpotMethod(hotspot_method); - return method->has_compiled_code(); + return getMethodFromHotSpotMethod(hotspot_method)->has_compiled_code(); } // public RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass); JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiSignature_1lookupType(JNIEnv *env, jobject, jstring jname, jobject accessingClass) { TRACE_graal_3("VMEntries::RiSignature_lookupType"); VM_ENTRY_MARK; + ResourceMark rm; Symbol* nameSymbol = VmIds::toSymbol(jname); Handle name = JNIHandles::resolve(jname); @@ -470,9 +405,11 @@ } } if (resolved_type != NULL) { - result = GraalCompiler::createHotSpotTypeResolved(resolved_type, name, CHECK_NULL); + Handle type = GraalCompiler::createHotSpotTypeResolved(resolved_type, name, CHECK_NULL); + result = type(); } else { - result = VMExits::createRiTypeUnresolved(name, THREAD); + Handle type = VMExits::createRiTypeUnresolved(name, THREAD); + result = type(); } } @@ -511,10 +448,8 @@ } result = VMExits::createCiConstantObject(string, CHECK_0); } else if (tag.is_klass() || tag.is_unresolved_klass()) { - bool ignore; - ciInstanceKlass* accessor = (ciInstanceKlass*) ciEnv::current()->get_object(cp->pool_holder()); - ciKlass* klass = ciEnv::current()->get_klass_by_index(cp, index, ignore, accessor); - result = GraalCompiler::get_RiType(klass, cp->pool_holder(), CHECK_NULL); + Handle type = GraalCompiler::get_RiType(cp, index, cp->pool_holder(), CHECK_NULL); + result = type(); } else if (tag.is_object()) { oop obj = cp->object_at(index); assert(obj->is_instance(), "must be an instance"); @@ -531,20 +466,20 @@ TRACE_graal_3("VMEntries::RiConstantPool_lookupMethod"); VM_ENTRY_MARK; index = GraalCompiler::to_cp_index_u2(index); - constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants(); + constantPoolHandle cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants(); Bytecodes::Code bc = (Bytecodes::Code) (((int) byteCode) & 0xFF); - ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(cp->pool_holder()); - ciMethod *cimethod = CURRENT_ENV->get_method_by_index(cp, index, bc, loading_klass); - if (cimethod->is_loaded()) { - methodOop method = (methodOop) cimethod->get_oop(); - oop ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); - return JNIHandles::make_local(THREAD, ret); + methodHandle method = GraalEnv::get_method_by_index(cp, index, bc, cp->pool_holder()); + if (!method.is_null()) { + Handle ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); + return JNIHandles::make_local(THREAD, ret()); } else { - Handle name = VmIds::toString(cimethod->name()->get_symbol(), CHECK_NULL); - Handle signature = VmIds::toString(cimethod->signature()->as_symbol()->get_symbol(), CHECK_NULL); - Handle holder = GraalCompiler::get_RiType(cimethod->holder(), cp->klass(), THREAD); - return JNIHandles::make_local(THREAD, VMExits::createRiMethodUnresolved(name, signature, holder, THREAD)); + // Get the method's name and signature. + Handle name = VmIds::toString(cp->name_ref_at(index), CHECK_NULL); + Handle signature = VmIds::toString(cp->signature_ref_at(index), CHECK_NULL); + int holder_index = cp->klass_ref_index_at(index); + Handle type = GraalCompiler::get_RiType(cp, holder_index, cp->pool_holder(), CHECK_NULL); + return JNIHandles::make_local(THREAD, VMExits::createRiMethodUnresolved(name, signature, type, THREAD)); } } @@ -554,11 +489,8 @@ VM_ENTRY_MARK; constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants(); - - ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(cp->pool_holder()); - bool is_accessible = false; - ciKlass *klass = CURRENT_ENV->get_klass_by_index(cp, index, is_accessible, loading_klass); - return JNIHandles::make_local(THREAD, GraalCompiler::get_RiType(klass, cp->klass(), THREAD)); + Handle result = GraalCompiler::get_RiType(cp, index, cp->pool_holder(), CHECK_NULL); + return JNIHandles::make_local(THREAD, result()); } // public void RiConstantPool_loadReferencedType(long vmId, int cpi); @@ -586,66 +518,110 @@ } // public RiField RiConstantPool_lookupField(long vmId, int cpi); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiConstantPool_1lookupField(JNIEnv *env, jobject, jobject type, jint index, jbyte byteCode) { +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiConstantPool_1lookupField(JNIEnv *env, jobject, jobject constantPoolHolder, jint index, jbyte byteCode) { TRACE_graal_3("VMEntries::RiConstantPool_lookupField"); VM_ENTRY_MARK; + ResourceMark rm; index = GraalCompiler::to_cp_index_u2(index); - constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants(); + constantPoolHandle cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(constantPoolHolder)))->constants(); - ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(cp->pool_holder()); - ciField *field = CURRENT_ENV->get_field_by_index(loading_klass, index); + int nt_index = cp->name_and_type_ref_index_at(index); + int sig_index = cp->signature_ref_index_at(nt_index); + Symbol* signature = cp->symbol_at(sig_index); + int name_index = cp->name_ref_index_at(nt_index); + Symbol* name = cp->symbol_at(name_index); + int holder_index = cp->klass_ref_index_at(index); + Handle holder = GraalCompiler::get_RiType(cp, holder_index, cp->pool_holder(), CHECK_NULL); + instanceKlassHandle holder_klass; Bytecodes::Code code = (Bytecodes::Code)(((int) byteCode) & 0xFF); - Handle field_handle = GraalCompiler::get_RiField(field, loading_klass, cp->pool_holder(), code, THREAD); - bool is_constant = field->is_constant(); - if (is_constant && field->is_static()) { - ciConstant constant = field->constant_value(); - oop constant_object = NULL; - switch (constant.basic_type()) { - case T_OBJECT: - case T_ARRAY: - { - ciObject* obj = constant.as_object(); - if (obj->is_null_object()) { - constant_object = VMExits::createCiConstantObject(NULL, CHECK_0); - } else if (obj->can_be_constant()) { - constant_object = VMExits::createCiConstantObject(constant.as_object()->get_oop(), CHECK_0); - } - } - break; - case T_DOUBLE: - constant_object = VMExits::createCiConstantDouble(constant.as_double(), CHECK_0); - break; - case T_FLOAT: - constant_object = VMExits::createCiConstantFloat(constant.as_float(), CHECK_0); - break; - case T_LONG: - constant_object = VMExits::createCiConstant(CiKind::Long(), constant.as_long(), CHECK_0); - break; - case T_INT: - constant_object = VMExits::createCiConstant(CiKind::Int(), constant.as_int(), CHECK_0); - break; - case T_SHORT: - constant_object = VMExits::createCiConstant(CiKind::Short(), constant.as_int(), CHECK_0); - break; - case T_CHAR: - constant_object = VMExits::createCiConstant(CiKind::Char(), constant.as_int(), CHECK_0); - break; - case T_BYTE: - constant_object = VMExits::createCiConstant(CiKind::Byte(), constant.as_int(), CHECK_0); - break; - case T_BOOLEAN: - constant_object = VMExits::createCiConstant(CiKind::Boolean(), constant.as_int(), CHECK_0); - break; - default: - constant.print(); - fatal("Unhandled constant"); - break; + int offset = -1; + AccessFlags flags; + BasicType basic_type; + if (holder->klass() == SystemDictionary::HotSpotTypeResolved_klass()) { + FieldAccessInfo result; + LinkResolver::resolve_field(result, cp, index, + Bytecodes::java_code(code), + true, false, Thread::current()); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + } else { + offset = result.field_offset(); + flags = result.access_flags(); + holder_klass = result.klass()->as_klassOop(); + basic_type = result.field_type(); + holder = GraalCompiler::get_RiType(holder_klass, CHECK_NULL); } - if (constant_object != NULL) { - HotSpotField::set_constant(field_handle, constant_object); + } + + Handle type = GraalCompiler::get_RiTypeFromSignature(cp, sig_index, cp->pool_holder(), CHECK_NULL); + Handle field_handle = GraalCompiler::get_RiField(offset, flags.as_int(), name, holder, type, code, THREAD); + + oop constant_object = NULL; + // Check to see if the field is constant. + if (!holder_klass.is_null() && holder_klass->is_initialized() && flags.is_final() && flags.is_static()) { + // This field just may be constant. The only cases where it will + // not be constant are: + // + // 1. The field holds a non-perm-space oop. The field is, strictly + // speaking, constant but we cannot embed non-perm-space oops into + // generated code. For the time being we need to consider the + // field to be not constant. + // 2. The field is a *special* static&final field whose value + // may change. The three examples are java.lang.System.in, + // java.lang.System.out, and java.lang.System.err. + + bool ok = true; + assert( SystemDictionary::System_klass() != NULL, "Check once per vm"); + if( holder_klass->as_klassOop() == SystemDictionary::System_klass() ) { + // Check offsets for case 2: System.in, System.out, or System.err + if( offset == java_lang_System::in_offset_in_bytes() || + offset == java_lang_System::out_offset_in_bytes() || + offset == java_lang_System::err_offset_in_bytes() ) { + ok = false; + } } + + if (ok) { + Handle mirror = holder_klass->java_mirror(); + switch(basic_type) { + case T_OBJECT: + case T_ARRAY: + constant_object = VMExits::createCiConstantObject(mirror->obj_field(offset), CHECK_0); + break; + case T_DOUBLE: + constant_object = VMExits::createCiConstantDouble(mirror->double_field(offset), CHECK_0); + break; + case T_FLOAT: + constant_object = VMExits::createCiConstantFloat(mirror->float_field(offset), CHECK_0); + break; + case T_LONG: + constant_object = VMExits::createCiConstant(CiKind::Long(), mirror->long_field(offset), CHECK_0); + break; + case T_INT: + constant_object = VMExits::createCiConstant(CiKind::Int(), mirror->int_field(offset), CHECK_0); + break; + case T_SHORT: + constant_object = VMExits::createCiConstant(CiKind::Short(), mirror->short_field(offset), CHECK_0); + break; + case T_CHAR: + constant_object = VMExits::createCiConstant(CiKind::Char(), mirror->char_field(offset), CHECK_0); + break; + case T_BYTE: + constant_object = VMExits::createCiConstant(CiKind::Byte(), mirror->byte_field(offset), CHECK_0); + break; + case T_BOOLEAN: + constant_object = VMExits::createCiConstant(CiKind::Boolean(), mirror->bool_field(offset), CHECK_0); + break; + default: + fatal("Unhandled constant"); + break; + } + } + } + if (constant_object != NULL) { + HotSpotField::set_constant(field_handle, constant_object); } return JNIHandles::make_local(THREAD, field_handle()); } @@ -659,7 +635,7 @@ klassOop klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(resolved_type)); Symbol* name_symbol = VmIds::toSymbol(name); Symbol* signature_symbol = VmIds::toSymbol(signature); - methodOop method = klass->klass_part()->lookup_method(name_symbol, signature_symbol); + methodHandle method = klass->klass_part()->lookup_method(name_symbol, signature_symbol); if (method == NULL) { if (TraceGraal >= 3) { ResourceMark rm; @@ -667,8 +643,8 @@ } return NULL; } - oop ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); - return JNIHandles::make_local(THREAD, ret); + Handle ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); + return JNIHandles::make_local(THREAD, ret()); } // public boolean RiType_isSubtypeOf(HotSpotTypeResolved klass, RiType other); @@ -692,17 +668,12 @@ // public RiType RiType_componentType(HotSpotResolvedType klass); JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiType_1componentType(JNIEnv *, jobject, jobject klass) { TRACE_graal_3("VMEntries::RiType_componentType"); - ciArrayKlass* array_klass; - { - VM_ENTRY_MARK; - assert(JNIHandles::resolve(klass) != NULL, ""); - array_klass = (ciArrayKlass *) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); - } - ciType* element_type = array_klass->element_type(); - VM_ENTRY_MARK; + KlassHandle array_klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)); + assert(array_klass->oop_is_objArray(), "just checking"); + klassOop element_type = objArrayKlass::cast(array_klass())->element_klass(); assert(JNIHandles::resolve(klass) != NULL, ""); - return JNIHandles::make_local(GraalCompiler::get_RiType(element_type, java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)), THREAD)); + return JNIHandles::make_local(GraalCompiler::get_RiType(element_type, THREAD)()); } // public RiType RiType_superType(HotSpotResolvedType klass); @@ -710,18 +681,17 @@ TRACE_graal_3("VMEntries::RiType_superType"); VM_ENTRY_MARK; KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); - ciInstanceKlass* k = NULL; + klassOop k; if (klass_handle->oop_is_array()) { - k = (ciInstanceKlass *) CURRENT_ENV->get_object(SystemDictionary::Object_klass()); + k = SystemDictionary::Object_klass(); } else { guarantee(klass_handle->oop_is_instance(), "must be instance klass"); - k = (ciInstanceKlass *) CURRENT_ENV->get_object(klass_handle()); - k = k->super(); + k = klass_handle->super(); } if (k != NULL) { - return JNIHandles::make_local(GraalCompiler::get_RiType(k, klass_handle, THREAD)); + return JNIHandles::make_local(GraalCompiler::get_RiType(k, THREAD)()); } else { return NULL; } @@ -730,25 +700,12 @@ // public RiType RiType_uniqueConcreteSubtype(HotSpotResolvedType klass); JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiType_1uniqueConcreteSubtype(JNIEnv *, jobject, jobject klass) { TRACE_graal_3("VMEntries::RiType_uniqueConcreteSubtype"); - Thread* THREAD = Thread::current(); + VM_ENTRY_MARK; KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); - ciInstanceKlass* k = NULL; - { - VM_ENTRY_MARK; - k = (ciInstanceKlass *) CURRENT_ENV->get_object(klass_handle()); + Klass *up_cast = klass_handle->up_cast_abstract(); + if (up_cast->is_leaf_class()) { + return JNIHandles::make_local(GraalCompiler::get_RiType(up_cast, THREAD)()); } - - if (k->is_abstract()) { - ciInstanceKlass* sub = k->unique_concrete_subklass(); - if (sub != NULL && sub->is_leaf_type()) { - VM_ENTRY_MARK; - return JNIHandles::make_local(GraalCompiler::get_RiType(sub, klass_handle, THREAD)); - } - } else if (k->is_leaf_type()) { - assert(!k->is_interface(), ""); - return klass; - } - return NULL; } @@ -768,45 +725,41 @@ KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); KlassHandle array = klass_handle->array_klass(THREAD); Handle name = VmIds::toString(array->name(), CHECK_NULL); - return JNIHandles::make_local(THREAD, GraalCompiler::createHotSpotTypeResolved(array, name, THREAD)); + return JNIHandles::make_local(THREAD, GraalCompiler::createHotSpotTypeResolved(array, name, THREAD)()); } // public RiField[] RiType_fields(HotSpotTypeResolved klass); JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiType_1fields(JNIEnv *, jobject, jobject klass) { TRACE_graal_3("VMEntries::RiType_fields"); - KlassHandle klass_handle; - ciInstanceKlass* instance_klass; - objArrayHandle fieldsArray; - HandleMark hm; - { - VM_ENTRY_MARK; - klass_handle = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)); - instance_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(klass_handle()); - } - GrowableArray* fields = instance_klass->non_static_fields(); - { - VM_ENTRY_MARK; + VM_ENTRY_MARK; + ResourceMark rm; + + instanceKlassHandle k = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)); + class MyFieldClosure : public FieldClosure { + public: + instanceKlassHandle _holder; + Handle _resolved_type_holder; + GrowableArray _field_array; + + MyFieldClosure(instanceKlassHandle& holder, Handle resolved_type_holder) : _holder(holder), _resolved_type_holder(resolved_type_holder) { } - int count = 0; - for (int i = 0; i < fields->length(); i++) { - ciField* field = fields->at(i); - if (field->holder() == instance_klass) { - count++; + virtual void do_field(fieldDescriptor* fd) { + if (!Thread::current()->has_pending_exception()) { + if (fd->field_holder() == _holder()) { + Handle type = GraalCompiler::get_RiTypeFromSignature(fd->constants(), fd->signature_index(), fd->field_holder(), Thread::current()); + Handle field = VMExits::createRiField(_resolved_type_holder, VmIds::toString(fd->name(), Thread::current()), type, fd->offset(), fd->access_flags().as_int(), Thread::current()); + _field_array.append(field()); + } } } - - fieldsArray = oopFactory::new_objArray(SystemDictionary::RiField_klass(), count, CHECK_NULL); - int z = 0; - for (int i = 0; i < fields->length(); i++) { - ciField* field = fields->at(i); - if (field->holder() == instance_klass) { - Handle field_handle = GraalCompiler::get_RiField(field, instance_klass, klass_handle, Bytecodes::_illegal, CHECK_NULL); - fieldsArray->obj_at_put(z, field_handle()); - z++; - } - } + }; + MyFieldClosure closure(k, JNIHandles::resolve(klass)); + k->do_nonstatic_fields(&closure); + objArrayHandle field_array = oopFactory::new_objArray(SystemDictionary::RiField_klass(), closure._field_array.length(), CHECK_NULL); + for (int i=0; iobj_at_put(i, closure._field_array.at(i)()); } - return JNIHandles::make_local(fieldsArray()); + return JNIHandles::make_local(field_array()); } // public RiType getPrimitiveArrayType(CiKind kind); @@ -815,8 +768,8 @@ VM_ENTRY_MARK; BasicType type = GraalCompiler::kindToBasicType(CiKind::typeChar(kind)); assert(type != T_OBJECT, "primitive type expecteds"); - ciKlass* klass = ciTypeArrayKlass::make(type); - return JNIHandles::make_local(THREAD, GraalCompiler::get_RiType(klass, KlassHandle(), THREAD)); + Handle result = GraalCompiler::get_RiType(Universe::typeArrayKlassObj(type), CHECK_NULL); + return JNIHandles::make_local(THREAD, result()); } // public long getMaxCallTargetOffset(CiRuntimeCall rtcall); @@ -848,8 +801,8 @@ KlassHandle klass = java_lang_Class::as_klassOop(javaClassOop); Handle name = java_lang_String::create_from_symbol(klass->name(), CHECK_NULL); - oop type = GraalCompiler::createHotSpotTypeResolved(klass, name, CHECK_NULL); - return JNIHandles::make_local(THREAD, type); + Handle type = GraalCompiler::createHotSpotTypeResolved(klass, name, CHECK_NULL); + return JNIHandles::make_local(THREAD, type()); } } @@ -975,19 +928,13 @@ JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_installMethod(JNIEnv *jniEnv, jobject, jobject targetMethod, jboolean install_code) { VM_ENTRY_MARK; nmethod* nm = NULL; - if (CURRENT_ENV == NULL) { - Arena arena; - ciEnv env(&arena); - ResourceMark rm; - CodeInstaller installer(JNIHandles::resolve(targetMethod), nm, install_code != 0); - } else { - ResourceMark rm; - CodeInstaller installer(JNIHandles::resolve(targetMethod), nm, install_code != 0); - - if (CURRENT_ENV->failing()) { - tty->print_cr("failing: %s", CURRENT_ENV->failure_reason()); - } - } + ciEnv* current_env = JavaThread::current()->env(); + JavaThread::current()->set_env(NULL); + Arena arena; + ciEnv env(&arena); + ResourceMark rm; + CodeInstaller installer(JNIHandles::resolve(targetMethod), nm, install_code != 0); + JavaThread::current()->set_env(current_env); // if install_code is true then we installed the code into the given method, no need to return an RiCompiledMethod if (!install_code && nm != NULL) { @@ -1007,15 +954,13 @@ JNIEXPORT jlong JNICALL Java_com_oracle_graal_hotspot_VMEntries_installStub(JNIEnv *jniEnv, jobject, jobject targetMethod) { VM_ENTRY_MARK; jlong id; - if (CURRENT_ENV == NULL) { - Arena arena; - ciEnv env(&arena); - ResourceMark rm; - CodeInstaller installer(JNIHandles::resolve(targetMethod), id); - } else { - ResourceMark rm; - CodeInstaller installer(JNIHandles::resolve(targetMethod), id); - } + ciEnv* current_env = JavaThread::current()->env(); + JavaThread::current()->set_env(NULL); + Arena arena; + ciEnv env(&arena); + ResourceMark rm; + CodeInstaller installer(JNIHandles::resolve(targetMethod), id); + JavaThread::current()->set_env(current_env); return id; } diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/graal/graalVMEntries.hpp --- a/src/share/vm/graal/graalVMEntries.hpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/graal/graalVMEntries.hpp Fri Nov 18 13:34:10 2011 +0100 @@ -28,8 +28,6 @@ methodOop getMethodFromHotSpotMethod(oop hotspotMethod); -oop getReflectedMethod(methodOop method, TRAPS); - // nothing here - no need to define the jni method implementations in a header file diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/graal/graalVMExits.cpp --- a/src/share/vm/graal/graalVMExits.cpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/graal/graalVMExits.cpp Fri Nov 18 13:34:10 2011 +0100 @@ -73,8 +73,6 @@ JavaValue result(T_VOID); JavaCalls::call_static(&result, compilerImplKlass, vmSymbols::initialize_name(), vmSymbols::void_method_signature(), Thread::current()); check_pending_exception("Couldn't initialize compiler"); - - startCompiler(); } jboolean VMExits::setOption(Handle option) { @@ -99,7 +97,7 @@ check_pending_exception("Error while calling setDefaultOptions"); } -void VMExits::compileMethod(Handle hotspot_method, int entry_bci) { +void VMExits::compileMethod(Handle hotspot_method, int entry_bci, jboolean blocking) { assert(!hotspot_method.is_null(), "just checking"); Thread* THREAD = Thread::current(); JavaValue result(T_VOID); @@ -107,6 +105,7 @@ args.push_oop(instance()); args.push_oop(hotspot_method); args.push_int(entry_bci); + args.push_int(blocking); JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::compileMethod_name(), vmSymbols::compileMethod_signature(), &args, THREAD); check_pending_exception("Error while calling compileMethod"); } @@ -140,6 +139,15 @@ check_pending_exception("Error while calling startCompiler"); } +void VMExits::bootstrap() { + JavaThread* THREAD = JavaThread::current(); + JavaValue result(T_VOID); + JavaCallArguments args; + args.push_oop(instance()); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::bootstrap_name(), vmSymbols::void_method_signature(), &args, THREAD); + check_pending_exception("Error while calling boostrap"); +} + void VMExits::pollJavaQueue() { JavaThread* THREAD = JavaThread::current(); JavaValue result(T_VOID); @@ -272,14 +280,6 @@ oop VMExits::createCiConstantObject(Handle object, TRAPS) { JavaValue result(T_OBJECT); JavaCallArguments args; - /* - args.push_oop(instance()); - args.push_oop(object); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstantObject_name(), vmSymbols::createCiConstantObject_signature(), &args, THREAD); - check_pending_exception("Error while calling createCiConstantObject"); - */ - - KlassHandle klass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_cri_ci_CiConstant(), SystemDictionary::java_system_loader(), NULL, Thread::current()); JavaCalls::call_static(&result, klass(), vmSymbols::forObject_name(), vmSymbols::createCiConstantObject_signature(), object, THREAD); check_pending_exception("Error while calling CiConstant.forObject"); diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/graal/graalVMExits.hpp --- a/src/share/vm/graal/graalVMExits.hpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/graal/graalVMExits.hpp Fri Nov 18 13:34:10 2011 +0100 @@ -50,14 +50,17 @@ // public static void HotSpotOptions.setDefaultOptions(); static void setDefaultOptions(); - // public abstract void compileMethod(long vmId, String name, int entry_bci); - static void compileMethod(Handle hotspot_method, int entry_bci); + // public abstract void compileMethod(long vmId, String name, int entry_bci, boolean blocking); + static void compileMethod(Handle hotspot_method, int entry_bci, jboolean blocking); // public abstract void shutdownCompiler(); static void shutdownCompiler(); // public abstract void startCompiler(); static void startCompiler(); + + // public abstract void bootstrap(); + static void bootstrap(); // public abstract void pollJavaQueue(); static void pollJavaQueue(); diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/oops/instanceKlass.hpp --- a/src/share/vm/oops/instanceKlass.hpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/oops/instanceKlass.hpp Fri Nov 18 13:34:10 2011 +0100 @@ -634,7 +634,7 @@ void process_interfaces(Thread *thread); // virtual operations from Klass - bool is_leaf_class() const { return _subklass == NULL; } + bool is_leaf_class() const { return _subklass == NULL && _nof_implementors == 0; } objArrayOop compute_secondary_supers(int num_extra_slots, TRAPS); bool compute_is_subtype_of(klassOop k); bool can_be_primary_super_slow() const; diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/opto/output.cpp --- a/src/share/vm/opto/output.cpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/opto/output.cpp Fri Nov 18 13:34:10 2011 +0100 @@ -934,7 +934,7 @@ assert(jvms->bci() >= InvocationEntryBci && jvms->bci() <= 0x10000, "must be a valid or entry BCI"); assert(!jvms->should_reexecute() || depth == max_depth, "reexecute allowed only for the youngest"); // Now we can describe the scope. - debug_info()->describe_scope(safepoint_pc_offset, scope_method, jvms->bci(), jvms->should_reexecute(), is_method_handle_invoke, return_oop, locvals, expvals, monvals); + debug_info()->describe_scope(safepoint_pc_offset, (methodOop)scope_method->get_oop(), jvms->bci(), jvms->should_reexecute(), is_method_handle_invoke, return_oop, locvals, expvals, monvals); } // End jvms loop // Mark the end of the scope set. @@ -1017,7 +1017,7 @@ JVMState* jvms = youngest_jvms->of_depth(depth); ciMethod* method = jvms->has_method() ? jvms->method() : NULL; assert(!jvms->should_reexecute() || depth==max_depth, "reexecute allowed only for the youngest"); - debug_info->describe_scope(pc_offset, method, jvms->bci(), jvms->should_reexecute()); + debug_info->describe_scope(pc_offset, (methodOop)method->get_oop(), jvms->bci(), jvms->should_reexecute()); } // Mark the end of the scope set. diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/prims/jni.cpp Fri Nov 18 13:34:10 2011 +0100 @@ -3361,6 +3361,12 @@ *vm = (JavaVM *)(&main_vm); *(JNIEnv**)penv = thread->jni_environment(); + if (UseGraal) { + GraalCompiler* compiler = GraalCompiler::instance(); + ciObjectFactory::initialize(); + compiler->initialize(); + } + // Tracks the time application was running before GC RuntimeService::record_application_start(); @@ -3369,10 +3375,6 @@ JvmtiExport::post_thread_start(thread); } - if (UseGraal && BootstrapGraal) { - CompileBroker::bootstrap_graal(); - } - // Check if we should compile all classes on bootclasspath NOT_PRODUCT(if (CompileTheWorld) ClassLoader::compile_the_world();) // Since this is not a JVM_ENTRY we have to set the thread state manually before leaving. diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/runtime/fieldDescriptor.hpp --- a/src/share/vm/runtime/fieldDescriptor.hpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/runtime/fieldDescriptor.hpp Fri Nov 18 13:34:10 2011 +0100 @@ -49,6 +49,8 @@ constantPoolHandle _cp; public: + int name_index() const { return _name_index; } + int signature_index() const { return _signature_index; } Symbol* name() const { return _cp->symbol_at(_name_index); } Symbol* signature() const { return _cp->symbol_at(_signature_index); } klassOop field_holder() const { return _cp->pool_holder(); } diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/runtime/thread.cpp Fri Nov 18 13:34:10 2011 +0100 @@ -2938,7 +2938,7 @@ static void compiler_thread_entry(JavaThread* thread, TRAPS) { assert(thread->is_Compiler_thread(), "must be compiler thread"); - CompileBroker::compiler_thread_loop(); + //CompileBroker::compiler_thread_loop(); } // Create a CompilerThread @@ -2948,7 +2948,6 @@ _task = NULL; _queue = queue; _counters = counters; - _is_compiling = false; _scanned_nmethod = NULL; #ifndef PRODUCT diff -r 1976ebe361c2 -r 5c8fc9f05960 src/share/vm/runtime/thread.hpp --- a/src/share/vm/runtime/thread.hpp Fri Nov 18 11:55:00 2011 +0100 +++ b/src/share/vm/runtime/thread.hpp Fri Nov 18 13:34:10 2011 +0100 @@ -716,6 +716,7 @@ // (tw) Necessary for holding a compilation buffer and ci environment. Moved from CompilerThread to JavaThread in order to enable code installation from Java application code. BufferBlob* _buffer_blob; ciEnv* _env; + bool _is_compiling; #ifdef ASSERT private: @@ -853,9 +854,6 @@ volatile int _exception_stack_size; // Size of frame where exception happened volatile int _is_method_handle_return; // true (== 1) if the current exception PC is a MethodHandle call site. - // support for compilation - bool _is_compiling; // is true if a compilation is active inthis thread (one compilation per thread possible) - // support for JNI critical regions jint _jni_active_critical; // count of entries into JNI critical region @@ -916,6 +914,9 @@ return (struct JNINativeInterface_ *)_jni_environment.functions; } + bool is_compiling() const { return _is_compiling; } + void set_compiling(bool b) { _is_compiling = b; } + // Get/set the thread's compilation environment. ciEnv* env() { return _env; } void set_env(ciEnv* env) { _env = env; } @@ -942,10 +943,6 @@ // Testers virtual bool is_Java_thread() const { return true; } - // compilation - void set_is_compiling(bool f) { _is_compiling = f; } - bool is_compiling() const { return _is_compiling; } - // Thread chain operations JavaThread* next() const { return _next; } void set_next(JavaThread* p) { _next = p; } @@ -1716,7 +1713,6 @@ CompileLog* _log; CompileTask* _task; CompileQueue* _queue; - bool _is_compiling; nmethod* _scanned_nmethod; // nmethod being scanned by the sweeper @@ -1726,8 +1722,6 @@ CompilerThread(CompileQueue* queue, CompilerCounters* counters); - bool is_compiling() const { return _is_compiling; } - void set_compiling(bool b) { _is_compiling = b; } bool is_Compiler_thread() const { return true; } // Hide this compiler thread from external view. // (tw) For Graal, the compiler thread should be visible.