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() { 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 for (CapturedParamInfo info : getCapturedVars()) { 153 builder.addCapturedParam(info, info.getOriginalFieldName()); 154 } 155 156 return builder.buildParameters(); 157 } 158 159 public int getCapturedVarsSize() { 160 int size = 0; 161 for (CapturedParamInfo next : getCapturedVars()) { 162 size += next.getType().getSize(); 163 } 164 return size; 165 } 166 167 @Override 168 public Type getType() { 169 return closureClassType; 170 } 171 }