Author: tcurdt Date: Tue Dec 22 14:04:05 2009 New Revision: 893171 URL: http://svn.apache.org/viewvc?rev=893171&view=rev Log: patch from Valery Silaev <vsil...@gmail.com> (see https://issues.apache.org/jira/browse/SANDBOX-277 )
Modified: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java Modified: commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java URL: http://svn.apache.org/viewvc/commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java?rev=893171&r1=893170&r2=893171&view=diff ============================================================================== --- commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java (original) +++ commons/sandbox/javaflow/trunk/src/main/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java Tue Dec 22 14:04:05 2009 @@ -100,7 +100,7 @@ int lsize = frame.getLocals(); for (int j = lsize - 1; j >= 0; j--) { BasicValue value = (BasicValue) frame.getLocal(j); - if (value == null) { + if (isNull(value)) { mv.visitInsn(ACONST_NULL); mv.visitVarInsn(ASTORE, j); } else if (value == BasicValue.UNINITIALIZED_VALUE) { @@ -145,7 +145,7 @@ int ssize = frame.getStackSize(); for (int j = 0; j < ssize - argSize - ownerSize - initSize; j++) { BasicValue value = (BasicValue) frame.getStack(j); - if (value == null) { + if (isNull(value)) { mv.visitInsn(ACONST_NULL); } else if (value == BasicValue.UNINITIALIZED_VALUE) { // TODO ?? @@ -163,9 +163,16 @@ } if (mnode.getOpcode() != INVOKESTATIC) { - mv.visitVarInsn(ALOAD, stackRecorderVar); - mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Reference", "()Ljava/lang/Object;"); - mv.visitTypeInsn(CHECKCAST, ((BasicValue) frame.getStack(ssize - argSize - 1)).getType().getInternalName()); + // Load the object whose method we are calling + BasicValue value = ((BasicValue) frame.getStack(ssize - argSize - 1)); + if (isNull(value)) { + // If user code causes NPE, then we keep this behavior: load null to get NPE at runtime + mv.visitInsn(ACONST_NULL); + } else { + mv.visitVarInsn(ALOAD, stackRecorderVar); + mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Reference", "()Ljava/lang/Object;"); + mv.visitTypeInsn(CHECKCAST, value.getType().getInternalName()); + } } // Create null types for the parameters of the method invocation @@ -216,7 +223,7 @@ int ssize = currentFrame.getStackSize() - argSize - ownerSize; for (int i = ssize - 1; i >= 0; i--) { BasicValue value = (BasicValue) currentFrame.getStack(i); - if (value == null) { + if (isNull(value)) { mv.visitInsn(POP); } else if (value == BasicValue.UNINITIALIZED_VALUE) { // TODO ?? @@ -251,7 +258,7 @@ int fsize = currentFrame.getLocals(); for (int j = 0; j < fsize; j++) { BasicValue value = (BasicValue) currentFrame.getLocal(j); - if (value == null) { + if (isNull(value)) { // no need to save null } else if (value == BasicValue.UNINITIALIZED_VALUE) { // no need to save uninitialized objects @@ -301,6 +308,15 @@ mv.visitMaxs(0, 0); } + static boolean isNull(BasicValue value) { + if (null == value) + return true; + if (!value.isReference()) + return false; + final Type type = value.getType(); + return "Lnull;".equals(type.getDescriptor()); + } + void pushDefault(Type type) { switch (type.getSort()) { case Type.VOID: