001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.codegen.inline;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.asm4.Type;
021 import org.jetbrains.asm4.tree.MethodNode;
022 import org.jetbrains.jet.codegen.AsmUtil;
023 import org.jetbrains.jet.codegen.binding.CalculatedClosure;
024 import org.jetbrains.jet.codegen.context.EnclosedValueDescriptor;
025 import org.jetbrains.jet.codegen.state.JetTypeMapper;
026 import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
027 import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
028 import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
029 import org.jetbrains.jet.lang.psi.JetFunctionLiteral;
030 import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
031 import org.jetbrains.jet.lang.resolve.BindingContext;
032 import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
033
034 import java.util.*;
035
036 import static org.jetbrains.jet.codegen.binding.CodegenBinding.CLOSURE;
037 import static org.jetbrains.jet.codegen.binding.CodegenBinding.anonymousClassForFunction;
038 import static org.jetbrains.jet.codegen.binding.CodegenBinding.asmTypeForAnonymousClass;
039
040 public class LambdaInfo implements CapturedParamOwner {
041
042 public final JetFunctionLiteralExpression expression;
043
044 @NotNull
045 private final JetTypeMapper typeMapper;
046
047 public final CalculatedClosure closure;
048
049 private MethodNode node;
050
051 private List<CapturedParamInfo> capturedVars;
052
053 private final FunctionDescriptor functionDescriptor;
054
055 private final ClassDescriptor classDescriptor;
056
057 private final Type closureClassType;
058
059 LambdaInfo(@NotNull JetFunctionLiteralExpression expression, @NotNull JetTypeMapper typeMapper) {
060 this.expression = expression;
061 this.typeMapper = typeMapper;
062 BindingContext bindingContext = typeMapper.getBindingContext();
063 functionDescriptor = bindingContext.get(BindingContext.FUNCTION, expression.getFunctionLiteral());
064 assert functionDescriptor != null : "Function is not resolved to descriptor: " + expression.getText();
065
066 classDescriptor = anonymousClassForFunction(bindingContext, functionDescriptor);
067 closureClassType = asmTypeForAnonymousClass(bindingContext, functionDescriptor);
068
069 closure = bindingContext.get(CLOSURE, classDescriptor);
070
071 }
072
073 public MethodNode getNode() {
074 return node;
075 }
076
077 public void setNode(MethodNode node) {
078 this.node = node;
079 }
080
081 public FunctionDescriptor getFunctionDescriptor() {
082 return functionDescriptor;
083 }
084
085 public JetFunctionLiteral getFunctionLiteral() {
086 return expression.getFunctionLiteral();
087 }
088
089 public ClassDescriptor getClassDescriptor() {
090 return classDescriptor;
091 }
092
093 public Type getLambdaClassType() {
094 return closureClassType;
095 }
096
097 public List<CapturedParamInfo> getCapturedVars() {
098 //lazy initialization cause it would be calculated after object creation
099 int index = 0;
100 if (capturedVars == null) {
101 capturedVars = new ArrayList<CapturedParamInfo>();
102
103 if (closure.getCaptureThis() != null) {
104 EnclosedValueDescriptor descriptor = new EnclosedValueDescriptor(AsmUtil.CAPTURED_THIS_FIELD, null, null, typeMapper.mapType(closure.getCaptureThis()));
105 capturedVars.add(getCapturedParamInfo(descriptor, index));
106 index += descriptor.getType().getSize();
107 }
108
109 if (closure.getCaptureReceiverType() != null) {
110 EnclosedValueDescriptor descriptor = new EnclosedValueDescriptor(AsmUtil.CAPTURED_RECEIVER_FIELD, null, null, typeMapper.mapType(closure.getCaptureReceiverType()));
111 capturedVars.add(getCapturedParamInfo(descriptor, index));
112 index += descriptor.getType().getSize();
113 }
114
115 if (closure != null) {
116 for (EnclosedValueDescriptor descriptor : closure.getCaptureVariables().values()) {
117 capturedVars.add(getCapturedParamInfo(descriptor, index));
118 index += descriptor.getType().getSize();
119 }
120 }
121 }
122 return capturedVars;
123 }
124
125 @NotNull
126 public CapturedParamInfo getCapturedParamInfo(@NotNull EnclosedValueDescriptor descriptor, int index) {
127 return new CapturedParamInfo(CapturedParamDesc.createDesc(this, descriptor.getFieldName(), descriptor.getType()), false, index, -1);
128 }
129
130 public void setParamOffset(int paramOffset) {
131 for (CapturedParamInfo var : getCapturedVars()) {
132 var.setShift(paramOffset);
133 }
134 }
135
136 public List<Type> getParamsWithoutCapturedValOrVar() {
137 Type[] types = typeMapper.mapSignature(functionDescriptor).getAsmMethod().getArgumentTypes();
138 return Arrays.asList(types);
139 }
140
141 public Parameters addAllParameters(@NotNull FieldRemapper remapper) {
142 ParametersBuilder builder = ParametersBuilder.newBuilder();
143 //add skipped this cause inlined lambda doesn't have it
144 builder.addThis(AsmTypeConstants.OBJECT_TYPE, true).setLambda(this);
145
146 List<ValueParameterDescriptor> valueParameters = getFunctionDescriptor().getValueParameters();
147 for (ValueParameterDescriptor parameter : valueParameters) {
148 Type type = typeMapper.mapType(parameter.getType());
149 builder.addNextParameter(type, false, null);
150 }
151
152 remapper.addCapturedFields(this, builder);
153
154 return builder.buildParameters();
155 }
156
157 public int getCapturedVarsSize() {
158 int size = 0;
159 for (CapturedParamInfo next : getCapturedVars()) {
160 size += next.getType().getSize();
161 }
162 return size;
163 }
164
165 @Override
166 public Type getType() {
167 return closureClassType;
168 }
169 }