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.load.java.JvmAbi;
|
||||
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.psi.*;
|
||||
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.JvmMethodSignature;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.FindClassInModuleKt;
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeProjection;
|
||||
import org.jetbrains.kotlin.types.TypeUtils;
|
||||
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.MethodVisitor;
|
||||
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.resolve.BindingContext.*;
|
||||
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.types.expressions.ExpressionTypingUtils.isFunctionExpression;
|
||||
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
|
||||
// because they may contain something to reify and straight call will probably fail at runtime
|
||||
boolean isInline = (state.isInlineEnabled() || InlineUtil.containsReifiedTypeParameters(descriptor)) &&
|
||||
InlineUtil.isInline(descriptor);
|
||||
(InlineUtil.isInline(descriptor) || InlineUtil.isArrayConstructorWithLambda(descriptor));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -2457,6 +2454,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
KotlinType type = TypeUtils.uncaptureTypeForInlineMapping(entry.getValue());
|
||||
|
||||
boolean isReified = key.isReified() || InlineUtil.isArrayConstructorWithLambda(resolvedCall.getResultingDescriptor());
|
||||
|
||||
Pair<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type);
|
||||
if (typeParameterAndReificationArgument == null) {
|
||||
// type is not generic
|
||||
@@ -2464,16 +2463,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
Type asmType = typeMapper.mapTypeParameter(type, signatureWriter);
|
||||
|
||||
mappings.addParameterMappingToType(
|
||||
key.getName().getIdentifier(),
|
||||
type,
|
||||
asmType,
|
||||
signatureWriter.toString(),
|
||||
key.isReified());
|
||||
key.getName().getIdentifier(), type, asmType, signatureWriter.toString(), isReified
|
||||
);
|
||||
}
|
||||
else {
|
||||
mappings.addParameterMappingForFurtherReification(
|
||||
key.getName().getIdentifier(), type,
|
||||
typeParameterAndReificationArgument.getSecond(), key.isReified());
|
||||
key.getName().getIdentifier(), type, typeParameterAndReificationArgument.getSecond(), isReified
|
||||
);
|
||||
}
|
||||
}
|
||||
return getOrCreateCallGenerator(
|
||||
@@ -3412,50 +3408,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
});
|
||||
}
|
||||
|
||||
final ConstructorDescriptor constructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor();
|
||||
|
||||
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));
|
||||
return invokeFunction(resolvedCall, StackValue.none());
|
||||
}
|
||||
|
||||
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.codegen.*;
|
||||
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.JetTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
@@ -69,7 +70,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
private final GenerationState state;
|
||||
private final JetTypeMapper typeMapper;
|
||||
|
||||
private final SimpleFunctionDescriptor functionDescriptor;
|
||||
private final FunctionDescriptor functionDescriptor;
|
||||
private final JvmMethodSignature jvmSignature;
|
||||
private final KtElement callElement;
|
||||
private final MethodContext context;
|
||||
@@ -92,17 +93,21 @@ public class InlineCodegen extends CallGenerator {
|
||||
public InlineCodegen(
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@NotNull GenerationState state,
|
||||
@NotNull SimpleFunctionDescriptor functionDescriptor,
|
||||
@NotNull FunctionDescriptor function,
|
||||
@NotNull KtElement callElement,
|
||||
@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.typeMapper = state.getTypeMapper();
|
||||
this.codegen = codegen;
|
||||
this.callElement = callElement;
|
||||
this.functionDescriptor = functionDescriptor.getOriginal();
|
||||
this.functionDescriptor =
|
||||
InlineUtil.isArrayConstructorWithLambda(function)
|
||||
? FictitiousArrayConstructor.create((ConstructorDescriptor) function)
|
||||
: function.getOriginal();
|
||||
this.typeParameterMappings = typeParameterMappings;
|
||||
|
||||
reifiedTypeInliner = new ReifiedTypeInliner(typeParameterMappings);
|
||||
@@ -119,13 +124,14 @@ public class InlineCodegen extends CallGenerator {
|
||||
isSameModule = JvmCodegenUtil.isCallInsideSameModuleAsDeclared(functionDescriptor, codegen.getContext(), state.getOutDirectory());
|
||||
|
||||
sourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper();
|
||||
reportIncrementalInfo(functionDescriptor, codegen.getContext().getFunctionDescriptor().getOriginal());
|
||||
|
||||
if (!(functionDescriptor instanceof FictitiousArrayConstructor)) {
|
||||
reportIncrementalInfo(functionDescriptor, codegen.getContext().getFunctionDescriptor().getOriginal());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void genCallWithoutAssertions(
|
||||
@NotNull CallableMethod callableMethod, @NotNull ExpressionCodegen codegen
|
||||
) {
|
||||
public void genCallWithoutAssertions(@NotNull CallableMethod callableMethod, @NotNull ExpressionCodegen codegen) {
|
||||
genCall(callableMethod, null, false, codegen);
|
||||
}
|
||||
|
||||
@@ -176,19 +182,25 @@ public class InlineCodegen extends CallGenerator {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private SMAPAndMethodNode createMethodNode(boolean callDefault) throws ClassNotFoundException, IOException {
|
||||
JvmMethodSignature jvmSignature = typeMapper.mapSignature(functionDescriptor, context.getContextKind());
|
||||
|
||||
Method asmMethod;
|
||||
if (callDefault) {
|
||||
asmMethod = typeMapper.mapDefaultMethod(functionDescriptor, context.getContextKind());
|
||||
}
|
||||
else {
|
||||
asmMethod = jvmSignature.getAsmMethod();
|
||||
}
|
||||
private SMAPAndMethodNode createMethodNode(boolean callDefault) throws IOException {
|
||||
Method asmMethod = callDefault
|
||||
? typeMapper.mapDefaultMethod(functionDescriptor, context.getContextKind())
|
||||
: jvmSignature.getAsmMethod();
|
||||
|
||||
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(
|
||||
(DeserializedSimpleFunctionDescriptor) functionDescriptor);
|
||||
|
||||
@@ -203,14 +215,14 @@ public class InlineCodegen extends CallGenerator {
|
||||
);
|
||||
|
||||
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 {
|
||||
PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor);
|
||||
|
||||
if (element == null || !(element instanceof KtNamedFunction)) {
|
||||
throw new RuntimeException("Couldn't find declaration for function " + descriptorName(functionDescriptor));
|
||||
if (!(element instanceof KtNamedFunction)) {
|
||||
throw new IllegalStateException("Couldn't find declaration for function " + descriptorName(functionDescriptor));
|
||||
}
|
||||
KtNamedFunction inliningFunction = (KtNamedFunction) element;
|
||||
|
||||
@@ -260,14 +272,10 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
Parameters parameters = invocationParamBuilder.buildParameters();
|
||||
|
||||
InliningContext info = new RootInliningContext(expressionMap,
|
||||
state,
|
||||
codegen.getInlineNameGenerator()
|
||||
.subGenerator(functionDescriptor.getName().asString()),
|
||||
codegen.getContext(),
|
||||
callElement,
|
||||
getInlineCallSiteInfo(), reifiedTypeInliner,
|
||||
typeParameterMappings);
|
||||
InliningContext info = new RootInliningContext(
|
||||
expressionMap, state, codegen.getInlineNameGenerator().subGenerator(jvmSignature.getAsmMethod().getName()),
|
||||
codegen.getContext(), callElement, getInlineCallSiteInfo(), reifiedTypeInliner, typeParameterMappings
|
||||
);
|
||||
|
||||
MethodInliner inliner = new MethodInliner(node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule,
|
||||
"Method inlining " + callElement.getText(),
|
||||
@@ -529,13 +537,11 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
@Override
|
||||
public void putHiddenParams() {
|
||||
List<JvmMethodParameterSignature> valueParameters = jvmSignature.getValueParameters();
|
||||
|
||||
if (!isStaticMethod(functionDescriptor, context)) {
|
||||
if ((getMethodAsmFlags(functionDescriptor, context.getContextKind()) & Opcodes.ACC_STATIC) == 0) {
|
||||
invocationParamBuilder.addNextParameter(AsmTypes.OBJECT_TYPE, false, null);
|
||||
}
|
||||
|
||||
for (JvmMethodParameterSignature param : valueParameters) {
|
||||
for (JvmMethodParameterSignature param : jvmSignature.getValueParameters()) {
|
||||
if (param.getKind() == JvmMethodParameterKind.VALUE) {
|
||||
break;
|
||||
}
|
||||
@@ -643,10 +649,6 @@ public class InlineCodegen extends CallGenerator {
|
||||
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) {
|
||||
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.InlineLambdaContext;
|
||||
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.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
@@ -84,7 +85,7 @@ public class InlineCodegenUtil {
|
||||
final String methodName,
|
||||
final String methodDescriptor,
|
||||
ClassId classId
|
||||
) throws ClassNotFoundException, IOException {
|
||||
) throws IOException {
|
||||
ClassReader cr = new ClassReader(classData);
|
||||
final MethodNode[] node = new MethodNode[1];
|
||||
final String[] debugInfo = new String[2];
|
||||
@@ -127,6 +128,15 @@ public class InlineCodegenUtil {
|
||||
}
|
||||
}, 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]);
|
||||
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.types.expressions.OperatorConventions;
|
||||
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES;
|
||||
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.kotlin.builtins.KotlinBuiltIns.*;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class IntrinsicMethods {
|
||||
@@ -150,6 +148,7 @@ public class IntrinsicMethods {
|
||||
declareIntrinsicFunction(arrayTypeFqName, "get", 1, ARRAY_GET);
|
||||
declareIntrinsicFunction(arrayTypeFqName, "clone", 0, CLONE);
|
||||
declareIntrinsicFunction(arrayTypeFqName, "iterator", 0, ARRAY_ITERATOR);
|
||||
declareIntrinsicFunction(arrayTypeFqName, "<init>", 2, ArrayConstructor.INSTANCE);
|
||||
}
|
||||
|
||||
private void declareBinaryOp(@NotNull String methodName, int opcode) {
|
||||
|
||||
@@ -69,6 +69,8 @@ messages/**)
|
||||
public protected *;
|
||||
}
|
||||
|
||||
-keep class org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt { *; }
|
||||
|
||||
-keep class org.jetbrains.org.objectweb.asm.Opcodes { *; }
|
||||
|
||||
-keep class org.jetbrains.kotlin.codegen.extensions.** {
|
||||
|
||||
@@ -133,6 +133,17 @@ public class InlineUtil {
|
||||
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
|
||||
public static DeclarationDescriptor getContainingClassOrFunctionDescriptor(@NotNull DeclarationDescriptor descriptor, boolean strict) {
|
||||
DeclarationDescriptor current = strict ? descriptor.getContainingDeclaration() : descriptor;
|
||||
|
||||
@@ -878,6 +878,10 @@ public abstract class KotlinBuiltIns {
|
||||
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) {
|
||||
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
|
||||
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