# HG changeset patch # User Andreas Woess # Date 1365520277 -7200 # Node ID 7ef66078d83755339e82d1221b1e74059f0f9162 # Parent 8fab4f4fde34c233569a230cfe6a3df58df319af add basic invokedynamic support diff -r 8fab4f4fde34 -r 7ef66078d837 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java Tue Apr 09 11:55:19 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java Tue Apr 09 17:11:17 2013 +0200 @@ -93,4 +93,12 @@ * entry */ Object lookupConstant(int cpi); + + /** + * Looks up the appendix at the specified index. + * + * @param cpi the constant pool index + * @return the appendix if resolved or {@code null}. + */ + Object lookupAppendix(int cpi); } diff -r 8fab4f4fde34 -r 7ef66078d837 graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeStream.java --- a/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeStream.java Tue Apr 09 11:55:19 2013 +0200 +++ b/graal/com.oracle.graal.bytecode/src/com/oracle/graal/bytecode/BytecodeStream.java Tue Apr 09 17:11:17 2013 +0200 @@ -168,6 +168,16 @@ } /** + * Reads a constant pool index for an invokedynamic instruction. + * + * @return the constant pool index + */ + public int readCPI4() { + assert opcode == Bytecodes.INVOKEDYNAMIC; + return Bytes.beS4(code, curBCI + 1); + } + + /** * Reads a signed, 1-byte value for the current instruction (e.g. BIPUSH). * * @return the byte diff -r 8fab4f4fde34 -r 7ef66078d837 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Tue Apr 09 11:55:19 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Tue Apr 09 17:11:17 2013 +0200 @@ -221,4 +221,6 @@ * @param metaspaceMethod the metaspace Method object */ void reprofile(long metaspaceMethod); + + Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi); } diff -r 8fab4f4fde34 -r 7ef66078d837 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Tue Apr 09 11:55:19 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Tue Apr 09 17:11:17 2013 +0200 @@ -158,4 +158,7 @@ @Override public native void reprofile(long metaspaceMethod); + + @Override + public native Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi); } diff -r 8fab4f4fde34 -r 7ef66078d837 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Tue Apr 09 11:55:19 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Tue Apr 09 17:11:17 2013 +0200 @@ -51,6 +51,13 @@ } @Override + public Object lookupAppendix(int cpi) { + assert cpi != 0; + Object constant = HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupAppendixInPool(type, cpi); + return constant; + } + + @Override public JavaMethod lookupMethod(int cpi, int opcode) { return HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupMethodInPool(type, cpi, (byte) opcode); } diff -r 8fab4f4fde34 -r 7ef66078d837 graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java Tue Apr 09 11:55:19 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java Tue Apr 09 17:11:17 2013 +0200 @@ -102,6 +102,13 @@ buf.append(String.format("#%-10s // %s", cpi + ", " + stream.readUByte(bci + 3), calleeDesc)); break; } + case INVOKEDYNAMIC: { + int cpi = stream.readCPI4(); + JavaMethod callee = cp.lookupMethod(cpi, opcode); + String calleeDesc = callee.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? MetaUtil.format("%n:(%P)%R", callee) : MetaUtil.format("%H.%n:(%P)%R", callee); + buf.append(String.format("#%-10d // %s", cpi, calleeDesc)); + break; + } case LDC : case LDC_W : case LDC2_W : { diff -r 8fab4f4fde34 -r 7ef66078d837 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Apr 09 11:55:19 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Apr 09 17:11:17 2013 +0200 @@ -766,7 +766,8 @@ } private void eagerResolvingForSnippets(int cpi, int bytecode) { - if (graphBuilderConfig.eagerResolving()) { + // (aw) cannot eager-resolve invokedynamic + if (graphBuilderConfig.eagerResolving() && bytecode != Bytecodes.INVOKEDYNAMIC) { constantPool.loadReferencedType(cpi, bytecode); } } @@ -1054,6 +1055,19 @@ } } + private void genInvokeDynamic(JavaMethod target) { + if (target instanceof ResolvedJavaMethod) { + Object appendix = constantPool.lookupAppendix(stream.readCPI4()); + if (appendix != null) { + frameState.apush(ConstantNode.forObject(appendix, runtime, currentGraph)); + } + ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(false), target.getSignature().getParameterCount(false)); + appendInvoke(InvokeKind.Static, (ResolvedJavaMethod) target, args); + } else { + handleUnresolvedInvoke(target, InvokeKind.Static); + } + } + private void genInvokeVirtual(JavaMethod target) { if (target instanceof ResolvedJavaMethod) { ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true)); @@ -1937,6 +1951,7 @@ case INVOKESPECIAL : cpi = stream.readCPI(); genInvokeSpecial(lookupMethod(cpi, opcode)); break; case INVOKESTATIC : cpi = stream.readCPI(); genInvokeStatic(lookupMethod(cpi, opcode)); break; case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(lookupMethod(cpi, opcode)); break; + case INVOKEDYNAMIC : cpi = stream.readCPI4(); genInvokeDynamic(lookupMethod(cpi, opcode)); break; case NEW : genNewInstance(stream.readCPI()); break; case NEWARRAY : genNewPrimitiveArray(stream.readLocalIndex()); break; case ANEWARRAY : genNewObjectArray(stream.readCPI()); break; diff -r 8fab4f4fde34 -r 7ef66078d837 src/cpu/x86/vm/templateInterpreter_x86.hpp --- a/src/cpu/x86/vm/templateInterpreter_x86.hpp Tue Apr 09 11:55:19 2013 +0200 +++ b/src/cpu/x86/vm/templateInterpreter_x86.hpp Tue Apr 09 17:11:17 2013 +0200 @@ -34,7 +34,7 @@ // Run with +PrintInterpreter to get the VM to print out the size. // Max size with JVMTI #ifdef AMD64 - const static int InterpreterCodeSize = 224 * 1024; + const static int InterpreterCodeSize = 240 * 1024; #else const static int InterpreterCodeSize = 168 * 1024; #endif // AMD64 diff -r 8fab4f4fde34 -r 7ef66078d837 src/share/vm/graal/graalCompiler.hpp --- a/src/share/vm/graal/graalCompiler.hpp Tue Apr 09 11:55:19 2013 +0200 +++ b/src/share/vm/graal/graalCompiler.hpp Tue Apr 09 17:11:17 2013 +0200 @@ -68,7 +68,7 @@ // Print compilation timers and statistics virtual void print_timers(); - + static Handle get_JavaTypeFromSignature(Symbol* signature, KlassHandle accessor, TRAPS); static Handle get_JavaType(constantPoolHandle cp, int index, KlassHandle accessor, TRAPS); static Handle get_JavaType(Symbol* klass_name, TRAPS); @@ -93,6 +93,11 @@ return ((index & 0xFF) << 8) | (index >> 8); } + static int to_index_u4(int index) { + // Swap. + return ((index & 0xFF) << 24) | ((index & 0xFF00) << 8) | ((index & 0xFF0000) >> 8) | ((index & 0xFF000000) >> 24); + } + static void initialize_buffer_blob(); }; diff -r 8fab4f4fde34 -r 7ef66078d837 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Tue Apr 09 11:55:19 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Tue Apr 09 17:11:17 2013 +0200 @@ -62,7 +62,7 @@ C2V_ENTRY(jbyteArray, initializeBytecode, (JNIEnv *env, jobject, jlong metaspace_method, jbyteArray result)) methodHandle method = asMethod(metaspace_method); ResourceMark rm; - + int code_size = method->code_size(); jbyte* reconstituted_code = NULL; @@ -416,12 +416,21 @@ return JNIHandles::make_local(THREAD, result); C2V_END +C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv *env, jobject, jobject type, jint index)) + assert(GraalCompiler::to_index_u4(index) < 0, "not an invokedynamic constant pool index"); + constantPoolHandle cpool(InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants()); + oop appendix_oop = ConstantPool::appendix_at_if_loaded(cpool, GraalCompiler::to_index_u4(index)); + + return JNIHandles::make_local(THREAD, appendix_oop); +C2V_END + C2V_VMENTRY(jobject, lookupMethodInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte opcode)) - index = GraalCompiler::to_cp_index_u2(index); constantPoolHandle cp = InstanceKlass::cast(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(type)))->constants(); instanceKlassHandle pool_holder(cp->pool_holder()); Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF); + index = (bc == Bytecodes::_invokedynamic) ? GraalCompiler::to_index_u4(index) : GraalCompiler::to_cp_index_u2(index); + methodHandle method = GraalEnv::get_method_by_index(cp, index, bc, pool_holder); if (!method.is_null()) { Handle holder = GraalCompiler::get_JavaType(method->method_holder(), CHECK_NULL); @@ -430,8 +439,13 @@ // Get the method's name and signature. Handle name = java_lang_String::create_from_symbol(cp->name_ref_at(index), CHECK_NULL); Handle signature = java_lang_String::create_from_symbol(cp->signature_ref_at(index), CHECK_NULL); - int holder_index = cp->klass_ref_index_at(index); - Handle type = GraalCompiler::get_JavaType(cp, holder_index, cp->pool_holder(), CHECK_NULL); + Handle type; + if (bc != Bytecodes::_invokedynamic) { + int holder_index = cp->klass_ref_index_at(index); + type = GraalCompiler::get_JavaType(cp, holder_index, cp->pool_holder(), CHECK_NULL); + } else { + type = Handle(SystemDictionary::MethodHandle_klass()->java_mirror()); + } return JNIHandles::make_local(THREAD, VMToCompiler::createUnresolvedJavaMethod(name, signature, type, THREAD)); } C2V_END @@ -479,7 +493,7 @@ int holder_index = cp->klass_ref_index_at(index); Handle holder = GraalCompiler::get_JavaType(cp, holder_index, cp->pool_holder(), CHECK_NULL); instanceKlassHandle holder_klass; - + Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF); int offset = -1; AccessFlags flags; @@ -499,7 +513,7 @@ holder = GraalCompiler::get_JavaType(holder_klass, CHECK_NULL); } } - + Handle type = GraalCompiler::get_JavaTypeFromSignature(signature, cp->pool_holder(), CHECK_NULL); Handle field_handle = GraalCompiler::get_JavaField(offset, flags.as_int(), name, holder, type, THREAD); @@ -663,7 +677,7 @@ set_int("arrayKlassLayoutHelperIdentifier", 0x80000000); assert((Klass::_lh_array_tag_obj_value & Klass::_lh_array_tag_type_value & 0x80000000) != 0, "obj_array and type_array must have first bit set"); set_int("arrayKlassComponentMirrorOffset", in_bytes(ArrayKlass::component_mirror_offset())); - + set_int("pendingDeoptimizationOffset", in_bytes(ThreadShadow::pending_deoptimization_offset())); @@ -1104,6 +1118,7 @@ {CC"getVtableEntryOffset", CC"("METASPACE_METHOD")I", FN_PTR(getVtableEntryOffset)}, {CC"lookupType", CC"("STRING HS_RESOLVED_TYPE"Z)"TYPE, FN_PTR(lookupType)}, {CC"lookupConstantInPool", CC"("HS_RESOLVED_TYPE"I)"OBJECT, FN_PTR(lookupConstantInPool)}, + {CC"lookupAppendixInPool", CC"("HS_RESOLVED_TYPE"I)"OBJECT, FN_PTR(lookupAppendixInPool)}, {CC"lookupMethodInPool", CC"("HS_RESOLVED_TYPE"IB)"METHOD, FN_PTR(lookupMethodInPool)}, {CC"lookupTypeInPool", CC"("HS_RESOLVED_TYPE"I)"TYPE, FN_PTR(lookupTypeInPool)}, {CC"lookupReferencedTypeInPool", CC"("HS_RESOLVED_TYPE"IB)V", FN_PTR(lookupReferencedTypeInPool)}, diff -r 8fab4f4fde34 -r 7ef66078d837 src/share/vm/graal/graalEnv.cpp --- a/src/share/vm/graal/graalEnv.cpp Tue Apr 09 11:55:19 2013 +0200 +++ b/src/share/vm/graal/graalEnv.cpp Tue Apr 09 17:11:17 2013 +0200 @@ -319,6 +319,19 @@ methodHandle GraalEnv::get_method_by_index_impl(constantPoolHandle& cpool, int index, Bytecodes::Code bc, instanceKlassHandle& accessor) { + if (bc == Bytecodes::_invokedynamic) { + ConstantPoolCacheEntry* cpce = cpool->invokedynamic_cp_cache_entry_at(index); + bool is_resolved = !cpce->is_f1_null(); + if (is_resolved) { + // Get the invoker Method* from the constant pool. + // (The appendix argument, if any, will be noted in the method's signature.) + Method* adapter = cpce->f1_as_method(); + return methodHandle(adapter); + } + + return NULL; + } + 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); @@ -369,7 +382,6 @@ 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); }