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