Skip to content

Commit 6df0696

Browse files
committed
Massively simplify this capturing in lambdas
Signed-off-by: TheSilkMiner <thesilkminer@outlook.com>
1 parent 0e37129 commit 6df0696

7 files changed

Lines changed: 95 additions & 281 deletions

File tree

JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaExpressionVisitor.java

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -498,39 +498,41 @@ public Void visitFunction(FunctionExpression expression) {
498498
final JavaClass thisClass = javaWriter.method.class_;
499499
final String lambdaName = this.javaMangler.mangleLambdaMethod(javaWriter.method.compiled.name, interfaces[0]);
500500
final LambdaClosureInfo closureInfo = LambdaClosureInfo.from(context, expression.closure, thisClass);
501-
final String lambdaDescriptor = calcFunctionDescriptor(thisClass, closureInfo, expression.header);
501+
final String lambdaDescriptor = calcFunctionDescriptor(closureInfo, expression.header);
502502
final JavaNativeMethod lambdaMethod = JavaNativeMethod.getStatic(thisClass, lambdaName, lambdaDescriptor, Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC);
503503
final JavaCompilingMethod lambdaMethodCompiling = JavaMemberVisitor.compileBridgeableMethodNoSideEffect(lambdaMethod, lambdaDescriptor); // TODO("Restore signatures")
504504
final JavaWriter lambdaWriter = new JavaWriter(context.logger, expression.position, javaWriter.clazzVisitor, lambdaMethodCompiling, null);
505505
final CapturedExpressionVisitor<Void> lambdaCapturesVisitor = new JavaCapturedExpressionVisitorLocalRedirectionVisitor(lambdaWriter, expression, closureInfo);
506-
final JavaCompiledModule lambdaModule = new ShiftingJavaCompiledModule(module, closureInfo, context);
507-
final JavaExpressionVisitor lambdaExpressionVisitor = new JavaExpressionVisitor(context, lambdaModule, lambdaWriter, javaMangler, lambdaCapturesVisitor);
506+
final JavaExpressionVisitor lambdaExpressionVisitor = new JavaExpressionVisitor(context, module, lambdaWriter, javaMangler, lambdaCapturesVisitor);
508507
final JavaStatementVisitor lambdaStatementVisitor = new JavaStatementVisitor(context, lambdaExpressionVisitor, javaMangler);
509508

510509
lambdaWriter.start();
511510
expression.body.accept(lambdaStatementVisitor);
512511
lambdaWriter.ret();
513512
lambdaWriter.end();
514513

515-
if (java.lang.reflect.Modifier.isStatic(javaWriter.method.compiled.modifiers) || thisClass.kind == JavaClass.Kind.EXPANSION) {
516-
javaWriter.aConstNull();
517-
} else {
518-
javaWriter.loadObject(0);
514+
final JavaLoadThisOnIndyCapturedExpressionVisitor thisVisitor = new JavaLoadThisOnIndyCapturedExpressionVisitor(this);
515+
final JavaLoadCapturesOnIndyCapturedExpressionVisitor othersVisitor = new JavaLoadCapturesOnIndyCapturedExpressionVisitor(this);
516+
517+
boolean hasLoadedThis = false;
518+
for (final CapturedExpression capture : expression.closure.captures) {
519+
// Note: we want this to be |= to ensure NO short-circuiting behavior
520+
hasLoadedThis |= capture.accept(thisVisitor);
519521
}
520522

521-
if (closureInfo.isDifferentThis()) {
522-
for (final CapturedExpression capture : expression.closure.captures) {
523-
capture.accept(new JavaCapturedExpressionVisitorLoadIndyCapturesVisitor(this, true));
524-
}
523+
// If no this was loaded, then we don't care about its value; just load null
524+
if (!hasLoadedThis) {
525+
javaWriter.aConstNull();
525526
}
527+
526528
for (final CapturedExpression capture : expression.closure.captures) {
527-
capture.accept(new JavaCapturedExpressionVisitorLoadIndyCapturesVisitor(this, false));
529+
capture.accept(othersVisitor);
528530
}
529531

530532
// TODO("Have this in JavaWriter")
531533
javaWriter.getVisitor().visitInvokeDynamicInsn(
532534
methodInfo.name,
533-
calcIndyDescriptor(thisClass, closureInfo, interfaces[0]),
535+
calcIndyDescriptor(closureInfo, interfaces[0]),
534536
new org.objectweb.asm.Handle(
535537
Opcodes.H_INVOKESTATIC,
536538
Type.getInternalName(org.openzen.zenscript.javart.factory.LambdaFactory.class),
@@ -555,14 +557,14 @@ public Void visitFunction(FunctionExpression expression) {
555557
false
556558
),
557559
Type.getMethodType(JavaMemberVisitor.compileBridgeableMethodNoSideEffect(methodInfo, context.getMethodDescriptor(expression.header)).compiled.descriptor),
558-
org.openzen.zenscript.javart.factory.LambdaFactory.FLAG_GENERATE_BRIDGE | (closureInfo.isDifferentThis()? org.openzen.zenscript.javart.factory.LambdaFactory.FLAG_DIFFERENTIATE_RECEIVER : 0),
560+
org.openzen.zenscript.javart.factory.LambdaFactory.FLAG_GENERATE_BRIDGE,
559561
Type.getMethodType(methodInfo.descriptor)
560562
);
561563

562564
return null;
563565
}
564566

565-
private String calcFunctionDescriptor(final JavaClass thisClass, final LambdaClosureInfo closureInfo, final FunctionHeader header) {
567+
private String calcFunctionDescriptor(final LambdaClosureInfo closureInfo, final FunctionHeader header) {
566568
final StringJoiner joiner = new StringJoiner("");
567569
for (final CapturedExpression capture : closureInfo.closure().captures) {
568570
if (!(capture instanceof CapturedThisExpression)) {
@@ -571,19 +573,21 @@ private String calcFunctionDescriptor(final JavaClass thisClass, final LambdaClo
571573
}
572574
}
573575

574-
final String thisDescriptor = closureInfo.isDifferentThis()? context.getDescriptor(closureInfo.thisType()) : "";
575-
576+
// TODO("Remove null check: the method should always return non-null")
577+
final String thisType = closureInfo.thisType() == null? "Ljava/lang/Void;" : context.getDescriptor(closureInfo.thisType());
576578
final StringBuilder builder = new StringBuilder(context.getMethodDescriptor(header));
577-
builder.insert(builder.indexOf("(") + 1, 'L' + thisClass.internalName + ';' + thisDescriptor);
579+
builder.insert(builder.indexOf("(") + 1, thisType);
578580
builder.insert(builder.lastIndexOf(")"), joiner);
579581
return builder.toString();
580582
}
581583

582-
private String calcIndyDescriptor(final JavaClass thisClass, final LambdaClosureInfo closureInfo, final String targetInterface) {
583-
final StringBuilder builder = new StringBuilder("(L");
584-
builder.append(thisClass.internalName).append(';');
584+
private String calcIndyDescriptor(final LambdaClosureInfo closureInfo, final String targetInterface) {
585+
final StringBuilder builder = new StringBuilder("(");
585586

586-
if (closureInfo.isDifferentThis()) {
587+
// TODO("Remove null check as this method should never return null")
588+
if (closureInfo.thisType() == null) {
589+
builder.append("Ljava/lang/Void;");
590+
} else {
587591
builder.append(context.getDescriptor(closureInfo.thisType()));
588592
}
589593

JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/LambdaClosureInfo.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@
33
import org.openzen.zenscript.codemodel.expression.LambdaClosure;
44
import org.openzen.zenscript.codemodel.expression.captured.CapturedExpression;
55
import org.openzen.zenscript.codemodel.expression.captured.CapturedThisExpression;
6+
import org.openzen.zenscript.codemodel.type.BasicTypeID;
7+
import org.openzen.zenscript.codemodel.type.OptionalTypeID;
68
import org.openzen.zenscript.codemodel.type.TypeID;
79
import org.openzen.zenscript.javabytecode.JavaBytecodeContext;
810
import org.openzen.zenscript.javashared.JavaClass;
911

1012
public final class LambdaClosureInfo {
1113
private final LambdaClosure closure;
1214
private final TypeID thisCapture;
13-
private final boolean isDifferent;
1415

15-
private LambdaClosureInfo(final LambdaClosure closure, final TypeID thisCapture, final boolean isDifferent) {
16+
private LambdaClosureInfo(final LambdaClosure closure, final TypeID thisCapture) {
1617
this.closure = closure;
1718
this.thisCapture = thisCapture;
18-
this.isDifferent = isDifferent;
1919
}
2020

2121
static LambdaClosureInfo from(final JavaBytecodeContext context, final LambdaClosure closure, final JavaClass thisClass) {
@@ -27,10 +27,17 @@ static LambdaClosureInfo from(final JavaBytecodeContext context, final LambdaClo
2727
}
2828
}
2929

30-
final TypeID thisType = capturedThis == null? null : capturedThis.type;
31-
final boolean isDifferent = capturedThis != null && !thisClass.internalName.equals(context.getInternalName(capturedThis.type));
30+
final TypeID thisType = computeCapturedThisType(capturedThis);
31+
return new LambdaClosureInfo(closure, thisType);
32+
}
33+
34+
private static TypeID computeCapturedThisType(final CapturedThisExpression expression) {
35+
if (expression != null) {
36+
return expression.type;
37+
}
3238

33-
return new LambdaClosureInfo(closure, thisType, isDifferent);
39+
// TODO("Make this default to void")
40+
return null;
3441
}
3542

3643
public LambdaClosure closure() {
@@ -40,8 +47,4 @@ public LambdaClosure closure() {
4047
public TypeID thisType() {
4148
return this.thisCapture;
4249
}
43-
44-
public boolean isDifferentThis() {
45-
return this.isDifferent;
46-
}
4750
}

JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/ShiftingJavaCompiledModule.java

Lines changed: 0 additions & 176 deletions
This file was deleted.

JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/capturing/JavaCapturedExpressionVisitorLocalRedirectionVisitor.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ public JavaCapturedExpressionVisitorLocalRedirectionVisitor(final JavaWriter jav
3939

4040
@Override
4141
public Void visitCapturedThis(final CapturedThisExpression expression) {
42-
return this.loadByMemberData(
43-
this.closureInfo.isDifferentThis()? new MemberData(1, this.getTypeFrom(this.closureInfo.thisType())) : new MemberData(0, Type.getType(Object.class))
44-
);
42+
// TODO("Remove null-check as this method should never return null")
43+
final Type type = this.closureInfo.thisType() == null? Type.getType(Void.class) : this.getTypeFrom(this.closureInfo.thisType());
44+
return this.loadByMemberData(new MemberData(0, type));
4545
}
4646

4747
@Override
@@ -109,11 +109,6 @@ private MemberData calculateMemberData(final FunctionExpression expression, fina
109109

110110
private int findFirstValidCaptureIndex(final FunctionExpression expression) {
111111
int h = 1;
112-
113-
if (this.closureInfo.isDifferentThis()) {
114-
h += this.getTypeFrom(this.closureInfo.thisType()).getSize();
115-
}
116-
117112
for (final FunctionParameter parameter : expression.header.parameters) {
118113
h += this.getTypeFrom(parameter.type).getSize();
119114
}
@@ -142,6 +137,6 @@ private Type getTypeFrom(final TypeID type) {
142137

143138
// We don't care about the actual class contained in the type here, we only care that Java treats it as an
144139
// object, so we simply grab a random Java class
145-
return Type.getType(Object.class);
140+
return Type.getType(Void.class);
146141
}
147142
}

0 commit comments

Comments
 (0)