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:
Alexander Udalov
2014-03-24 21:33:10 +04:00
parent 320a17739d
commit 2c2c918447
@@ -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) {