Refactor bridges algorithm in codegen
- fix a typo (which apparently didn't matter) - queue now always contains originals, no need to invoke getOriginal() - no need to add current descriptor's original anymore, this was a hack working around a problem with trait-impl which was fixed by another change - a small optimization: don't do anything for constructors
This commit is contained in:
@@ -414,22 +414,18 @@ public class FunctionCodegen extends ParentCodegenAwareImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateBridgeIfNeeded(@NotNull FunctionDescriptor functionDescriptor) {
|
private void generateBridgeIfNeeded(@NotNull FunctionDescriptor functionDescriptor) {
|
||||||
if (owner.getContextKind() == OwnerKind.TRAIT_IMPL) {
|
if (functionDescriptor instanceof ConstructorDescriptor) return;
|
||||||
return;
|
if (owner.getContextKind() == OwnerKind.TRAIT_IMPL) return;
|
||||||
}
|
|
||||||
|
|
||||||
Method method = state.getTypeMapper().mapSignature(functionDescriptor).getAsmMethod();
|
Method method = typeMapper.mapSignature(functionDescriptor).getAsmMethod();
|
||||||
|
|
||||||
Queue<FunctionDescriptor> bfsQueue = new LinkedList<FunctionDescriptor>();
|
Queue<FunctionDescriptor> bfsQueue = new LinkedList<FunctionDescriptor>();
|
||||||
Set<FunctionDescriptor> visited = new HashSet<FunctionDescriptor>();
|
Set<FunctionDescriptor> visited = new HashSet<FunctionDescriptor>();
|
||||||
|
|
||||||
bfsQueue.offer(functionDescriptor.getOriginal());
|
|
||||||
visited.add(functionDescriptor.getOriginal());
|
|
||||||
for (FunctionDescriptor overriddenDescriptor : functionDescriptor.getOverriddenDescriptors()) {
|
for (FunctionDescriptor overriddenDescriptor : functionDescriptor.getOverriddenDescriptors()) {
|
||||||
FunctionDescriptor orig = overriddenDescriptor.getOriginal();
|
FunctionDescriptor orig = overriddenDescriptor.getOriginal();
|
||||||
if (!visited.contains(orig)) {
|
if (visited.add(orig)) {
|
||||||
bfsQueue.offer(overriddenDescriptor);
|
bfsQueue.offer(orig);
|
||||||
visited.add(overriddenDescriptor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,7 +433,7 @@ public class FunctionCodegen extends ParentCodegenAwareImpl {
|
|||||||
while (!bfsQueue.isEmpty()) {
|
while (!bfsQueue.isEmpty()) {
|
||||||
FunctionDescriptor descriptor = bfsQueue.poll();
|
FunctionDescriptor descriptor = bfsQueue.poll();
|
||||||
if (descriptor.getKind() == CallableMemberDescriptor.Kind.DECLARATION) {
|
if (descriptor.getKind() == CallableMemberDescriptor.Kind.DECLARATION) {
|
||||||
Method overridden = state.getTypeMapper().mapSignature(descriptor.getOriginal()).getAsmMethod();
|
Method overridden = typeMapper.mapSignature(descriptor).getAsmMethod();
|
||||||
if (differentMethods(method, overridden)) {
|
if (differentMethods(method, overridden)) {
|
||||||
bridgesToGenerate.add(overridden);
|
bridgesToGenerate.add(overridden);
|
||||||
}
|
}
|
||||||
@@ -446,15 +442,17 @@ public class FunctionCodegen extends ParentCodegenAwareImpl {
|
|||||||
|
|
||||||
for (FunctionDescriptor overriddenDescriptor : descriptor.getOverriddenDescriptors()) {
|
for (FunctionDescriptor overriddenDescriptor : descriptor.getOverriddenDescriptors()) {
|
||||||
FunctionDescriptor orig = overriddenDescriptor.getOriginal();
|
FunctionDescriptor orig = overriddenDescriptor.getOriginal();
|
||||||
if (!visited.contains(orig)) {
|
if (visited.add(orig)) {
|
||||||
bfsQueue.offer(orig);
|
bfsQueue.offer(orig);
|
||||||
visited.add(orig);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Method overridden : bridgesToGenerate) {
|
if (!bridgesToGenerate.isEmpty()) {
|
||||||
generateBridge(state, v, functionDescriptor, overridden);
|
PsiElement origin = callableDescriptorToDeclaration(bindingContext, functionDescriptor);
|
||||||
|
for (Method bridge : bridgesToGenerate) {
|
||||||
|
generateBridge(origin, bridge, method);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -723,23 +721,16 @@ public class FunctionCodegen extends ParentCodegenAwareImpl {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void generateBridge(
|
private void generateBridge(@Nullable PsiElement origin, @NotNull Method bridge, @NotNull Method delegateTo) {
|
||||||
GenerationState state,
|
|
||||||
ClassBuilder v,
|
|
||||||
FunctionDescriptor functionDescriptor,
|
|
||||||
Method overridden
|
|
||||||
) {
|
|
||||||
Method jvmSignature = state.getTypeMapper().mapSignature(functionDescriptor).getAsmMethod();
|
|
||||||
|
|
||||||
int flags = ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC; // TODO.
|
int flags = ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC; // TODO.
|
||||||
|
|
||||||
MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overridden.getDescriptor(), null, null);
|
MethodVisitor mv = v.newMethod(null, flags, delegateTo.getName(), bridge.getDescriptor(), null, null);
|
||||||
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
|
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
|
||||||
|
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
|
|
||||||
Type[] argTypes = overridden.getArgumentTypes();
|
Type[] argTypes = bridge.getArgumentTypes();
|
||||||
Type[] originalArgTypes = jvmSignature.getArgumentTypes();
|
Type[] originalArgTypes = delegateTo.getArgumentTypes();
|
||||||
|
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
iv.load(0, OBJECT_TYPE);
|
iv.load(0, OBJECT_TYPE);
|
||||||
@@ -749,12 +740,12 @@ public class FunctionCodegen extends ParentCodegenAwareImpl {
|
|||||||
reg += argTypes[i].getSize();
|
reg += argTypes[i].getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
iv.invokevirtual(v.getThisName(), jvmSignature.getName(), jvmSignature.getDescriptor());
|
iv.invokevirtual(v.getThisName(), delegateTo.getName(), delegateTo.getDescriptor());
|
||||||
|
|
||||||
StackValue.coerce(jvmSignature.getReturnType(), overridden.getReturnType(), iv);
|
StackValue.coerce(delegateTo.getReturnType(), bridge.getReturnType(), iv);
|
||||||
iv.areturn(overridden.getReturnType());
|
iv.areturn(bridge.getReturnType());
|
||||||
|
|
||||||
endVisit(mv, "bridge method", callableDescriptorToDeclaration(state.getBindingContext(), functionDescriptor));
|
endVisit(mv, "bridge method", origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void genDelegate(FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenDescriptor, StackValue field) {
|
public void genDelegate(FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenDescriptor, StackValue field) {
|
||||||
|
|||||||
Reference in New Issue
Block a user