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.inline;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.kotlin.codegen.state.GenerationState;
022
023 import java.util.Collections;
024 import java.util.HashMap;
025 import java.util.Map;
026
027 public class InliningContext {
028 @Nullable
029 private final InliningContext parent;
030
031 private final Map<Integer, LambdaInfo> expressionMap;
032 public final GenerationState state;
033 public final NameGenerator nameGenerator;
034 public final TypeRemapper typeRemapper;
035 public final ReifiedTypeInliner reifiedTypeInliner;
036 public final boolean isInliningLambda;
037 public final boolean classRegeneration;
038 public final Map<String, AnonymousObjectTransformationInfo> internalNameToAnonymousObjectTransformationInfo =
039 new HashMap<String, AnonymousObjectTransformationInfo>();
040
041 private boolean isContinuation;
042
043 public InliningContext(
044 @Nullable InliningContext parent,
045 @NotNull Map<Integer, LambdaInfo> expressionMap,
046 @NotNull GenerationState state,
047 @NotNull NameGenerator nameGenerator,
048 @NotNull TypeRemapper typeRemapper,
049 @NotNull ReifiedTypeInliner reifiedTypeInliner,
050 boolean isInliningLambda,
051 boolean classRegeneration
052 ) {
053 this.parent = parent;
054 this.expressionMap = expressionMap;
055 this.state = state;
056 this.nameGenerator = nameGenerator;
057 this.typeRemapper = typeRemapper;
058 this.reifiedTypeInliner = reifiedTypeInliner;
059 this.isInliningLambda = isInliningLambda;
060 this.classRegeneration = classRegeneration;
061 }
062
063 @NotNull
064 public InliningContext subInline(@NotNull NameGenerator generator) {
065 return subInline(generator, Collections.<String, String>emptyMap(), isInliningLambda);
066 }
067
068 @NotNull
069 public InliningContext subInlineLambda(@NotNull LambdaInfo lambdaInfo) {
070 Map<String, String> map = new HashMap<String, String>();
071 map.put(lambdaInfo.getLambdaClassType().getInternalName(), null); //mark lambda inlined
072 return subInline(nameGenerator.subGenerator("lambda"), map, true);
073 }
074
075 @NotNull
076 public InliningContext subInlineWithClassRegeneration(
077 @NotNull NameGenerator generator,
078 @NotNull Map<String, String> newTypeMappings,
079 @NotNull InlineCallSiteInfo callSiteInfo
080 ) {
081 return new RegeneratedClassContext(
082 this, expressionMap, state, generator, TypeRemapper.createFrom(typeRemapper, newTypeMappings),
083 reifiedTypeInliner, isInliningLambda, callSiteInfo
084 );
085 }
086
087 @NotNull
088 private InliningContext subInline(
089 @NotNull NameGenerator generator, @NotNull Map<String, String> additionalTypeMappings, boolean isInliningLambda
090 ) {
091 //isInliningLambda && !this.isInliningLambda for root inline lambda
092 return new InliningContext(
093 this, expressionMap, state, generator,
094 TypeRemapper.createFrom(
095 typeRemapper,
096 additionalTypeMappings,
097 //root inline lambda
098 isInliningLambda && !this.isInliningLambda
099 ),
100 reifiedTypeInliner, isInliningLambda, classRegeneration
101 );
102 }
103
104 public boolean isRoot() {
105 return parent == null;
106 }
107
108 @NotNull
109 public RootInliningContext getRoot() {
110 //noinspection ConstantConditions
111 return isRoot() ? (RootInliningContext) this : parent.getRoot();
112 }
113
114 @Nullable
115 public InliningContext getParent() {
116 return parent;
117 }
118
119 @NotNull
120 public InlineCallSiteInfo getCallSiteInfo() {
121 assert parent != null : "At least root context should return proper value";
122 return parent.getCallSiteInfo();
123 }
124
125 @Nullable
126 public AnonymousObjectTransformationInfo findAnonymousObjectTransformationInfo(@NotNull String internalName) {
127 if (getRoot().internalNameToAnonymousObjectTransformationInfo.containsKey(internalName)) {
128 return getRoot().internalNameToAnonymousObjectTransformationInfo.get(internalName);
129 }
130
131 return null;
132 }
133
134 public boolean isContinuation() {
135 return isContinuation;
136 }
137
138 public void setContinuation(boolean continuation) {
139 isContinuation = continuation;
140 }
141 }