diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index b83f66d532f..32b2568f2cb 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -53,7 +53,6 @@ import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.java.*; import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode; -import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.receivers.*; import org.jetbrains.jet.lang.types.JetType; @@ -1888,24 +1887,14 @@ public class ExpressionCodegen extends JetVisitor implem return invokeFunction(call, receiver, resolvedCall); } - @Nullable - private FunctionDescriptor getOriginalIfSamAdapter(@NotNull CallableDescriptor fun) { - if (!(fun instanceof FunctionDescriptor)) { - return null; + private void samAwareGen(@NotNull JetExpression expression, @NotNull Type defaultType) { + ClassDescriptorFromJvmBytecode samInterface = bindingContext.get(CodegenBinding.SAM_VALUE, expression); + if (samInterface != null) { + genSamInterfaceValue(expression, samInterface); } - FunctionDescriptor original = ((FunctionDescriptor) fun).getOriginal(); - if (original.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) { - return bindingContext.get(JavaBindingContext.SAM_ADAPTER_FUNCTION_TO_ORIGINAL, original); + else { + gen(expression, defaultType); } - if (original.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { - for (FunctionDescriptor overridden : original.getOverriddenDescriptors()) { - FunctionDescriptor originalIfSamAdapter = getOriginalIfSamAdapter(overridden); - if (originalIfSamAdapter != null) { - return originalIfSamAdapter; - } - } - } - return null; } private StackValue invokeSamConstructor( @@ -2064,7 +2053,8 @@ public class ExpressionCodegen extends JetVisitor implem return typeMapper.mapToFunctionInvokeCallableMethod(createInvoke(fd)); } else { - SimpleFunctionDescriptor originalOfSamAdapter = (SimpleFunctionDescriptor) getOriginalIfSamAdapter(fd); + SimpleFunctionDescriptor originalOfSamAdapter = (SimpleFunctionDescriptor) SamCodegenUtil + .getOriginalIfSamAdapter(bindingContext, fd); return typeMapper.mapToCallableMethod(originalOfSamAdapter != null ? originalOfSamAdapter : fd, superCall, isCallInsideSameClassAsDeclared(fd, context), isCallInsideSameModuleAsDeclared(fd, context), @@ -2298,31 +2288,19 @@ public class ExpressionCodegen extends JetVisitor implem int mask = 0; - FunctionDescriptor originalOfSamAdapter = getOriginalIfSamAdapter(fd); - for (ValueParameterDescriptor valueParameter : fd.getValueParameters()) { ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex()); + Type parameterType = valueParameterTypes.get(valueParameter.getIndex()); if (resolvedValueArgument instanceof ExpressionValueArgument) { ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument(); assert valueArgument != null; JetExpression argumentExpression = valueArgument.getArgumentExpression(); assert argumentExpression != null : valueArgument.asElement().getText(); - if (originalOfSamAdapter != null) { - JetType samAdapterType = originalOfSamAdapter.getValueParameters().get(valueParameter.getIndex()).getType(); - if (SingleAbstractMethodUtils.isSamType(samAdapterType)) { - ClassDescriptorFromJvmBytecode samInterface = (ClassDescriptorFromJvmBytecode) samAdapterType.getConstructor().getDeclarationDescriptor(); - assert samInterface != null; - - genSamInterfaceValue(argumentExpression, samInterface); - continue; - } - } - gen(argumentExpression, valueParameterTypes.get(valueParameter.getIndex())); + samAwareGen(argumentExpression, parameterType); } else if (resolvedValueArgument instanceof DefaultValueArgument) { - Type type = valueParameterTypes.get(valueParameter.getIndex()); - pushDefaultValueOnStack(type, v); + pushDefaultValueOnStack(parameterType, v); mask |= (1 << valueParameter.getIndex()); } else if (resolvedValueArgument instanceof VarargValueArgument) { @@ -3274,7 +3252,8 @@ public class ExpressionCodegen extends JetVisitor implem //See StackValue.receiver for more info pushClosureOnStack(closure, resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists()); - ConstructorDescriptor originalOfSamAdapter = (ConstructorDescriptor) getOriginalIfSamAdapter(constructorDescriptor); + ConstructorDescriptor originalOfSamAdapter = (ConstructorDescriptor) SamCodegenUtil + .getOriginalIfSamAdapter(bindingContext, constructorDescriptor); CallableMethod method = typeMapper.mapToCallableMethod(originalOfSamAdapter == null ? constructorDescriptor : originalOfSamAdapter); invokeMethodWithArguments(method, resolvedCall, null, StackValue.none()); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/SamCodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/SamCodegenUtil.java new file mode 100644 index 00000000000..9b967cd5918 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/SamCodegenUtil.java @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.codegen; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.java.JavaBindingContext; + +public class SamCodegenUtil { + @Nullable + public static FunctionDescriptor getOriginalIfSamAdapter(@NotNull BindingContext bindingContext, @NotNull CallableDescriptor fun) { + if (!(fun instanceof FunctionDescriptor)) { + return null; + } + FunctionDescriptor original = ((FunctionDescriptor) fun).getOriginal(); + if (original.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) { + return bindingContext.get(JavaBindingContext.SAM_ADAPTER_FUNCTION_TO_ORIGINAL, original); + } + if (original.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { + for (FunctionDescriptor overridden : original.getOverriddenDescriptors()) { + FunctionDescriptor originalIfSamAdapter = getOriginalIfSamAdapter(bindingContext, overridden); + if (originalIfSamAdapter != null) { + return originalIfSamAdapter; + } + } + } + return null; + } + + private SamCodegenUtil() { + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java index c5059c40757..da5904adfd4 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.codegen.binding; import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.SamCodegenUtil; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorImpl; @@ -26,10 +27,14 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.calls.model.ExpressionValueArgument; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; +import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.java.PackageClassUtils; +import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode; +import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; @@ -37,6 +42,7 @@ import org.jetbrains.jet.lang.types.JetType; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import static org.jetbrains.jet.codegen.CodegenUtil.peekFromStack; @@ -339,4 +345,50 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { return null; } } + + @Override + public void visitCallExpression(JetCallExpression expression) { + super.visitCallExpression(expression); + ResolvedCall call = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression()); + if (call == null) { + return; + } + + CallableDescriptor descriptor = call.getResultingDescriptor(); + if (!(descriptor instanceof FunctionDescriptor)) { + return; + } + FunctionDescriptor original = SamCodegenUtil.getOriginalIfSamAdapter(bindingContext, descriptor); + + if (original == null) { + return; + } + List valueArguments = call.getValueArgumentsByIndex(); + for (ValueParameterDescriptor valueParameter : original.getValueParameters()) { + ClassDescriptorFromJvmBytecode samInterface = getInterfaceIfSamType(valueParameter.getType()); + if (samInterface == null) { + continue; + } + + ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex()); + assert resolvedValueArgument instanceof ExpressionValueArgument : resolvedValueArgument; + ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument(); + assert valueArgument != null; + JetExpression argumentExpression = valueArgument.getArgumentExpression(); + assert argumentExpression != null : valueArgument.asElement().getText(); + + bindingTrace.record(CodegenBinding.SAM_VALUE, argumentExpression, samInterface); + } + } + + @Nullable + private static ClassDescriptorFromJvmBytecode getInterfaceIfSamType(@NotNull JetType originalType) { + if (!SingleAbstractMethodUtils.isSamType(originalType)) { + return null; + } + ClassDescriptorFromJvmBytecode samInterface = + (ClassDescriptorFromJvmBytecode) originalType.getConstructor().getDeclarationDescriptor(); + assert samInterface != null; + return samInterface; + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java index c8128c8b5d2..20b2f66c69a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java @@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmClassName; +import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; @@ -57,6 +58,8 @@ public class CodegenBinding { public static final WritableSlice> INNER_CLASSES = Slices.createSimpleSlice(); + public static final WritableSlice SAM_VALUE = Slices.createSimpleSlice(); + private CodegenBinding() { }