Skip to content

Commit

Permalink
Refactor boot strap method branch (#500)
Browse files Browse the repository at this point in the history
* add Tests to test record feature of jpf

* modify the setBootstrapMethod(...) to adapt Java-17 requirement

* Refactor JVMClassInfo.setBootstrapMethod(...)
  • Loading branch information
eklaDFF authored Oct 10, 2024
1 parent 4ffa7e9 commit 80c9660
Showing 1 changed file with 67 additions and 54 deletions.
121 changes: 67 additions & 54 deletions src/main/gov/nasa/jpf/jvm/JVMClassInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,70 +99,83 @@ public void setBootstrapMethod (ClassFile cf, Object tag, int idx, int refKind,
ClassInfo enclosingLambdaCls;

if (cls.equals("java/lang/invoke/LambdaMetafactory") && (mth.equals("metafactory") || mth.equals("altMetafactory"))) {
assert(cpArgs.length>1);
// For Lambdas
int mrefIdx = cf.mhMethodRefIndexAt(cpArgs[1]);
clsName = cf.methodClassNameAt(mrefIdx).replace('/', '.');

if(!clsName.equals(JVMClassInfo.this.getName())) {
if (JVMClassInfo.resolvedClasses.containsKey(clsName))
enclosingLambdaCls = (JVMClassInfo) JVMClassInfo.resolvedClasses.get(clsName);
else
enclosingLambdaCls = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
} else {
enclosingLambdaCls = JVMClassInfo.this;
JVMClassInfo.resolvedClasses.put(clsName, enclosingLambdaCls);
}

// The following check should be up-to-date
// with OpenJDK 11' implementation of
// java.lang.invoke.LambdaMetafactory::altMetafactory()
//
// Check if it is serializable lambda expression. It is if:
// 1. bootstrap method is "altMetafactory"
// 2. 4-th cp arg value has FLAG_SERIALIZABLE (1 << 0) bit set
// The check order cannot be reversed since other BSM may not
// have forth argument in `cpArgs`
boolean isSerializable = false;
if (cls.equals("java/lang/invoke/LambdaMetafactory")
&& mth.equals("altMetafactory")) {
int flags = cf.intAt(cpArgs[3]);
int FLAG_SERIALIZABLE = 1 << 0;
if ((flags & FLAG_SERIALIZABLE) != 0) {
isSerializable = true;
}
}
lambdaMetaFactory(cf,idx,cls,mth,cpArgs);
} else if (cls.equals("java/lang/runtime/ObjectMethods") && mth.equals("bootstrap")) {
objectMethodsBootstrap(cf,tag,idx,refKind,cls,mth,parameters,descriptor,cpArgs);
} else {
// For String Concatenation
stringConcatenation(cf,idx,refKind,cls,mth,parameters,descriptor,cpArgs);
}

assert (enclosingLambdaCls!=null);
}
private void lambdaMetaFactory(ClassFile cf, int idx, String cls, String mth, int[] cpArgs){
String clsName;
ClassInfo enclosingLambdaCls;

int lambdaRefKind = cf.mhRefTypeAt(cpArgs[1]);
String mthName = cf.methodNameAt(mrefIdx);
String signature = cf.methodDescriptorAt(mrefIdx);
String samDescriptor = cf.methodTypeDescriptorAt(cpArgs[2]);
assert (cpArgs.length > 1);
// For Lambdas
int mrefIdx = cf.mhMethodRefIndexAt(cpArgs[1]);
clsName = cf.methodClassNameAt(mrefIdx).replace('/', '.');

setBootstrapMethodInfo(enclosingLambdaCls, mthName, signature, idx, lambdaRefKind, samDescriptor, null,
isSerializable ? BootstrapMethodInfo.BMType.SERIALIZABLE_LAMBDA_EXPRESSION
: BootstrapMethodInfo.BMType.LAMBDA_EXPRESSION);
} else if (cls.equals("java/lang/runtime/ObjectMethods") && mth.equals("bootstrap")) {
// -----
if (!clsName.equals(JVMClassInfo.this.getName())) {
if (JVMClassInfo.resolvedClasses.containsKey(clsName))
enclosingLambdaCls = (JVMClassInfo) JVMClassInfo.resolvedClasses.get(clsName);
else
enclosingLambdaCls = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
} else {
// For String Concatenation
clsName = cls;
assert(mth.startsWith("makeConcat"));
if(!clsName.equals(JVMClassInfo.this.getName())) {
enclosingLambdaCls = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
} else {
enclosingLambdaCls = JVMClassInfo.this;
enclosingLambdaCls = JVMClassInfo.this;
JVMClassInfo.resolvedClasses.put(clsName, enclosingLambdaCls);
}

// The following check should be up-to-date
// with OpenJDK 11' implementation of
// java.lang.invoke.LambdaMetafactory::altMetafactory()
//
// Check if it is serializable lambda expression. It is if:
// 1. bootstrap method is "altMetafactory"
// 2. 4-th cp arg value has FLAG_SERIALIZABLE (1 << 0) bit set
// The check order cannot be reversed since other BSM may not
// have forth argument in `cpArgs`
boolean isSerializable = false;
if (cls.equals("java/lang/invoke/LambdaMetafactory")
&& mth.equals("altMetafactory")) {
int flags = cf.intAt(cpArgs[3]);
int FLAG_SERIALIZABLE = 1 << 0;
if ((flags & FLAG_SERIALIZABLE) != 0) {
isSerializable = true;
}
}

assert (enclosingLambdaCls!=null);
assert (enclosingLambdaCls != null);

String bmArg = cf.getBmArgString(cpArgs[0]);
int lambdaRefKind = cf.mhRefTypeAt(cpArgs[1]);
String mthName = cf.methodNameAt(mrefIdx);
String signature = cf.methodDescriptorAt(mrefIdx);
String samDescriptor = cf.methodTypeDescriptorAt(cpArgs[2]);

setBootstrapMethodInfo(enclosingLambdaCls, mth, parameters, idx, refKind, descriptor, bmArg,
BootstrapMethodInfo.BMType.STRING_CONCATENATION);
setBootstrapMethodInfo(enclosingLambdaCls, mthName, signature, idx, lambdaRefKind, samDescriptor, null,
isSerializable ? BootstrapMethodInfo.BMType.SERIALIZABLE_LAMBDA_EXPRESSION
: BootstrapMethodInfo.BMType.LAMBDA_EXPRESSION);
}
private void objectMethodsBootstrap(ClassFile cf, Object tag, int idx, int refKind, String cls, String mth, String parameters, String descriptor, int[] cpArgs){
//-----
}
private void stringConcatenation(ClassFile cf, int idx, int refKind, String cls, String mth, String parameters, String descriptor, int[] cpArgs){
String clsName = cls;
ClassInfo enclosingLambdaCls;
assert(mth.startsWith("makeConcat"));
if(!clsName.equals(JVMClassInfo.this.getName())) {
enclosingLambdaCls = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
} else {
enclosingLambdaCls = JVMClassInfo.this;
}

assert (enclosingLambdaCls!=null);

String bmArg = cf.getBmArgString(cpArgs[0]);

setBootstrapMethodInfo(enclosingLambdaCls, mth, parameters, idx, refKind, descriptor, bmArg,
BootstrapMethodInfo.BMType.STRING_CONCATENATION);
}

// helper method for setBootstrapMethod()
Expand Down

0 comments on commit 80c9660

Please sign in to comment.