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.KotlinTypeMapper;
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 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 ) {
048 super(JvmCodegenUtil.getDirectMember(functionDescriptor), contextKind, parentContext, closure,
049 parentContext.hasThisDescriptor() ? parentContext.getThisDescriptor() : null, null);
050 this.functionDescriptor = functionDescriptor;
051 }
052
053 @NotNull
054 @Override
055 public CodegenContext getParentContext() {
056 //noinspection ConstantConditions
057 return super.getParentContext();
058 }
059
060 public StackValue getReceiverExpression(KotlinTypeMapper typeMapper) {
061 assert getCallableDescriptorWithReceiver() != null;
062 @SuppressWarnings("ConstantConditions")
063 Type asmType = typeMapper.mapType(getCallableDescriptorWithReceiver().getExtensionReceiverParameter().getType());
064 return StackValue.local(AsmUtil.getReceiverIndex(this, getContextDescriptor()), asmType);
065 }
066
067 @Override
068 public StackValue lookupInContext(DeclarationDescriptor d, @Nullable StackValue result, GenerationState state, boolean ignoreNoOuter) {
069 if (d instanceof SyntheticFieldDescriptor) {
070 SyntheticFieldDescriptor fieldDescriptor = (SyntheticFieldDescriptor) d;
071 d = fieldDescriptor.getPropertyDescriptor();
072 }
073 if (getContextDescriptor() == d) {
074 return result != null ? result : StackValue.LOCAL_0;
075 }
076
077 return getParentContext().lookupInContext(d, result, state, ignoreNoOuter);
078 }
079
080 @Nullable
081 public StackValue generateReceiver(@NotNull CallableDescriptor descriptor, @NotNull GenerationState state, boolean ignoreNoOuter) {
082 if (getCallableDescriptorWithReceiver() == descriptor) {
083 return getReceiverExpression(state.getTypeMapper());
084 }
085 ReceiverParameterDescriptor parameter = descriptor.getExtensionReceiverParameter();
086 return lookupInContext(parameter, StackValue.LOCAL_0, state, ignoreNoOuter);
087 }
088
089 @Override
090 public StackValue getOuterExpression(StackValue prefix, boolean ignoreNoOuter) {
091 return getParentContext().getOuterExpression(prefix, false);
092 }
093
094 @Nullable
095 public Label getMethodStartLabel() {
096 return methodStartLabel;
097 }
098
099 public void setMethodStartLabel(@NotNull Label methodStartLabel) {
100 this.methodStartLabel = methodStartLabel;
101 }
102
103 @Nullable
104 public Label getMethodEndLabel() {
105 return methodEndLabel;
106 }
107
108 public void setMethodEndLabel(@NotNull Label methodEndLabel) {
109 this.methodEndLabel = methodEndLabel;
110 }
111
112 @Override
113 public String toString() {
114 return "Method: " + getContextDescriptor();
115 }
116
117 public boolean isInlineMethodContext() {
118 return InlineUtil.isInline(getContextDescriptor());
119 }
120
121 @NotNull
122 public FunctionDescriptor getFunctionDescriptor() {
123 return functionDescriptor;
124 }
125 }