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:
Alexander Udalov
2016-01-27 03:28:35 +03:00
parent 0e11aa098f
commit 70e847b794
11 changed files with 253 additions and 192 deletions
@@ -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) {
@@ -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) {}
}
}
@@ -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) {
+2
View File
@@ -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&lt;T&gt;, 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
}
}