Construction invocation simplification
This commit is contained in:
@@ -25,7 +25,7 @@ public class ConstructorInvocation {
|
|||||||
|
|
||||||
private final String ownerInternalName;
|
private final String ownerInternalName;
|
||||||
|
|
||||||
private final Map<Integer, InvokeCall> access;
|
private final Map<Integer, LambdaInfo> lambdasToInline;
|
||||||
|
|
||||||
private final boolean isSameModule;
|
private final boolean isSameModule;
|
||||||
|
|
||||||
@@ -37,9 +37,9 @@ public class ConstructorInvocation {
|
|||||||
|
|
||||||
private Map<String, LambdaInfo> recapturedLambdas;
|
private Map<String, LambdaInfo> recapturedLambdas;
|
||||||
|
|
||||||
ConstructorInvocation(String ownerInternalName, Map<Integer, InvokeCall> access, boolean isSameModule) {
|
ConstructorInvocation(String ownerInternalName, Map<Integer, LambdaInfo> lambdasToInline, boolean isSameModule) {
|
||||||
this.ownerInternalName = ownerInternalName;
|
this.ownerInternalName = ownerInternalName;
|
||||||
this.access = access;
|
this.lambdasToInline = lambdasToInline;
|
||||||
this.isSameModule = isSameModule;
|
this.isSameModule = isSameModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,12 +47,12 @@ public class ConstructorInvocation {
|
|||||||
return ownerInternalName;
|
return ownerInternalName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInlinable() {
|
public boolean shouldRegenerate() {
|
||||||
return !access.isEmpty() || !isSameModule;
|
return !lambdasToInline.isEmpty() || !isSameModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Integer, InvokeCall> getAccess() {
|
public Map<Integer, LambdaInfo> getLambdasToInline() {
|
||||||
return access;
|
return lambdasToInline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ public class LambdaTransformer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void extractParametersMapping(MethodNode constructor, ParametersBuilder builder, ConstructorInvocation invocation) {
|
private void extractParametersMapping(MethodNode constructor, ParametersBuilder builder, ConstructorInvocation invocation) {
|
||||||
Map<Integer, InvokeCall> indexToLambda = invocation.getAccess();
|
Map<Integer, LambdaInfo> indexToLambda = invocation.getLambdasToInline();
|
||||||
|
|
||||||
AbstractInsnNode cur = constructor.instructions.getFirst();
|
AbstractInsnNode cur = constructor.instructions.getFirst();
|
||||||
cur = cur.getNext(); //skip super call
|
cur = cur.getNext(); //skip super call
|
||||||
@@ -202,13 +202,10 @@ public class LambdaTransformer {
|
|||||||
paramMapping.put(fieldNode.name, varIndex);
|
paramMapping.put(fieldNode.name, varIndex);
|
||||||
|
|
||||||
CapturedParamInfo info = builder.addCapturedParam(fieldNode.name, Type.getType(fieldNode.desc), false, null);
|
CapturedParamInfo info = builder.addCapturedParam(fieldNode.name, Type.getType(fieldNode.desc), false, null);
|
||||||
InvokeCall access = indexToLambda.get(varIndex);
|
LambdaInfo LambdaInfo = indexToLambda.get(varIndex);
|
||||||
if (access != null) {
|
if (LambdaInfo != null) {
|
||||||
LambdaInfo accessInfo = access.lambdaInfo;
|
info.setLambda(LambdaInfo);
|
||||||
if (accessInfo != null) {
|
additionalCaptured.add(LambdaInfo);
|
||||||
info.setLambda(accessInfo);
|
|
||||||
additionalCaptured.add(accessInfo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cur = cur.getNext();
|
cur = cur.getNext();
|
||||||
|
|||||||
@@ -119,19 +119,20 @@ public class MethodInliner {
|
|||||||
if (isLambdaConstructorCall(type.getInternalName(), "<init>")) {
|
if (isLambdaConstructorCall(type.getInternalName(), "<init>")) {
|
||||||
invocation = iterator.next();
|
invocation = iterator.next();
|
||||||
|
|
||||||
if (invocation.isInlinable()) {
|
if (invocation.shouldRegenerate()) {
|
||||||
//TODO: need poping of type but what to do with local funs???
|
//TODO: need poping of type but what to do with local funs???
|
||||||
Type newLambdaType = Type.getObjectType(parent.nameGenerator.genLambdaClassName());
|
Type newLambdaType = Type.getObjectType(parent.nameGenerator.genLambdaClassName());
|
||||||
currentTypeMapping.put(invocation.getOwnerInternalName(), newLambdaType.getInternalName());
|
currentTypeMapping.put(invocation.getOwnerInternalName(), newLambdaType.getInternalName());
|
||||||
LambdaTransformer transformer = new LambdaTransformer(invocation.getOwnerInternalName(), parent.subInline(parent.nameGenerator, currentTypeMapping),
|
LambdaTransformer transformer = new LambdaTransformer(invocation.getOwnerInternalName(),
|
||||||
|
parent.subInline(parent.nameGenerator, currentTypeMapping),
|
||||||
isSameModule, newLambdaType);
|
isSameModule, newLambdaType);
|
||||||
|
|
||||||
transformer.doTransform(invocation);
|
transformer.doTransform(invocation);
|
||||||
}
|
}
|
||||||
super.anew(type);
|
|
||||||
} else {
|
|
||||||
super.anew(type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//in case of regenerated invocation type would be remapped to new one via remappingMethodAdapter
|
||||||
|
super.anew(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -167,12 +168,11 @@ public class MethodInliner {
|
|||||||
}
|
}
|
||||||
else if (isLambdaConstructorCall(owner, name)) { //TODO add method
|
else if (isLambdaConstructorCall(owner, name)) { //TODO add method
|
||||||
assert invocation != null : "<init> call not corresponds to new call" + owner + " " + name;
|
assert invocation != null : "<init> call not corresponds to new call" + owner + " " + name;
|
||||||
if (invocation.isInlinable()) {
|
if (invocation.shouldRegenerate()) {
|
||||||
//put additional captured parameters on stack
|
//put additional captured parameters on stack
|
||||||
List<CapturedParamInfo> recaptured = invocation.getRecaptured();
|
List<CapturedParamInfo> recaptured = invocation.getRecaptured();
|
||||||
|
List<CapturedParamInfo> contextCaptured = MethodInliner.this.parameters.getCaptured();
|
||||||
for (CapturedParamInfo capturedParamInfo : recaptured) {
|
for (CapturedParamInfo capturedParamInfo : recaptured) {
|
||||||
Type type = capturedParamInfo.getType();
|
|
||||||
List<CapturedParamInfo> contextCaptured = MethodInliner.this.parameters.getCaptured();
|
|
||||||
CapturedParamInfo result = null;
|
CapturedParamInfo result = null;
|
||||||
for (CapturedParamInfo info : contextCaptured) {
|
for (CapturedParamInfo info : contextCaptured) {
|
||||||
//TODO more sophisticated check
|
//TODO more sophisticated check
|
||||||
@@ -180,7 +180,12 @@ public class MethodInliner {
|
|||||||
result = info;
|
result = info;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super.visitVarInsn(type.getOpcode(Opcodes.ILOAD), result.getIndex());
|
if (result == null) {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"Unsupported operation: could not transform non-inline lambda inside inlined one: " +
|
||||||
|
owner + "." + name);
|
||||||
|
}
|
||||||
|
super.visitVarInsn(capturedParamInfo.getType().getOpcode(Opcodes.ILOAD), result.getIndex());
|
||||||
}
|
}
|
||||||
super.visitMethodInsn(opcode, invocation.getNewLambdaType().getInternalName(), name, invocation.getNewConstructorDescriptor());
|
super.visitMethodInsn(opcode, invocation.getNewLambdaType().getInternalName(), name, invocation.getNewConstructorDescriptor());
|
||||||
invocation = null;
|
invocation = null;
|
||||||
@@ -296,25 +301,25 @@ public class MethodInliner {
|
|||||||
invokeCalls.add(new InvokeCall(varIndex, lambdaInfo));
|
invokeCalls.add(new InvokeCall(varIndex, lambdaInfo));
|
||||||
}
|
}
|
||||||
else if (isLambdaConstructorCall(owner, name)) {
|
else if (isLambdaConstructorCall(owner, name)) {
|
||||||
Map<Integer, InvokeCall> infos = new HashMap<Integer, InvokeCall>();
|
Map<Integer, LambdaInfo> lambdaMapping = new HashMap<Integer, LambdaInfo>();
|
||||||
int paramStart = frame.getStackSize() - paramLength;
|
int paramStart = frame.getStackSize() - paramLength;
|
||||||
|
|
||||||
for (int i = 0; i < paramLength; i++) {
|
for (int i = 0; i < paramLength; i++) {
|
||||||
SourceValue sourceValue = frame.getStack(paramStart + i);
|
SourceValue sourceValue = frame.getStack(paramStart + i);
|
||||||
if (sourceValue.insns.size() == 1) {
|
if (sourceValue.insns.size() == 1) {
|
||||||
AbstractInsnNode insnNode = sourceValue.insns.iterator().next();
|
AbstractInsnNode insnNode = sourceValue.insns.iterator().next();
|
||||||
if (insnNode.getType() == AbstractInsnNode.VAR_INSN && insnNode.getOpcode() == Opcodes.ALOAD) {
|
if (insnNode.getOpcode() == Opcodes.ALOAD) {
|
||||||
int varIndex = ((VarInsnNode) insnNode).var;
|
int varIndex = ((VarInsnNode) insnNode).var;
|
||||||
LambdaInfo lambdaInfo = getLambda(varIndex);
|
LambdaInfo lambdaInfo = getLambda(varIndex);
|
||||||
if (lambdaInfo != null) {
|
if (lambdaInfo != null) {
|
||||||
infos.put(i, new InvokeCall(varIndex, lambdaInfo));
|
lambdaMapping.put(i, lambdaInfo);
|
||||||
node.instructions.remove(insnNode);
|
node.instructions.remove(insnNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructorInvocations.add(new ConstructorInvocation(owner, infos, isSameModule));
|
constructorInvocations.add(new ConstructorInvocation(owner, lambdaMapping, isSameModule));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -456,6 +461,9 @@ public class MethodInliner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: check annotation on class - it's package part
|
||||||
|
//TODO: check it's external module
|
||||||
|
//TODO?: assert method exists in facade?
|
||||||
public String changeOwnerForExternalPackage(String type, int opcode) {
|
public String changeOwnerForExternalPackage(String type, int opcode) {
|
||||||
if (isSameModule || (opcode & Opcodes.INVOKESTATIC) == 0) {
|
if (isSameModule || (opcode & Opcodes.INVOKESTATIC) == 0) {
|
||||||
return type;
|
return type;
|
||||||
|
|||||||
Reference in New Issue
Block a user