Reimplement generation of intrinsic array constructors
Instead of relying on a class from the runtime (which thus cannot be deleted from the runtime ever), rely on a class from the compiler instead. This has a minor downside: that class is compiled by the bootstrap compiler, so if codegen of 'for'-loops or something else used in that class changes, it won't immediately have an effect on a local working copy (on the build server everything will be fine because of a 2-step building process). In the future it may make sense to just manually create all the bytecode instructions and dump them into a MethodNode. Currently the amount of work needed for that seems rather significant
This commit is contained in:
@@ -56,8 +56,6 @@ import org.jetbrains.kotlin.jvm.bindingContextSlices.BindingContextSlicesKt;
|
|||||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
||||||
import org.jetbrains.kotlin.name.ClassId;
|
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
@@ -80,13 +78,11 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.*;
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.FindClassInModuleKt;
|
|
||||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
|
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.kotlin.types.TypeProjection;
|
import org.jetbrains.kotlin.types.TypeProjection;
|
||||||
import org.jetbrains.kotlin.types.TypeUtils;
|
import org.jetbrains.kotlin.types.TypeUtils;
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
||||||
import org.jetbrains.kotlin.utils.StringsKt;
|
|
||||||
import org.jetbrains.org.objectweb.asm.Label;
|
import org.jetbrains.org.objectweb.asm.Label;
|
||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes;
|
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||||
@@ -101,7 +97,8 @@ import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
|
|||||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
|
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
|
||||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.*;
|
import static org.jetbrains.kotlin.resolve.BindingContextUtils.*;
|
||||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry;
|
||||||
|
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isObject;
|
||||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||||
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionExpression;
|
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionExpression;
|
||||||
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral;
|
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral;
|
||||||
@@ -2435,11 +2432,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
// We should inline callable containing reified type parameters even if inline is disabled
|
// We should inline callable containing reified type parameters even if inline is disabled
|
||||||
// because they may contain something to reify and straight call will probably fail at runtime
|
// because they may contain something to reify and straight call will probably fail at runtime
|
||||||
boolean isInline = (state.isInlineEnabled() || InlineUtil.containsReifiedTypeParameters(descriptor)) &&
|
boolean isInline = (state.isInlineEnabled() || InlineUtil.containsReifiedTypeParameters(descriptor)) &&
|
||||||
InlineUtil.isInline(descriptor);
|
(InlineUtil.isInline(descriptor) || InlineUtil.isArrayConstructorWithLambda(descriptor));
|
||||||
|
|
||||||
if (!isInline) return defaultCallGenerator;
|
if (!isInline) return defaultCallGenerator;
|
||||||
|
|
||||||
SimpleFunctionDescriptor original = DescriptorUtils.unwrapFakeOverride((SimpleFunctionDescriptor) descriptor.getOriginal());
|
FunctionDescriptor original = DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal());
|
||||||
return new InlineCodegen(this, state, original, callElement, typeParameterMappings);
|
return new InlineCodegen(this, state, original, callElement, typeParameterMappings);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2457,6 +2454,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
|
|
||||||
KotlinType type = TypeUtils.uncaptureTypeForInlineMapping(entry.getValue());
|
KotlinType type = TypeUtils.uncaptureTypeForInlineMapping(entry.getValue());
|
||||||
|
|
||||||
|
boolean isReified = key.isReified() || InlineUtil.isArrayConstructorWithLambda(resolvedCall.getResultingDescriptor());
|
||||||
|
|
||||||
Pair<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type);
|
Pair<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type);
|
||||||
if (typeParameterAndReificationArgument == null) {
|
if (typeParameterAndReificationArgument == null) {
|
||||||
// type is not generic
|
// type is not generic
|
||||||
@@ -2464,16 +2463,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
Type asmType = typeMapper.mapTypeParameter(type, signatureWriter);
|
Type asmType = typeMapper.mapTypeParameter(type, signatureWriter);
|
||||||
|
|
||||||
mappings.addParameterMappingToType(
|
mappings.addParameterMappingToType(
|
||||||
key.getName().getIdentifier(),
|
key.getName().getIdentifier(), type, asmType, signatureWriter.toString(), isReified
|
||||||
type,
|
);
|
||||||
asmType,
|
|
||||||
signatureWriter.toString(),
|
|
||||||
key.isReified());
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mappings.addParameterMappingForFurtherReification(
|
mappings.addParameterMappingForFurtherReification(
|
||||||
key.getName().getIdentifier(), type,
|
key.getName().getIdentifier(), type, typeParameterAndReificationArgument.getSecond(), isReified
|
||||||
typeParameterAndReificationArgument.getSecond(), key.isReified());
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return getOrCreateCallGenerator(
|
return getOrCreateCallGenerator(
|
||||||
@@ -3412,50 +3408,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
final ConstructorDescriptor constructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor();
|
return invokeFunction(resolvedCall, StackValue.none());
|
||||||
|
|
||||||
final ClassDescriptor intrinsicConstructors =
|
|
||||||
FindClassInModuleKt.findClassAcrossModuleDependencies(
|
|
||||||
getContainingModule(context.getContextDescriptor()),
|
|
||||||
ClassId.topLevel(new FqName("kotlin.jvm.internal.IntrinsicArrayConstructors"))
|
|
||||||
);
|
|
||||||
// TODO: do not depend on a class from the runtime
|
|
||||||
assert intrinsicConstructors != null : "Class IntrinsicArrayConstructors is not found";
|
|
||||||
|
|
||||||
ResolvedCall<?> fakeResolvedCall = new DelegatingResolvedCall<CallableDescriptor>(resolvedCall) {
|
|
||||||
private final CallableDescriptor descriptor;
|
|
||||||
|
|
||||||
{
|
|
||||||
Collection<FunctionDescriptor> functions = intrinsicConstructors.getUnsubstitutedMemberScope().getContributedFunctions(
|
|
||||||
constructor.getContainingDeclaration().getName(), NoLookupLocation.FROM_BACKEND);
|
|
||||||
assert functions.size() == 1
|
|
||||||
: "IntrinsicArrayConstructors does not have a single constructor for " +
|
|
||||||
constructor.getContainingDeclaration().getName() + ":\n" + StringsKt.join(functions, "\n");
|
|
||||||
descriptor = CollectionsKt.single(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public CallableDescriptor getResultingDescriptor() {
|
|
||||||
return descriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Map<TypeParameterDescriptor, KotlinType> getTypeArguments() {
|
|
||||||
Map<TypeParameterDescriptor, KotlinType> originalArgs = super.getTypeArguments();
|
|
||||||
if (originalArgs.isEmpty()) return originalArgs;
|
|
||||||
|
|
||||||
assert originalArgs.size() == 1 : "Unknown constructor called: " + originalArgs.size() + " type arguments";
|
|
||||||
|
|
||||||
return Collections.singletonMap(
|
|
||||||
CollectionsKt.single(descriptor.getTypeParameters()),
|
|
||||||
CollectionsKt.single(originalArgs.values())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return invokeFunction(fakeResolvedCall, StackValue.singleton(intrinsicConstructors, typeMapper));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void newArrayInstruction(@NotNull KotlinType arrayType) {
|
public void newArrayInstruction(@NotNull KotlinType arrayType) {
|
||||||
|
|||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.codegen.inline
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||||
|
|
||||||
|
internal class FictitiousArrayConstructor(arrayClass: ClassDescriptor) : SimpleFunctionDescriptorImpl(
|
||||||
|
arrayClass.containingDeclaration, null, Annotations.EMPTY, arrayClass.name, CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||||
|
SourceElement.NO_SOURCE
|
||||||
|
) {
|
||||||
|
companion object Factory {
|
||||||
|
@JvmStatic
|
||||||
|
fun create(arrayConstructor: ConstructorDescriptor): FictitiousArrayConstructor {
|
||||||
|
val arrayClass = arrayConstructor.containingDeclaration
|
||||||
|
return FictitiousArrayConstructor(arrayClass).apply {
|
||||||
|
this.initialize(null, null, arrayConstructor.typeParameters, arrayConstructor.valueParameters, arrayClass.defaultType,
|
||||||
|
Modality.FINAL, Visibilities.PUBLIC)
|
||||||
|
this.isInline = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
||||||
import org.jetbrains.kotlin.codegen.*;
|
import org.jetbrains.kotlin.codegen.*;
|
||||||
import org.jetbrains.kotlin.codegen.context.*;
|
import org.jetbrains.kotlin.codegen.context.*;
|
||||||
|
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt;
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
@@ -69,7 +70,7 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
private final GenerationState state;
|
private final GenerationState state;
|
||||||
private final JetTypeMapper typeMapper;
|
private final JetTypeMapper typeMapper;
|
||||||
|
|
||||||
private final SimpleFunctionDescriptor functionDescriptor;
|
private final FunctionDescriptor functionDescriptor;
|
||||||
private final JvmMethodSignature jvmSignature;
|
private final JvmMethodSignature jvmSignature;
|
||||||
private final KtElement callElement;
|
private final KtElement callElement;
|
||||||
private final MethodContext context;
|
private final MethodContext context;
|
||||||
@@ -92,17 +93,21 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
public InlineCodegen(
|
public InlineCodegen(
|
||||||
@NotNull ExpressionCodegen codegen,
|
@NotNull ExpressionCodegen codegen,
|
||||||
@NotNull GenerationState state,
|
@NotNull GenerationState state,
|
||||||
@NotNull SimpleFunctionDescriptor functionDescriptor,
|
@NotNull FunctionDescriptor function,
|
||||||
@NotNull KtElement callElement,
|
@NotNull KtElement callElement,
|
||||||
@Nullable TypeParameterMappings typeParameterMappings
|
@Nullable TypeParameterMappings typeParameterMappings
|
||||||
) {
|
) {
|
||||||
assert InlineUtil.isInline(functionDescriptor) : "InlineCodegen could inline only inline function: " + functionDescriptor;
|
assert InlineUtil.isInline(function) || InlineUtil.isArrayConstructorWithLambda(function) :
|
||||||
|
"InlineCodegen can inline only inline functions and array constructors: " + function;
|
||||||
|
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.typeMapper = state.getTypeMapper();
|
this.typeMapper = state.getTypeMapper();
|
||||||
this.codegen = codegen;
|
this.codegen = codegen;
|
||||||
this.callElement = callElement;
|
this.callElement = callElement;
|
||||||
this.functionDescriptor = functionDescriptor.getOriginal();
|
this.functionDescriptor =
|
||||||
|
InlineUtil.isArrayConstructorWithLambda(function)
|
||||||
|
? FictitiousArrayConstructor.create((ConstructorDescriptor) function)
|
||||||
|
: function.getOriginal();
|
||||||
this.typeParameterMappings = typeParameterMappings;
|
this.typeParameterMappings = typeParameterMappings;
|
||||||
|
|
||||||
reifiedTypeInliner = new ReifiedTypeInliner(typeParameterMappings);
|
reifiedTypeInliner = new ReifiedTypeInliner(typeParameterMappings);
|
||||||
@@ -119,13 +124,14 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
isSameModule = JvmCodegenUtil.isCallInsideSameModuleAsDeclared(functionDescriptor, codegen.getContext(), state.getOutDirectory());
|
isSameModule = JvmCodegenUtil.isCallInsideSameModuleAsDeclared(functionDescriptor, codegen.getContext(), state.getOutDirectory());
|
||||||
|
|
||||||
sourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper();
|
sourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper();
|
||||||
reportIncrementalInfo(functionDescriptor, codegen.getContext().getFunctionDescriptor().getOriginal());
|
|
||||||
|
if (!(functionDescriptor instanceof FictitiousArrayConstructor)) {
|
||||||
|
reportIncrementalInfo(functionDescriptor, codegen.getContext().getFunctionDescriptor().getOriginal());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void genCallWithoutAssertions(
|
public void genCallWithoutAssertions(@NotNull CallableMethod callableMethod, @NotNull ExpressionCodegen codegen) {
|
||||||
@NotNull CallableMethod callableMethod, @NotNull ExpressionCodegen codegen
|
|
||||||
) {
|
|
||||||
genCall(callableMethod, null, false, codegen);
|
genCall(callableMethod, null, false, codegen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,19 +182,25 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private SMAPAndMethodNode createMethodNode(boolean callDefault) throws ClassNotFoundException, IOException {
|
private SMAPAndMethodNode createMethodNode(boolean callDefault) throws IOException {
|
||||||
JvmMethodSignature jvmSignature = typeMapper.mapSignature(functionDescriptor, context.getContextKind());
|
Method asmMethod = callDefault
|
||||||
|
? typeMapper.mapDefaultMethod(functionDescriptor, context.getContextKind())
|
||||||
Method asmMethod;
|
: jvmSignature.getAsmMethod();
|
||||||
if (callDefault) {
|
|
||||||
asmMethod = typeMapper.mapDefaultMethod(functionDescriptor, context.getContextKind());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
asmMethod = jvmSignature.getAsmMethod();
|
|
||||||
}
|
|
||||||
|
|
||||||
SMAPAndMethodNode nodeAndSMAP;
|
SMAPAndMethodNode nodeAndSMAP;
|
||||||
if (functionDescriptor instanceof DeserializedSimpleFunctionDescriptor) {
|
if (functionDescriptor instanceof FictitiousArrayConstructor) {
|
||||||
|
nodeAndSMAP = InlineCodegenUtil.getMethodNode(
|
||||||
|
IntrinsicArrayConstructorsKt.getBytecode(),
|
||||||
|
asmMethod.getName(),
|
||||||
|
asmMethod.getDescriptor(),
|
||||||
|
IntrinsicArrayConstructorsKt.getClassId()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (nodeAndSMAP == null) {
|
||||||
|
throw new IllegalStateException("Couldn't obtain array constructor body for " + descriptorName(functionDescriptor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (functionDescriptor instanceof DeserializedSimpleFunctionDescriptor) {
|
||||||
JetTypeMapper.ContainingClassesInfo containingClasses = typeMapper.getContainingClassesForDeserializedCallable(
|
JetTypeMapper.ContainingClassesInfo containingClasses = typeMapper.getContainingClassesForDeserializedCallable(
|
||||||
(DeserializedSimpleFunctionDescriptor) functionDescriptor);
|
(DeserializedSimpleFunctionDescriptor) functionDescriptor);
|
||||||
|
|
||||||
@@ -203,14 +215,14 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (nodeAndSMAP == null) {
|
if (nodeAndSMAP == null) {
|
||||||
throw new RuntimeException("Couldn't obtain compiled function body for " + descriptorName(functionDescriptor));
|
throw new IllegalStateException("Couldn't obtain compiled function body for " + descriptorName(functionDescriptor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor);
|
PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor);
|
||||||
|
|
||||||
if (element == null || !(element instanceof KtNamedFunction)) {
|
if (!(element instanceof KtNamedFunction)) {
|
||||||
throw new RuntimeException("Couldn't find declaration for function " + descriptorName(functionDescriptor));
|
throw new IllegalStateException("Couldn't find declaration for function " + descriptorName(functionDescriptor));
|
||||||
}
|
}
|
||||||
KtNamedFunction inliningFunction = (KtNamedFunction) element;
|
KtNamedFunction inliningFunction = (KtNamedFunction) element;
|
||||||
|
|
||||||
@@ -260,14 +272,10 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
|
|
||||||
Parameters parameters = invocationParamBuilder.buildParameters();
|
Parameters parameters = invocationParamBuilder.buildParameters();
|
||||||
|
|
||||||
InliningContext info = new RootInliningContext(expressionMap,
|
InliningContext info = new RootInliningContext(
|
||||||
state,
|
expressionMap, state, codegen.getInlineNameGenerator().subGenerator(jvmSignature.getAsmMethod().getName()),
|
||||||
codegen.getInlineNameGenerator()
|
codegen.getContext(), callElement, getInlineCallSiteInfo(), reifiedTypeInliner, typeParameterMappings
|
||||||
.subGenerator(functionDescriptor.getName().asString()),
|
);
|
||||||
codegen.getContext(),
|
|
||||||
callElement,
|
|
||||||
getInlineCallSiteInfo(), reifiedTypeInliner,
|
|
||||||
typeParameterMappings);
|
|
||||||
|
|
||||||
MethodInliner inliner = new MethodInliner(node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule,
|
MethodInliner inliner = new MethodInliner(node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule,
|
||||||
"Method inlining " + callElement.getText(),
|
"Method inlining " + callElement.getText(),
|
||||||
@@ -529,13 +537,11 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putHiddenParams() {
|
public void putHiddenParams() {
|
||||||
List<JvmMethodParameterSignature> valueParameters = jvmSignature.getValueParameters();
|
if ((getMethodAsmFlags(functionDescriptor, context.getContextKind()) & Opcodes.ACC_STATIC) == 0) {
|
||||||
|
|
||||||
if (!isStaticMethod(functionDescriptor, context)) {
|
|
||||||
invocationParamBuilder.addNextParameter(AsmTypes.OBJECT_TYPE, false, null);
|
invocationParamBuilder.addNextParameter(AsmTypes.OBJECT_TYPE, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (JvmMethodParameterSignature param : valueParameters) {
|
for (JvmMethodParameterSignature param : jvmSignature.getValueParameters()) {
|
||||||
if (param.getKind() == JvmMethodParameterKind.VALUE) {
|
if (param.getKind() == JvmMethodParameterKind.VALUE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -643,10 +649,6 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
throw new IllegalStateException("Couldn't build context for " + descriptorName(descriptor));
|
throw new IllegalStateException("Couldn't build context for " + descriptorName(descriptor));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isStaticMethod(FunctionDescriptor functionDescriptor, MethodContext context) {
|
|
||||||
return (getMethodAsmFlags(functionDescriptor, context.getContextKind()) & Opcodes.ACC_STATIC) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String descriptorName(DeclarationDescriptor descriptor) {
|
private static String descriptorName(DeclarationDescriptor descriptor) {
|
||||||
return DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(descriptor);
|
return DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(descriptor);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
|||||||
import org.jetbrains.kotlin.codegen.context.CodegenContextUtil;
|
import org.jetbrains.kotlin.codegen.context.CodegenContextUtil;
|
||||||
import org.jetbrains.kotlin.codegen.context.InlineLambdaContext;
|
import org.jetbrains.kotlin.codegen.context.InlineLambdaContext;
|
||||||
import org.jetbrains.kotlin.codegen.context.MethodContext;
|
import org.jetbrains.kotlin.codegen.context.MethodContext;
|
||||||
|
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt;
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.UtilKt;
|
import org.jetbrains.kotlin.codegen.optimization.common.UtilKt;
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||||
@@ -84,7 +85,7 @@ public class InlineCodegenUtil {
|
|||||||
final String methodName,
|
final String methodName,
|
||||||
final String methodDescriptor,
|
final String methodDescriptor,
|
||||||
ClassId classId
|
ClassId classId
|
||||||
) throws ClassNotFoundException, IOException {
|
) throws IOException {
|
||||||
ClassReader cr = new ClassReader(classData);
|
ClassReader cr = new ClassReader(classData);
|
||||||
final MethodNode[] node = new MethodNode[1];
|
final MethodNode[] node = new MethodNode[1];
|
||||||
final String[] debugInfo = new String[2];
|
final String[] debugInfo = new String[2];
|
||||||
@@ -127,6 +128,15 @@ public class InlineCodegenUtil {
|
|||||||
}
|
}
|
||||||
}, ClassReader.SKIP_FRAMES | (GENERATE_SMAP ? 0 : ClassReader.SKIP_DEBUG));
|
}, ClassReader.SKIP_FRAMES | (GENERATE_SMAP ? 0 : ClassReader.SKIP_DEBUG));
|
||||||
|
|
||||||
|
if (node[0] == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classId.equals(IntrinsicArrayConstructorsKt.getClassId())) {
|
||||||
|
// Don't load source map for intrinsic array constructors
|
||||||
|
debugInfo[0] = null;
|
||||||
|
}
|
||||||
|
|
||||||
SMAP smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classId.asString(), lines[0], lines[1]);
|
SMAP smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classId.asString(), lines[0], lines[1]);
|
||||||
return new SMAPAndMethodNode(node[0], smap);
|
return new SMAPAndMethodNode(node[0], smap);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.codegen.intrinsics
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.codegen.Callable
|
||||||
|
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
|
object ArrayConstructor : IntrinsicMethod() {
|
||||||
|
override fun toCallable(method: CallableMethod): Callable {
|
||||||
|
return object : IntrinsicCallable(method.owner, method.valueParameterTypes, null, null) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
+107
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("unused")
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.codegen.intrinsics
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
|
// Bodies of methods in this file are used in InlineCodegen to inline array constructors. It is loaded via reflection at runtime.
|
||||||
|
// TODO: generate the bytecode manually instead, do not depend on the previous compiler working correctly here
|
||||||
|
|
||||||
|
internal val classId: ClassId =
|
||||||
|
ClassId.topLevel(FqName("org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt"))
|
||||||
|
|
||||||
|
internal val bytecode: ByteArray by lazy {
|
||||||
|
val stream = object {}.javaClass.classLoader.getResourceAsStream("${classId.asString()}.class")
|
||||||
|
stream.readBytes().apply {
|
||||||
|
stream.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <reified T> Array(size: Int, init: (Int) -> T): Array<T> {
|
||||||
|
val result = arrayOfNulls<T>(size)
|
||||||
|
for (i in 0..size - 1) {
|
||||||
|
result[i] = init(i)
|
||||||
|
}
|
||||||
|
return result as Array<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun DoubleArray(size: Int, init: (Int) -> Double): DoubleArray {
|
||||||
|
val result = DoubleArray(size)
|
||||||
|
for (i in 0..size - 1) {
|
||||||
|
result[i] = init(i)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun FloatArray(size: Int, init: (Int) -> Float): FloatArray {
|
||||||
|
val result = FloatArray(size)
|
||||||
|
for (i in 0..size - 1) {
|
||||||
|
result[i] = init(i)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun LongArray(size: Int, init: (Int) -> Long): LongArray {
|
||||||
|
val result = LongArray(size)
|
||||||
|
for (i in 0..size - 1) {
|
||||||
|
result[i] = init(i)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun IntArray(size: Int, init: (Int) -> Int): IntArray {
|
||||||
|
val result = IntArray(size)
|
||||||
|
for (i in 0..size - 1) {
|
||||||
|
result[i] = init(i)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun CharArray(size: Int, init: (Int) -> Char): CharArray {
|
||||||
|
val result = CharArray(size)
|
||||||
|
for (i in 0..size - 1) {
|
||||||
|
result[i] = init(i)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun ShortArray(size: Int, init: (Int) -> Short): ShortArray {
|
||||||
|
val result = ShortArray(size)
|
||||||
|
for (i in 0..size - 1) {
|
||||||
|
result[i] = init(i)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun ByteArray(size: Int, init: (Int) -> Byte): ByteArray {
|
||||||
|
val result = ByteArray(size)
|
||||||
|
for (i in 0..size - 1) {
|
||||||
|
result[i] = init(i)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun BooleanArray(size: Int, init: (Int) -> Boolean): BooleanArray {
|
||||||
|
val result = BooleanArray(size)
|
||||||
|
for (i in 0..size - 1) {
|
||||||
|
result[i] = init(i)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -29,9 +29,7 @@ import org.jetbrains.kotlin.name.Name;
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
|
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
|
||||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
|
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES;
|
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.*;
|
||||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME;
|
|
||||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.COLLECTIONS_PACKAGE_FQ_NAME;
|
|
||||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
public class IntrinsicMethods {
|
public class IntrinsicMethods {
|
||||||
@@ -150,6 +148,7 @@ public class IntrinsicMethods {
|
|||||||
declareIntrinsicFunction(arrayTypeFqName, "get", 1, ARRAY_GET);
|
declareIntrinsicFunction(arrayTypeFqName, "get", 1, ARRAY_GET);
|
||||||
declareIntrinsicFunction(arrayTypeFqName, "clone", 0, CLONE);
|
declareIntrinsicFunction(arrayTypeFqName, "clone", 0, CLONE);
|
||||||
declareIntrinsicFunction(arrayTypeFqName, "iterator", 0, ARRAY_ITERATOR);
|
declareIntrinsicFunction(arrayTypeFqName, "iterator", 0, ARRAY_ITERATOR);
|
||||||
|
declareIntrinsicFunction(arrayTypeFqName, "<init>", 2, ArrayConstructor.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void declareBinaryOp(@NotNull String methodName, int opcode) {
|
private void declareBinaryOp(@NotNull String methodName, int opcode) {
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ messages/**)
|
|||||||
public protected *;
|
public protected *;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-keep class org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt { *; }
|
||||||
|
|
||||||
-keep class org.jetbrains.org.objectweb.asm.Opcodes { *; }
|
-keep class org.jetbrains.org.objectweb.asm.Opcodes { *; }
|
||||||
|
|
||||||
-keep class org.jetbrains.kotlin.codegen.extensions.** {
|
-keep class org.jetbrains.kotlin.codegen.extensions.** {
|
||||||
|
|||||||
@@ -133,6 +133,17 @@ public class InlineUtil {
|
|||||||
return functionalExpression instanceof KtFunctionLiteral || functionalExpression instanceof KtNamedFunction;
|
return functionalExpression instanceof KtFunctionLiteral || functionalExpression instanceof KtNamedFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the descriptor is the constructor of one of 9 array classes (Array<T>, IntArray, FloatArray, ...)
|
||||||
|
* which takes the size and an initializer lambda as parameters. Such constructors are marked as 'inline' but they are not loaded
|
||||||
|
* as such because the 'inline' flag is not stored for constructors in the binary metadata. Therefore we pretend that they are inline
|
||||||
|
*/
|
||||||
|
public static boolean isArrayConstructorWithLambda(@NotNull CallableDescriptor descriptor) {
|
||||||
|
return descriptor.getValueParameters().size() == 2 &&
|
||||||
|
descriptor instanceof ConstructorDescriptor &&
|
||||||
|
KotlinBuiltIns.isArrayOrPrimitiveArray(((ConstructorDescriptor) descriptor).getContainingDeclaration());
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static DeclarationDescriptor getContainingClassOrFunctionDescriptor(@NotNull DeclarationDescriptor descriptor, boolean strict) {
|
public static DeclarationDescriptor getContainingClassOrFunctionDescriptor(@NotNull DeclarationDescriptor descriptor, boolean strict) {
|
||||||
DeclarationDescriptor current = strict ? descriptor.getContainingDeclaration() : descriptor;
|
DeclarationDescriptor current = strict ? descriptor.getContainingDeclaration() : descriptor;
|
||||||
|
|||||||
@@ -878,6 +878,10 @@ public abstract class KotlinBuiltIns {
|
|||||||
return isConstructedFromGivenClass(type, FQ_NAMES.array);
|
return isConstructedFromGivenClass(type, FQ_NAMES.array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isArrayOrPrimitiveArray(@NotNull ClassDescriptor descriptor) {
|
||||||
|
return classFqNameEquals(descriptor, FQ_NAMES.array) || getPrimitiveTypeByArrayClassFqName(getFqName(descriptor)) != null;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isPrimitiveArray(@NotNull KotlinType type) {
|
public static boolean isPrimitiveArray(@NotNull KotlinType type) {
|
||||||
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
|
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
|
||||||
return descriptor != null && getPrimitiveTypeByArrayClassFqName(getFqName(descriptor)) != null;
|
return descriptor != null && getPrimitiveTypeByArrayClassFqName(getFqName(descriptor)) != null;
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2016 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package kotlin.jvm.internal
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
object IntrinsicArrayConstructors {
|
|
||||||
private inline fun <reified T> Array(size: Int, init: (Int) -> T): Array<T> {
|
|
||||||
val result = arrayOfNulls<T>(size)
|
|
||||||
for (i in 0..size - 1) {
|
|
||||||
result[i] = init(i)
|
|
||||||
}
|
|
||||||
return result as Array<T>
|
|
||||||
}
|
|
||||||
|
|
||||||
private inline fun DoubleArray(size: Int, init: (Int) -> Double): DoubleArray {
|
|
||||||
val result = DoubleArray(size)
|
|
||||||
for (i in 0..size - 1) {
|
|
||||||
result[i] = init(i)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private inline fun FloatArray(size: Int, init: (Int) -> Float): FloatArray {
|
|
||||||
val result = FloatArray(size)
|
|
||||||
for (i in 0..size - 1) {
|
|
||||||
result[i] = init(i)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private inline fun LongArray(size: Int, init: (Int) -> Long): LongArray {
|
|
||||||
val result = LongArray(size)
|
|
||||||
for (i in 0..size - 1) {
|
|
||||||
result[i] = init(i)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private inline fun IntArray(size: Int, init: (Int) -> Int): IntArray {
|
|
||||||
val result = IntArray(size)
|
|
||||||
for (i in 0..size - 1) {
|
|
||||||
result[i] = init(i)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private inline fun CharArray(size: Int, init: (Int) -> Char): CharArray {
|
|
||||||
val result = CharArray(size)
|
|
||||||
for (i in 0..size - 1) {
|
|
||||||
result[i] = init(i)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private inline fun ShortArray(size: Int, init: (Int) -> Short): ShortArray {
|
|
||||||
val result = ShortArray(size)
|
|
||||||
for (i in 0..size - 1) {
|
|
||||||
result[i] = init(i)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private inline fun ByteArray(size: Int, init: (Int) -> Byte): ByteArray {
|
|
||||||
val result = ByteArray(size)
|
|
||||||
for (i in 0..size - 1) {
|
|
||||||
result[i] = init(i)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private inline fun BooleanArray(size: Int, init: (Int) -> Boolean): BooleanArray {
|
|
||||||
val result = BooleanArray(size)
|
|
||||||
for (i in 0..size - 1) {
|
|
||||||
result[i] = init(i)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user