Commit 6bf25759 authored by Remi Forax's avatar Remi Forax

Methodwriter ldc condy should generate ldc2 w if result is a long or a double

parent cc3e0ae7
......@@ -31,6 +31,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.objectweb.asm.ConstantDynamic;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
......@@ -406,7 +407,9 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes
super.visitLdcInsn(value);
if (isConstructor && !superClassConstructorCalled) {
pushValue(OTHER);
if (value instanceof Double || value instanceof Long) {
if (value instanceof Double
|| value instanceof Long
|| (value instanceof ConstantDynamic && ((ConstantDynamic) value).getSize() == 2)) {
pushValue(OTHER);
}
}
......
......@@ -27,6 +27,7 @@
// THE POSSIBILITY OF SUCH DAMAGE.
package org.objectweb.asm.commons;
import org.objectweb.asm.ConstantDynamic;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
......@@ -178,7 +179,9 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
@Override
public void visitLdcInsn(final Object value) {
if (value instanceof Long || value instanceof Double) {
if (value instanceof Long
|| value instanceof Double
|| (value instanceof ConstantDynamic && ((ConstantDynamic) value).getSize() == 2)) {
minSize += 3;
maxSize += 3;
} else {
......
......@@ -31,6 +31,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ConstantDynamic;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
......@@ -442,6 +443,19 @@ public class GeneratorAdapter extends LocalVariablesSorter {
}
}
/**
* Generates the instruction to push a constant dynamic on the stack.
*
* @param constantDynamic the constant dynamic to be pushed on the stack.
*/
public void push(final ConstantDynamic constantDynamic) {
if (constantDynamic == null) {
mv.visitInsn(Opcodes.ACONST_NULL);
} else {
mv.visitLdcInsn(constantDynamic);
}
}
// -----------------------------------------------------------------------------------------------
// Instructions to load and store method arguments
// -----------------------------------------------------------------------------------------------
......
......@@ -150,7 +150,7 @@ class ClassDump {
builder.add("magic: ", parser.u4());
builder.add("minor_version: ", parser.u2());
int majorVersion = parser.u2();
if (majorVersion > /* V11 = */ 55) {
if (majorVersion > /* V12 = */ 56) {
throw new IOException("Unsupported class version");
}
builder.add("major_version: ", majorVersion);
......@@ -1244,12 +1244,12 @@ class ClassDump {
builder.addInsn(insnIndex, opcode);
break;
case 0x12: // ldc
builder.addInsn(insnIndex, opcode, builder.getCpInfo(parser.u1()));
builder.addInsn(insnIndex, 0x12, builder.getCpInfo(parser.u1()));
bytecodeOffset += 1;
break;
case 0x13: // ldc_w
case 0x14: // ldc2_w
builder.addInsn(insnIndex, 0x12, builder.getCpInfo(parser.u2()));
builder.addInsn(insnIndex, opcode == 0x13 ? 0x12 : 0x14, builder.getCpInfo(parser.u2()));
bytecodeOffset += 2;
break;
case 0x6D: // ldiv
......
......@@ -66,6 +66,25 @@ public Method m:"()Ljava/lang/Object;"
areturn;
}
public static Method primitiveExample:"()J"
stack 2 locals 0
{
ldc2_w Dynamic REF_invokeStatic
:jdk11/AllInstructions.bsm
:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)J"
:test
:"J";
lreturn;
}
private static Method bsm:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)J"
stack 2 locals 3
{
bipush 42;
i2l;
lreturn;
}
public static Method main:"([Ljava/lang/String;)V"
stack 1 locals 2
{
......
......@@ -61,7 +61,7 @@ public class AsmTestTest extends AsmTest {
assertEquals(majorVersion > /* V10 = */ 54, isMoreRecent);
break;
case ASM7:
assertEquals(majorVersion > /* V11 = */ 55, isMoreRecent);
assertEquals(majorVersion > /* V12 = */ 56, isMoreRecent);
break;
default:
fail("Unknown API value");
......
......@@ -21,6 +21,21 @@ public class jdk11/AllInstructions {
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x9
public static primitiveExample()J
LDC test : J jdk11/AllInstructions.bsm(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)J (6) []
LRETURN
MAXSTACK = 2
MAXLOCALS = 0
// access flags 0xA
private static bsm(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)J
BIPUSH 42
I2L
LRETURN
MAXSTACK = 2
MAXLOCALS = 3
// access flags 0x9
public static main([Ljava/lang/String;)V
LDC run : Ljava/lang/Runnable; java/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/Object; (6) [()V, jdk11/AllInstructions.lambda$main$0()V (6), ()V]
......
......@@ -111,6 +111,16 @@ public final class ConstantDynamic {
return bootstrapMethodArguments;
}
/**
* Returns the size of this constant.
*
* @return the size of this constant, i.e., 2 for {@code long} and {@code double}, 1 otherwise.
*/
public int getSize() {
char firstCharOfDescriptor = descriptor.charAt(0);
return (firstCharOfDescriptor == 'J' || firstCharOfDescriptor == 'D') ? 2 : 1;
}
@Override
public boolean equals(final Object object) {
if (object == this) {
......
......@@ -1291,9 +1291,13 @@ final class MethodWriter extends MethodVisitor {
// Add the instruction to the bytecode of the method.
Symbol constantSymbol = symbolTable.addConstant(value);
int constantIndex = constantSymbol.index;
char firstDescriptorChar;
boolean isLongOrDouble =
constantSymbol.tag == Symbol.CONSTANT_LONG_TAG
|| constantSymbol.tag == Symbol.CONSTANT_DOUBLE_TAG;
|| constantSymbol.tag == Symbol.CONSTANT_DOUBLE_TAG
|| (constantSymbol.tag == Symbol.CONSTANT_DYNAMIC_TAG
&& ((firstDescriptorChar = constantSymbol.value.charAt(0)) == 'J'
|| firstDescriptorChar == 'D'));
if (isLongOrDouble) {
code.put12(Constants.LDC2_W, constantIndex);
} else if (constantIndex >= 256) {
......
......@@ -285,7 +285,7 @@ public class ClassReaderTest extends AsmTest implements Opcodes {
ClassVisitor classVisitor = new EmptyClassVisitor(apiParameter.value());
// jdk8.ArtificialStructures contains structures which require ASM5, but only inside the method
// code. Here we skip the code, so this class can be read with ASM4. Likewise for
// jdk11.AllInstructions and jdk11.LambdaCondy.
// jdk11.AllInstructions.
assertThat(() -> classReader.accept(classVisitor, ClassReader.SKIP_CODE))
.succeedsOrThrows(RuntimeException.class)
.when(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment