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