[Nice-commit] Nice/src/gnu/bytecode Type.java,1.13,1.14 CodeAttr.java,1.16,1.17 ClassType.java,1.14,
Brought to you by:
bonniot
From: <bo...@us...> - 2003-06-24 20:07:41
|
Update of /cvsroot/nice/Nice/src/gnu/bytecode In directory sc8-pr-cvs1:/tmp/cvs-serv31471/src/gnu/bytecode Modified Files: Type.java CodeAttr.java ClassType.java Log Message: In the bytecode, make method calls refer to the most precise reveiver. This improves the ability to compile on one version of the JDK and run on an earlier one, if a super-class is added in the later version (this happens in particular between JDK 1.3 and 1.4 with String and CharSequence). Incidentally, it can make the method call more efficient, especially if it changes an interface method into a class method. Index: Type.java =================================================================== RCS file: /cvsroot/nice/Nice/src/gnu/bytecode/Type.java,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** Type.java 4 Dec 2002 10:31:13 -0000 1.13 --- Type.java 24 Jun 2003 20:07:38 -0000 1.14 *************** *** 460,463 **** --- 460,467 ---- return null; + // Optimization + if (t1 == t2) + return t1; + if (t1.isSubtype(t2)) return t2; *************** *** 560,563 **** --- 564,576 ---- { throw new Error ("unimplemented emitCoerceFromObject for "+this); + } + + /** + Return an equivalent method when the receiver is of this type. + Return null if no more precise method exists. + */ + Method refineMethod (Method method) + { + return null; } Index: CodeAttr.java =================================================================== RCS file: /cvsroot/nice/Nice/src/gnu/bytecode/CodeAttr.java,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** CodeAttr.java 2 Apr 2003 21:38:17 -0000 1.16 --- CodeAttr.java 24 Jun 2003 20:07:38 -0000 1.17 *************** *** 637,643 **** public void emitPushNull () { reserve(1); put1(1); // aconst_null ! pushType(Type.pointer_type); } --- 637,651 ---- public void emitPushNull () { + emitPushNull(Type.pointer_type); + } + + /** + @param type the type <code>null</code> is considered to have. + */ + public void emitPushNull (Type type) + { reserve(1); put1(1); // aconst_null ! pushType(type); } *************** *** 1056,1061 **** throw new Error ("emitInvokeXxx static flag mis-match method.flags="+method.access_flags); if (!is_invokestatic) ! arg_count++; put1(opcode); // invokevirtual, invokespecial, or invokestatic putIndex2(getConstants().addMethodRef(method)); --- 1064,1096 ---- throw new Error ("emitInvokeXxx static flag mis-match method.flags="+method.access_flags); + while (--arg_count >= 0) + popType(); if (!is_invokestatic) ! { ! arg_count++; ! Type receiverType = popType(); ! // Don't change anything is the call is an invokespecial ! if (opcode != 183 && receiverType != method.getDeclaringClass()) ! { ! // We try to find a more precise method, given the known ! // type of the receiver. ! Method preciseMethod = receiverType.refineMethod(method); ! ! if (preciseMethod != null && ! // Don't choose a more precise method if it is an ! // interface method, and the original is a class method ! // (can happen if the original class is Object, like in ! // Object.equals, refined in List.equals). ! ((! preciseMethod.getDeclaringClass().isInterface()) || ! method.getDeclaringClass().isInterface())) ! { ! method = preciseMethod; ! // It could be that the call was an invokeinterface, and ! // now became an invokevirtual. ! if (opcode == 185 && ! method.getDeclaringClass().isInterface()) ! opcode = 182; ! } ! } ! } put1(opcode); // invokevirtual, invokespecial, or invokestatic putIndex2(getConstants().addMethodRef(method)); *************** *** 1065,1070 **** put1(0); } - while (--arg_count >= 0) - popType(); if (method.return_type.size != 0) pushType(method.return_type); --- 1100,1103 ---- *************** *** 1479,1482 **** --- 1512,1530 ---- + " while SP at end of 'else' was " + SP); } + else + { + // Reconcile the types on the stack. + for (int i = 0; i < if_stack.then_stacked_types.length; i++) + { + Type t1 = if_stack.then_stacked_types[i]; + Type t2 = stack_types[if_stack.start_stack_size + i]; + + Type common = Type.lowestCommonSuperType(t1, t2); + if (common == null) + common = Type.pointer_type; + + stack_types[if_stack.start_stack_size + i] = common; + } + } } else if (unreachable_here) Index: ClassType.java =================================================================== RCS file: /cvsroot/nice/Nice/src/gnu/bytecode/ClassType.java,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** ClassType.java 26 Apr 2003 15:47:02 -0000 1.14 --- ClassType.java 24 Jun 2003 20:07:38 -0000 1.15 *************** *** 712,715 **** --- 712,728 ---- } + /** + Return an equivalent method when the receiver is of this type. + Return null if no more precise method exists. + */ + Method refineMethod (Method method) + { + Method res = getMethod(method.getName(), method.arg_types); + if (res == method) + return null; + else + return res; + } + /** Do various fixups after generating code but before we can write it out. * This includes assigning constant pool indexes where needed, *************** *** 991,994 **** --- 1004,1010 ---- emitCoerceToObject(code); code.emitFi(); + + // Set the type + code.popType(); code.pushType(collectionType); } else |