001 /*
002 * Copyright 2010-2015 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.kotlin.codegen.context;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.kotlin.codegen.AsmUtil;
022 import org.jetbrains.kotlin.codegen.JvmCodegenUtil;
023 import org.jetbrains.kotlin.codegen.OwnerKind;
024 import org.jetbrains.kotlin.codegen.StackValue;
025 import org.jetbrains.kotlin.codegen.binding.MutableClosure;
026 import org.jetbrains.kotlin.codegen.state.GenerationState;
027 import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
028 import org.jetbrains.kotlin.descriptors.*;
029 import org.jetbrains.kotlin.resolve.inline.InlineUtil;
030 import org.jetbrains.org.objectweb.asm.Label;
031 import org.jetbrains.org.objectweb.asm.Type;
032
033 public class MethodContext extends CodegenContext<CallableMemberDescriptor> {
034 private final boolean isInliningLambda;
035 private Label methodStartLabel;
036 private Label methodEndLabel;
037
038 // Note: in case of code inside property accessors, functionDescriptor will be that accessor,
039 // but CodegenContext#contextDescriptor will be the corresponding property
040 private final FunctionDescriptor functionDescriptor;
041
042 protected MethodContext(
043 @NotNull FunctionDescriptor functionDescriptor,
044 @NotNull OwnerKind contextKind,
045 @NotNull CodegenContext parentContext,
046 @Nullable MutableClosure closure,
047 boolean isInliningLambda
048 ) {
049 super(JvmCodegenUtil.getDirectMember(functionDescriptor), contextKind, parentContext, closure,
050 parentContext.hasThisDescriptor() ? parentContext.getThisDescriptor() : null, null);
051 this.isInliningLambda = isInliningLambda;
052 this.functionDescriptor = functionDescriptor;
053 }
054
055 @NotNull
056 @Override
057 public CodegenContext getParentContext() {
058 //noinspection ConstantConditions
059 return super.getParentContext();
060 }
061
062 public StackValue getReceiverExpression(JetTypeMapper typeMapper) {
063 assert getCallableDescriptorWithReceiver() != null;
064 @SuppressWarnings("ConstantConditions")
065 Type asmType = typeMapper.mapType(getCallableDescriptorWithReceiver().getExtensionReceiverParameter().getType());
066 return StackValue.local(AsmUtil.getReceiverIndex(this, getContextDescriptor()), asmType);
067 }
068
069 @Override
070 public StackValue lookupInContext(DeclarationDescriptor d, @Nullable StackValue result, GenerationState state, boolean ignoreNoOuter) {
071 if (getContextDescriptor() == d) {
072 return result != null ? result : StackValue.LOCAL_0;
073 }
074
075 return getParentContext().lookupInContext(d, result, state, ignoreNoOuter);
076 }
077
078 @Nullable
079 public StackValue generateReceiver(@NotNull CallableDescriptor descriptor, @NotNull GenerationState state, boolean ignoreNoOuter) {
080 if (getCallableDescriptorWithReceiver() == descriptor) {
081 return getReceiverExpression(state.getTypeMapper());
082 }
083 ReceiverParameterDescriptor parameter = descriptor.getExtensionReceiverParameter();
084 return lookupInContext(parameter, StackValue.LOCAL_0, state, ignoreNoOuter);
085 }
086
087 @Override
088 public StackValue getOuterExpression(StackValue prefix, boolean ignoreNoOuter) {
089 return getParentContext().getOuterExpression(prefix, false);
090 }
091
092 @Nullable
093 public Label getMethodStartLabel() {
094 return methodStartLabel;
095 }
096
097 public void setMethodStartLabel(@NotNull Label methodStartLabel) {
098 this.methodStartLabel = methodStartLabel;
099 }
100
101 @Nullable
102 public Label getMethodEndLabel() {
103 return methodEndLabel;
104 }
105
106 public void setMethodEndLabel(@NotNull Label methodEndLabel) {
107 this.methodEndLabel = methodEndLabel;
108 }
109
110 @Override
111 public String toString() {
112 return "Method: " + getContextDescriptor();
113 }
114
115 public boolean isInlineFunction() {
116 return InlineUtil.isInline(getContextDescriptor());
117 }
118
119 public boolean isInliningLambda() {
120 return isInliningLambda;
121 }
122
123 @NotNull
124 public FunctionDescriptor getFunctionDescriptor() {
125 return functionDescriptor;
126 }
127 }