001    /*
002    /*
003     * Copyright 2010-2013 JetBrains s.r.o.
004     *
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     * http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.jetbrains.jet.codegen;
019    
020    import com.intellij.openapi.progress.ProcessCanceledException;
021    import com.intellij.psi.PsiElement;
022    import com.intellij.util.ArrayUtil;
023    import com.intellij.util.Function;
024    import com.intellij.util.containers.ContainerUtil;
025    import kotlin.Function1;
026    import org.jetbrains.annotations.NotNull;
027    import org.jetbrains.annotations.Nullable;
028    import org.jetbrains.jet.codegen.binding.CodegenBinding;
029    import org.jetbrains.jet.codegen.bridges.Bridge;
030    import org.jetbrains.jet.codegen.bridges.BridgesPackage;
031    import org.jetbrains.jet.codegen.context.CodegenContext;
032    import org.jetbrains.jet.codegen.context.MethodContext;
033    import org.jetbrains.jet.codegen.context.PackageFacadeContext;
034    import org.jetbrains.jet.codegen.state.GenerationState;
035    import org.jetbrains.jet.codegen.state.JetTypeMapper;
036    import org.jetbrains.jet.lang.descriptors.*;
037    import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
038    import org.jetbrains.jet.lang.psi.JetNamedFunction;
039    import org.jetbrains.jet.lang.resolve.BindingContext;
040    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
041    import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
042    import org.jetbrains.jet.lang.resolve.constants.ArrayValue;
043    import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
044    import org.jetbrains.jet.lang.resolve.constants.JavaClassValue;
045    import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterKind;
046    import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterSignature;
047    import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature;
048    import org.jetbrains.jet.lang.resolve.name.FqName;
049    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
050    import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
051    import org.jetbrains.org.objectweb.asm.Label;
052    import org.jetbrains.org.objectweb.asm.MethodVisitor;
053    import org.jetbrains.org.objectweb.asm.Type;
054    import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
055    import org.jetbrains.org.objectweb.asm.commons.Method;
056    import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor;
057    
058    import java.io.PrintWriter;
059    import java.io.StringWriter;
060    import java.util.Collection;
061    import java.util.Iterator;
062    import java.util.List;
063    import java.util.Set;
064    
065    import static org.jetbrains.jet.codegen.AsmUtil.*;
066    import static org.jetbrains.jet.codegen.JvmSerializationBindings.*;
067    import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalNamedFun;
068    import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.DECLARATION;
069    import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration;
070    import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
071    import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isFunctionLiteral;
072    import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isTrait;
073    import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
074    import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.OLD_JET_VALUE_PARAMETER_ANNOTATION;
075    import static org.jetbrains.org.objectweb.asm.Opcodes.*;
076    
077    public class FunctionCodegen extends ParentCodegenAware {
078        private final CodegenContext owner;
079    
080        private final ClassBuilder v;
081    
082        public FunctionCodegen(
083                @NotNull CodegenContext owner,
084                @NotNull ClassBuilder v,
085                @NotNull GenerationState state,
086                MemberCodegen<?> parentCodegen
087        ) {
088            super(state, parentCodegen);
089            this.owner = owner;
090            this.v = v;
091        }
092    
093        public void gen(@NotNull JetNamedFunction function) {
094            SimpleFunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, function);
095            assert functionDescriptor != null : "No descriptor for function " + function.getText() + "\n" +
096                                                "in " + function.getContainingFile().getVirtualFile();
097    
098            OwnerKind kind = owner.getContextKind();
099            JvmMethodSignature method = typeMapper.mapSignature(functionDescriptor, kind);
100    
101            if (kind != OwnerKind.TRAIT_IMPL || function.hasBody()) {
102                generateMethod(function, method, functionDescriptor,
103                               new FunctionGenerationStrategy.FunctionDefault(state, functionDescriptor, function));
104            }
105    
106            generateDefaultIfNeeded(owner.intoFunction(functionDescriptor), method, functionDescriptor, kind,
107                                    DefaultParameterValueLoader.DEFAULT, function);
108        }
109    
110        public void generateMethod(
111                @Nullable PsiElement origin,
112                @NotNull JvmMethodSignature jvmSignature,
113                @NotNull FunctionDescriptor functionDescriptor,
114                @NotNull FunctionGenerationStrategy strategy
115        ) {
116            generateMethod(origin, jvmSignature, functionDescriptor, owner.intoFunction(functionDescriptor), strategy);
117        }
118    
119        public void generateMethod(
120                @Nullable PsiElement origin,
121                @NotNull JvmMethodSignature jvmSignature,
122                @NotNull FunctionDescriptor functionDescriptor,
123                @NotNull MethodContext methodContext,
124                @NotNull FunctionGenerationStrategy strategy
125        ) {
126            OwnerKind methodContextKind = methodContext.getContextKind();
127            Method asmMethod = jvmSignature.getAsmMethod();
128    
129            MethodVisitor mv = v.newMethod(origin,
130                                           getMethodAsmFlags(functionDescriptor, methodContextKind),
131                                           asmMethod.getName(),
132                                           asmMethod.getDescriptor(),
133                                           jvmSignature.getGenericsSignature(),
134                                           getThrownExceptions(functionDescriptor, typeMapper));
135    
136            if (owner instanceof PackageFacadeContext) {
137                Type ownerType = ((PackageFacadeContext) owner).getDelegateToClassType();
138                v.getSerializationBindings().put(IMPL_CLASS_NAME_FOR_CALLABLE, functionDescriptor, shortNameByAsmType(ownerType));
139            }
140            else {
141                v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod);
142            }
143    
144            AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor);
145    
146            generateParameterAnnotations(functionDescriptor, mv, jvmSignature);
147    
148            generateJetValueParameterAnnotations(mv, functionDescriptor, jvmSignature);
149    
150            if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES || isAbstractMethod(functionDescriptor, methodContextKind)) {
151                generateLocalVariableTable(
152                        mv,
153                        jvmSignature,
154                        functionDescriptor,
155                        getThisTypeForFunction(functionDescriptor, methodContext, typeMapper),
156                        new Label(),
157                        new Label(),
158                        methodContextKind
159                );
160                return;
161            }
162    
163            generateMethodBody(mv, functionDescriptor, methodContext, jvmSignature, strategy, getParentCodegen());
164    
165            endVisit(mv, null, origin);
166    
167            methodContext.recordSyntheticAccessorIfNeeded(functionDescriptor, bindingContext);
168    
169            generateBridges(functionDescriptor);
170        }
171    
172        private void generateParameterAnnotations(
173                @NotNull FunctionDescriptor functionDescriptor,
174                @NotNull MethodVisitor mv,
175                @NotNull JvmMethodSignature jvmSignature
176        ) {
177            Iterator<ValueParameterDescriptor> iterator = functionDescriptor.getValueParameters().iterator();
178            List<JvmMethodParameterSignature> kotlinParameterTypes = jvmSignature.getValueParameters();
179    
180            for (int i = 0; i < kotlinParameterTypes.size(); i++) {
181                JvmMethodParameterKind kind = kotlinParameterTypes.get(i).getKind();
182                if (kind.isSkippedInGenericSignature()) {
183                    markEnumOrInnerConstructorParameterAsSynthetic(mv, i);
184                    continue;
185                }
186    
187                if (kind == JvmMethodParameterKind.VALUE) {
188                    ValueParameterDescriptor parameter = iterator.next();
189                    v.getSerializationBindings().put(INDEX_FOR_VALUE_PARAMETER, parameter, i);
190                    AnnotationCodegen.forParameter(i, mv, typeMapper).genAnnotations(parameter);
191                }
192            }
193        }
194    
195        @SuppressWarnings("deprecation")
196        private void generateJetValueParameterAnnotations(
197                @NotNull MethodVisitor mv,
198                @NotNull FunctionDescriptor functionDescriptor,
199                @NotNull JvmMethodSignature jvmSignature
200        ) {
201            Iterator<ValueParameterDescriptor> descriptors = functionDescriptor.getValueParameters().iterator();
202            List<JvmMethodParameterSignature> kotlinParameterTypes = jvmSignature.getValueParameters();
203    
204            for (int i = 0; i < kotlinParameterTypes.size(); i++) {
205                JvmMethodParameterKind kind = kotlinParameterTypes.get(i).getKind();
206                if (kind.isSkippedInGenericSignature()) {
207                    markEnumOrInnerConstructorParameterAsSynthetic(mv, i);
208                    continue;
209                }
210    
211                String name;
212                boolean nullableType;
213                if (kind == JvmMethodParameterKind.VALUE) {
214                    ValueParameterDescriptor descriptor = descriptors.next();
215                    name = descriptor.getName().asString();
216                    nullableType = descriptor.getType().isNullable();
217                }
218                else {
219                    String lowercaseKind = kind.name().toLowerCase();
220                    if (needIndexForVar(kind)) {
221                        name = "$" + lowercaseKind + "$" + i;
222                    }
223                    else {
224                        name = "$" + lowercaseKind;
225                    }
226    
227                    if (kind == JvmMethodParameterKind.RECEIVER) {
228                        ReceiverParameterDescriptor receiver = functionDescriptor.getReceiverParameter();
229                        nullableType = receiver == null || receiver.getType().isNullable();
230                    }
231                    else {
232                        nullableType = true;
233                    }
234                }
235    
236                AnnotationVisitor av =
237                        mv.visitParameterAnnotation(i, asmDescByFqNameWithoutInnerClasses(OLD_JET_VALUE_PARAMETER_ANNOTATION), true);
238                if (av != null) {
239                    av.visit("name", name);
240                    if (nullableType) {
241                        av.visit("type", "?");
242                    }
243                    av.visitEnd();
244                }
245            }
246        }
247    
248        private void markEnumOrInnerConstructorParameterAsSynthetic(MethodVisitor mv, int i) {
249            // IDEA's ClsPsi builder fails to annotate synthetic parameters
250            if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return;
251    
252            // This is needed to avoid RuntimeInvisibleParameterAnnotations error in javac:
253            // see MethodWriter.visitParameterAnnotation()
254    
255            AnnotationVisitor av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", true);
256            if (av != null) {
257                av.visitEnd();
258            }
259        }
260    
261        @Nullable
262        private static Type getThisTypeForFunction(@NotNull FunctionDescriptor functionDescriptor, @NotNull MethodContext context, @NotNull JetTypeMapper typeMapper) {
263            ReceiverParameterDescriptor expectedThisObject = functionDescriptor.getExpectedThisObject();
264            if (functionDescriptor instanceof ConstructorDescriptor) {
265                return typeMapper.mapType(functionDescriptor);
266            }
267            else if (expectedThisObject != null) {
268                return typeMapper.mapType(expectedThisObject.getType());
269            }
270            else if (isFunctionLiteral(functionDescriptor) || isLocalNamedFun(functionDescriptor)) {
271                return typeMapper.mapType(context.getThisDescriptor());
272            }
273            else {
274                return null;
275            }
276        }
277    
278        public static void generateMethodBody(
279                @NotNull MethodVisitor mv,
280                @NotNull FunctionDescriptor functionDescriptor,
281                @NotNull MethodContext context,
282                @NotNull JvmMethodSignature signature,
283                @NotNull FunctionGenerationStrategy strategy,
284                @NotNull MemberCodegen<?> parentCodegen
285        ) {
286            mv.visitCode();
287    
288            Label methodBegin = new Label();
289            mv.visitLabel(methodBegin);
290    
291            JetTypeMapper typeMapper = parentCodegen.typeMapper;
292    
293            if (context.getParentContext() instanceof PackageFacadeContext) {
294                generateStaticDelegateMethodBody(mv, signature.getAsmMethod(), (PackageFacadeContext) context.getParentContext());
295            }
296            else {
297                FrameMap frameMap = strategy.getFrameMap(typeMapper, context);
298    
299                for (ValueParameterDescriptor parameter : functionDescriptor.getValueParameters()) {
300                    frameMap.enter(parameter, typeMapper.mapType(parameter));
301                }
302    
303                Label methodEntry = new Label();
304                mv.visitLabel(methodEntry);
305                context.setMethodStartLabel(methodEntry);
306    
307                if (!JetTypeMapper.isAccessor(functionDescriptor)) {
308                    genNotNullAssertionsForParameters(new InstructionAdapter(mv), parentCodegen.state, functionDescriptor, frameMap);
309                }
310    
311                strategy.generateBody(mv, signature, context, parentCodegen);
312            }
313    
314            Label methodEnd = new Label();
315            mv.visitLabel(methodEnd);
316    
317            Type thisType = getThisTypeForFunction(functionDescriptor, context, typeMapper);
318            generateLocalVariableTable(mv, signature, functionDescriptor, thisType, methodBegin, methodEnd, context.getContextKind());
319        }
320    
321        private static void generateLocalVariableTable(
322                @NotNull MethodVisitor mv,
323                @NotNull JvmMethodSignature jvmMethodSignature,
324                @NotNull FunctionDescriptor functionDescriptor,
325                @Nullable Type thisType,
326                @NotNull Label methodBegin,
327                @NotNull Label methodEnd,
328                @NotNull OwnerKind ownerKind
329        ) {
330            Iterator<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters().iterator();
331            List<JvmMethodParameterSignature> params = jvmMethodSignature.getValueParameters();
332            int shift = 0;
333    
334            boolean isStatic = AsmUtil.isStaticMethod(ownerKind, functionDescriptor);
335            if (!isStatic) {
336                //add this
337                if (thisType != null) {
338                    mv.visitLocalVariable("this", thisType.getDescriptor(), null, methodBegin, methodEnd, shift);
339                } else {
340                    //TODO: provide thisType for callable reference
341                }
342                shift++;
343            }
344    
345            for (int i = 0; i < params.size(); i++) {
346                JvmMethodParameterSignature param =  params.get(i);
347                JvmMethodParameterKind kind = param.getKind();
348                String parameterName;
349    
350                if (kind == JvmMethodParameterKind.VALUE) {
351                    ValueParameterDescriptor parameter = valueParameters.next();
352                    parameterName = parameter.getName().asString();
353                }
354                else {
355                    String lowercaseKind = kind.name().toLowerCase();
356                    parameterName = needIndexForVar(kind)
357                                    ? "$" + lowercaseKind + "$" + i
358                                    : "$" + lowercaseKind;
359                }
360    
361                Type type = param.getAsmType();
362                mv.visitLocalVariable(parameterName, type.getDescriptor(), null, methodBegin, methodEnd, shift);
363                shift += type.getSize();
364            }
365        }
366    
367        private static void generateStaticDelegateMethodBody(
368                @NotNull MethodVisitor mv,
369                @NotNull Method asmMethod,
370                @NotNull PackageFacadeContext context
371        ) {
372            InstructionAdapter iv = new InstructionAdapter(mv);
373            Type[] argTypes = asmMethod.getArgumentTypes();
374    
375            // The first line of some package file is written to the line number attribute of a static delegate to allow to 'step into' it
376            // This is similar to what javac does with bridge methods
377            Label label = new Label();
378            iv.visitLabel(label);
379            iv.visitLineNumber(1, label);
380    
381            int k = 0;
382            for (Type argType : argTypes) {
383                iv.load(k, argType);
384                k += argType.getSize();
385            }
386            iv.invokestatic(context.getDelegateToClassType().getInternalName(), asmMethod.getName(), asmMethod.getDescriptor());
387            iv.areturn(asmMethod.getReturnType());
388        }
389    
390        private static boolean needIndexForVar(JvmMethodParameterKind kind) {
391            return kind == JvmMethodParameterKind.CAPTURED_LOCAL_VARIABLE || kind == JvmMethodParameterKind.SUPER_OF_ANONYMOUS_CALL_PARAM;
392        }
393    
394        public static void endVisit(MethodVisitor mv, @Nullable String description, @Nullable PsiElement method) {
395            try {
396                mv.visitMaxs(-1, -1);
397            }
398            catch (ProcessCanceledException e) {
399                throw e;
400            }
401            catch (Throwable t) {
402                String bytecode = renderByteCodeIfAvailable(mv);
403                throw new CompilationException(
404                        "wrong code generated" +
405                        (description != null ? " for " + description : "") +
406                        t.getClass().getName() +
407                        " " +
408                        t.getMessage() +
409                        (bytecode != null ? "\nbytecode:\n" + bytecode : ""),
410                        t, method);
411            }
412            mv.visitEnd();
413        }
414    
415        private static String renderByteCodeIfAvailable(MethodVisitor mv) {
416            String bytecode = null;
417            if (mv instanceof TraceMethodVisitor) {
418                TraceMethodVisitor traceMethodVisitor = (TraceMethodVisitor) mv;
419                StringWriter sw = new StringWriter();
420                PrintWriter pw = new PrintWriter(sw);
421                traceMethodVisitor.p.print(pw);
422                pw.close();
423                bytecode = sw.toString();
424            }
425            return bytecode;
426        }
427    
428        public void generateBridges(@NotNull FunctionDescriptor descriptor) {
429            if (descriptor instanceof ConstructorDescriptor) return;
430            if (owner.getContextKind() == OwnerKind.TRAIT_IMPL) return;
431            if (isTrait(descriptor.getContainingDeclaration())) return;
432    
433            // equals(Any?), hashCode(), toString() never need bridges
434            if (isMethodOfAny(descriptor)) return;
435    
436            // If the function doesn't have a physical declaration among super-functions, it's a SAM adapter or alike and doesn't need bridges
437            if (CallResolverUtil.isOrOverridesSynthesized(descriptor)) return;
438    
439            Set<Bridge<Method>> bridgesToGenerate = BridgesPackage.generateBridgesForFunctionDescriptor(
440                    descriptor,
441                    new Function1<FunctionDescriptor, Method>() {
442                        @Override
443                        public Method invoke(FunctionDescriptor descriptor) {
444                            return typeMapper.mapSignature(descriptor).getAsmMethod();
445                        }
446                    }
447            );
448    
449            if (!bridgesToGenerate.isEmpty()) {
450                PsiElement origin = descriptor.getKind() == DECLARATION ? callableDescriptorToDeclaration(bindingContext, descriptor) : null;
451                for (Bridge<Method> bridge : bridgesToGenerate) {
452                    generateBridge(origin, bridge.getFrom(), bridge.getTo());
453                }
454            }
455        }
456    
457        private static boolean isMethodOfAny(@NotNull FunctionDescriptor descriptor) {
458            String name = descriptor.getName().asString();
459            List<ValueParameterDescriptor> parameters = descriptor.getValueParameters();
460            if (parameters.isEmpty()) {
461                return name.equals("hashCode") || name.equals("toString");
462            }
463            else if (parameters.size() == 1 && name.equals("equals")) {
464                ValueParameterDescriptor parameter = parameters.get(0);
465                return parameter.getType().equals(KotlinBuiltIns.getInstance().getNullableAnyType());
466            }
467            return false;
468        }
469    
470        @NotNull
471        private static String[] getThrownExceptions(@NotNull FunctionDescriptor function, @NotNull final JetTypeMapper mapper) {
472            AnnotationDescriptor annotation = function.getAnnotations().findAnnotation(new FqName("kotlin.throws"));
473            if (annotation == null) return ArrayUtil.EMPTY_STRING_ARRAY;
474    
475            Collection<CompileTimeConstant<?>> values = annotation.getAllValueArguments().values();
476            if (values.isEmpty()) return ArrayUtil.EMPTY_STRING_ARRAY;
477    
478            Object value = values.iterator().next();
479            if (!(value instanceof ArrayValue)) return ArrayUtil.EMPTY_STRING_ARRAY;
480            ArrayValue arrayValue = (ArrayValue) value;
481    
482            List<String> strings = ContainerUtil.mapNotNull(
483                    arrayValue.getValue(),
484                    new Function<CompileTimeConstant<?>, String>() {
485                        @Override
486                        public String fun(CompileTimeConstant<?> constant) {
487                            if (constant instanceof JavaClassValue) {
488                                JavaClassValue classValue = (JavaClassValue) constant;
489                                ClassDescriptor classDescriptor = DescriptorUtils.getClassDescriptorForType(classValue.getValue());
490                                return mapper.mapClass(classDescriptor).getInternalName();
491                            }
492                            return null;
493                        }
494                    }
495            );
496            return strings.toArray(new String[strings.size()]);
497        }
498    
499        static void generateConstructorWithoutParametersIfNeeded(
500                @NotNull GenerationState state,
501                @NotNull CallableMethod method,
502                @NotNull ConstructorDescriptor constructorDescriptor,
503                @NotNull ClassBuilder classBuilder
504        ) {
505            if (!isDefaultConstructorNeeded(state.getBindingContext(), constructorDescriptor)) {
506                return;
507            }
508            int flags = getVisibilityAccessFlag(constructorDescriptor);
509            MethodVisitor mv = classBuilder.newMethod(null, flags, "<init>", "()V", null,
510                                                      getThrownExceptions(constructorDescriptor, state.getTypeMapper()));
511    
512            if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return;
513    
514            InstructionAdapter v = new InstructionAdapter(mv);
515            mv.visitCode();
516    
517            Type methodOwner = method.getOwner();
518            v.load(0, methodOwner); // Load this on stack
519    
520            int mask = 0;
521            for (ValueParameterDescriptor parameterDescriptor : constructorDescriptor.getValueParameters()) {
522                Type paramType = state.getTypeMapper().mapType(parameterDescriptor.getType());
523                pushDefaultValueOnStack(paramType, v);
524                mask |= (1 << parameterDescriptor.getIndex());
525            }
526            v.iconst(mask);
527            String desc = method.getAsmMethod().getDescriptor().replace(")", "I)");
528            v.invokespecial(methodOwner.getInternalName(), "<init>", desc);
529            v.areturn(Type.VOID_TYPE);
530            endVisit(mv, "default constructor for " + methodOwner.getInternalName(), null);
531        }
532    
533        void generateDefaultIfNeeded(
534                @NotNull MethodContext owner,
535                @NotNull JvmMethodSignature signature,
536                @NotNull FunctionDescriptor functionDescriptor,
537                @NotNull OwnerKind kind,
538                @NotNull DefaultParameterValueLoader loadStrategy,
539                @Nullable JetNamedFunction function
540        ) {
541            DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();
542    
543            if (kind != OwnerKind.TRAIT_IMPL &&
544                contextClass instanceof ClassDescriptor &&
545                ((ClassDescriptor) contextClass).getKind() == ClassKind.TRAIT) {
546                return;
547            }
548    
549            if (!isDefaultNeeded(functionDescriptor)) {
550                return;
551            }
552    
553            Method jvmSignature = signature.getAsmMethod();
554    
555            int flags = getVisibilityAccessFlag(functionDescriptor) | getDeprecatedAccessFlag(functionDescriptor);
556    
557            boolean isConstructor = "<init>".equals(jvmSignature.getName());
558    
559            Method defaultMethod = typeMapper.mapDefaultMethod(functionDescriptor, kind, owner);
560    
561            MethodVisitor mv = v.newMethod(null, flags | (isConstructor ? 0 : ACC_STATIC),
562                                           defaultMethod.getName(),
563                                           defaultMethod.getDescriptor(), null,
564                                           getThrownExceptions(functionDescriptor, typeMapper));
565    
566            if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
567                if (this.owner instanceof PackageFacadeContext) {
568                    mv.visitCode();
569                    generateStaticDelegateMethodBody(mv, defaultMethod, (PackageFacadeContext) this.owner);
570                    endVisit(mv, "default method delegation", callableDescriptorToDeclaration(state.getBindingContext(), functionDescriptor));
571                }
572                else {
573                    generateDefaultImpl(owner, signature, functionDescriptor, isStatic(kind), mv, loadStrategy, function);
574                }
575            }
576        }
577    
578        private void generateDefaultImpl(
579                @NotNull MethodContext methodContext,
580                @NotNull JvmMethodSignature signature,
581                @NotNull FunctionDescriptor functionDescriptor,
582                boolean isStatic,
583                @NotNull MethodVisitor mv,
584                @NotNull DefaultParameterValueLoader loadStrategy,
585                @Nullable JetNamedFunction function
586        ) {
587            mv.visitCode();
588            generateDefaultImplBody(methodContext, signature, functionDescriptor, isStatic, mv, loadStrategy, function, getParentCodegen(), state);
589            endVisit(mv, "default method", callableDescriptorToDeclaration(state.getBindingContext(), functionDescriptor));
590        }
591    
592        public static void generateDefaultImplBody(
593                @NotNull MethodContext methodContext,
594                @NotNull JvmMethodSignature signature,
595                @NotNull FunctionDescriptor functionDescriptor,
596                boolean isStatic,
597                @NotNull MethodVisitor mv,
598                @NotNull DefaultParameterValueLoader loadStrategy,
599                @Nullable JetNamedFunction function,
600                @NotNull MemberCodegen<?> parentCodegen,
601                @NotNull GenerationState state
602        ) {
603            FrameMap frameMap = new FrameMap();
604    
605            if (!isStatic) {
606                frameMap.enterTemp(OBJECT_TYPE);
607            }
608    
609            ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, signature.getReturnType(), methodContext, state, parentCodegen);
610    
611            Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
612            List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
613            Iterator<ValueParameterDescriptor> iterator = paramDescrs.iterator();
614    
615            int countOfExtraVarsInMethodArgs = 0;
616    
617            for (JvmMethodParameterSignature parameterSignature : signature.getValueParameters()) {
618                if (parameterSignature.getKind() != JvmMethodParameterKind.VALUE) {
619                    countOfExtraVarsInMethodArgs++;
620                    frameMap.enterTemp(parameterSignature.getAsmType());
621                }
622                else {
623                    frameMap.enter(iterator.next(), parameterSignature.getAsmType());
624                }
625            }
626    
627            int maskIndex = frameMap.enterTemp(Type.INT_TYPE);
628    
629            CallGenerator generator = codegen.getOrCreateCallGenerator(functionDescriptor, function);
630    
631            InstructionAdapter iv = new InstructionAdapter(mv);
632            loadExplicitArgumentsOnStack(iv, OBJECT_TYPE, isStatic, signature);
633            generator.putHiddenParams();
634    
635            for (int index = 0; index < paramDescrs.size(); index++) {
636                ValueParameterDescriptor parameterDescriptor = paramDescrs.get(index);
637    
638                Type t = argTypes[countOfExtraVarsInMethodArgs + index];
639    
640                int parameterIndex = frameMap.getIndex(parameterDescriptor);
641                if (parameterDescriptor.declaresDefaultValue()) {
642                    iv.load(maskIndex, Type.INT_TYPE);
643                    iv.iconst(1 << index);
644                    iv.and(Type.INT_TYPE);
645                    Label loadArg = new Label();
646                    iv.ifeq(loadArg);
647    
648                    loadStrategy.putValueOnStack(parameterDescriptor, codegen);
649    
650                    iv.store(parameterIndex, t);
651    
652                    iv.mark(loadArg);
653                }
654    
655                generator.putValueIfNeeded(parameterDescriptor, t, StackValue.local(parameterIndex, t));
656            }
657    
658            CallableMethod method;
659            if (functionDescriptor instanceof ConstructorDescriptor) {
660                method = state.getTypeMapper().mapToCallableMethod((ConstructorDescriptor) functionDescriptor);
661            } else {
662                method = state.getTypeMapper().mapToCallableMethod(functionDescriptor, false, methodContext);
663            }
664    
665            generator.genCallWithoutAssertions(method, codegen);
666    
667            iv.areturn(signature.getReturnType());
668        }
669    
670    
671        private static void loadExplicitArgumentsOnStack(
672                @NotNull InstructionAdapter iv,
673                @NotNull Type ownerType,
674                boolean isStatic,
675                @NotNull JvmMethodSignature signature
676        ) {
677            int var = 0;
678            if (!isStatic) {
679                iv.load(var, ownerType);
680                var += ownerType.getSize();
681            }
682    
683            for (JvmMethodParameterSignature parameterSignature : signature.getValueParameters()) {
684                if (parameterSignature.getKind() != JvmMethodParameterKind.VALUE) {
685                    Type type = parameterSignature.getAsmType();
686                    iv.load(var, type);
687                    var += type.getSize();
688                }
689            }
690        }
691    
692        private static boolean isDefaultNeeded(FunctionDescriptor functionDescriptor) {
693            boolean needed = false;
694            if (functionDescriptor != null) {
695                for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) {
696                    if (parameterDescriptor.declaresDefaultValue()) {
697                        needed = true;
698                        break;
699                    }
700                }
701            }
702            return needed;
703        }
704    
705        private static boolean isDefaultConstructorNeeded(@NotNull BindingContext context, @NotNull ConstructorDescriptor constructorDescriptor) {
706            ClassDescriptor classDescriptor = constructorDescriptor.getContainingDeclaration();
707    
708            if (CodegenBinding.canHaveOuter(context, classDescriptor)) return false;
709    
710            if (classDescriptor.getVisibility() == Visibilities.PRIVATE ||
711                constructorDescriptor.getVisibility() == Visibilities.PRIVATE) return false;
712    
713            if (constructorDescriptor.getValueParameters().isEmpty()) return false;
714    
715            for (ValueParameterDescriptor parameterDescriptor : constructorDescriptor.getValueParameters()) {
716                if (!parameterDescriptor.declaresDefaultValue()) {
717                    return false;
718                }
719            }
720            return true;
721        }
722    
723        private void generateBridge(@Nullable PsiElement origin, @NotNull Method bridge, @NotNull Method delegateTo) {
724            int flags = ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC; // TODO.
725    
726            MethodVisitor mv = v.newMethod(null, flags, delegateTo.getName(), bridge.getDescriptor(), null, null);
727            if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
728    
729            mv.visitCode();
730    
731            Type[] argTypes = bridge.getArgumentTypes();
732            Type[] originalArgTypes = delegateTo.getArgumentTypes();
733    
734            InstructionAdapter iv = new InstructionAdapter(mv);
735            iv.load(0, OBJECT_TYPE);
736            for (int i = 0, reg = 1; i < argTypes.length; i++) {
737                StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
738                //noinspection AssignmentToForLoopParameter
739                reg += argTypes[i].getSize();
740            }
741    
742            iv.invokevirtual(v.getThisName(), delegateTo.getName(), delegateTo.getDescriptor());
743    
744            StackValue.coerce(delegateTo.getReturnType(), bridge.getReturnType(), iv);
745            iv.areturn(bridge.getReturnType());
746    
747            endVisit(mv, "bridge method", origin);
748        }
749    
750        public void genDelegate(FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenDescriptor, StackValue field) {
751            genDelegate(functionDescriptor, (ClassDescriptor) overriddenDescriptor.getContainingDeclaration(), field,
752                        typeMapper.mapSignature(functionDescriptor),
753                        typeMapper.mapSignature(overriddenDescriptor.getOriginal())
754            );
755        }
756    
757        public void genDelegate(
758                FunctionDescriptor functionDescriptor,
759                ClassDescriptor toClass,
760                StackValue field,
761                JvmMethodSignature jvmDelegateMethodSignature,
762                JvmMethodSignature jvmOverriddenMethodSignature
763        ) {
764            Method overriddenMethod = jvmOverriddenMethodSignature.getAsmMethod();
765            Method delegateMethod = jvmDelegateMethodSignature.getAsmMethod();
766    
767            int flags = ACC_PUBLIC;
768    
769            MethodVisitor mv = v.newMethod(null, flags, delegateMethod.getName(), delegateMethod.getDescriptor(), null,
770                                           getThrownExceptions(functionDescriptor, typeMapper));
771            if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
772    
773            mv.visitCode();
774    
775            Type[] argTypes = delegateMethod.getArgumentTypes();
776            Type[] originalArgTypes = overriddenMethod.getArgumentTypes();
777    
778            InstructionAdapter iv = new InstructionAdapter(mv);
779            iv.load(0, OBJECT_TYPE);
780            field.put(field.type, iv);
781            for (int i = 0, reg = 1; i < argTypes.length; i++) {
782                StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
783                //noinspection AssignmentToForLoopParameter
784                reg += argTypes[i].getSize();
785            }
786    
787            String internalName = typeMapper.mapType(toClass).getInternalName();
788            if (toClass.getKind() == ClassKind.TRAIT) {
789                iv.invokeinterface(internalName, overriddenMethod.getName(), overriddenMethod.getDescriptor());
790            }
791            else {
792                iv.invokevirtual(internalName, overriddenMethod.getName(), overriddenMethod.getDescriptor());
793            }
794    
795            StackValue.onStack(overriddenMethod.getReturnType()).put(delegateMethod.getReturnType(), iv);
796    
797            iv.areturn(delegateMethod.getReturnType());
798            endVisit(mv, "Delegate method " + functionDescriptor + " to " + jvmOverriddenMethodSignature,
799                     descriptorToDeclaration(bindingContext, functionDescriptor.getContainingDeclaration()));
800    
801            generateBridges(functionDescriptor);
802        }
803    }