[K/N] Added functions for set/get array operatorswithout bounds check
This commit is contained in:
@@ -59,6 +59,7 @@ interface IrDeclarationOrigin {
|
||||
object IR_BUILTINS_STUB : IrDeclarationOriginImpl("IR_BUILTINS_STUB")
|
||||
object BRIDGE : IrDeclarationOriginImpl("BRIDGE", isSynthetic = true)
|
||||
object BRIDGE_SPECIAL : IrDeclarationOriginImpl("BRIDGE_SPECIAL")
|
||||
object GENERATED_SETTER_GETTER : IrDeclarationOriginImpl("GENERATED_SETTER_GETTER", isSynthetic = true)
|
||||
|
||||
object FIELD_FOR_ENUM_ENTRY : IrDeclarationOriginImpl("FIELD_FOR_ENUM_ENTRY")
|
||||
object SYNTHETIC_HELPER_FOR_ENUM_VALUES : IrDeclarationOriginImpl("SYNTHETIC_HELPER_FOR_ENUM_VALUES", isSynthetic = true)
|
||||
|
||||
@@ -85,6 +85,9 @@ fun IrSimpleFunction.overrides(other: IrSimpleFunction): Boolean {
|
||||
private val IrConstructorCall.annotationClass
|
||||
get() = this.symbol.owner.constructedClass
|
||||
|
||||
fun IrConstructorCall.isAnnotationWithEqualFqName(fqName: FqName): Boolean =
|
||||
annotationClass.hasEqualFqName(fqName)
|
||||
|
||||
val IrClass.packageFqName: FqName?
|
||||
get() = symbol.signature?.packageFqName() ?: parent.getPackageFragment()?.fqName
|
||||
|
||||
|
||||
+10
-1
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.lower.loops.ForLoopsLowering
|
||||
import org.jetbrains.kotlin.backend.common.lower.optimizations.FoldConstantLowering
|
||||
import org.jetbrains.kotlin.backend.common.lower.optimizations.PropertyAccessorInlineLowering
|
||||
import org.jetbrains.kotlin.backend.common.phaser.*
|
||||
import org.jetbrains.kotlin.backend.konan.ir.FunctionsWithoutBCGenerator
|
||||
import org.jetbrains.kotlin.backend.konan.lower.*
|
||||
import org.jetbrains.kotlin.backend.konan.lower.FinallyBlocksLowering
|
||||
import org.jetbrains.kotlin.backend.konan.lower.InitializersLowering
|
||||
@@ -331,11 +332,19 @@ internal val interopPhase = makeKonanFileLoweringPhase(
|
||||
prerequisite = setOf(inlinePhase, localFunctionsPhase, functionReferencePhase)
|
||||
)
|
||||
|
||||
internal val functionsWithoutBC = makeKonanModuleOpPhase(
|
||||
name = "FunctionsWithoutBCGenerator",
|
||||
description = "Functions without bounds check generation",
|
||||
op = { context, _ ->
|
||||
FunctionsWithoutBCGenerator(context).generate()
|
||||
}
|
||||
)
|
||||
|
||||
internal val varargPhase = makeKonanFileLoweringPhase(
|
||||
::VarargInjectionLowering,
|
||||
name = "Vararg",
|
||||
description = "Vararg lowering",
|
||||
prerequisite = setOf(functionReferencePhase, defaultParameterExtentPhase, interopPhase)
|
||||
prerequisite = setOf(functionReferencePhase, defaultParameterExtentPhase, interopPhase, functionsWithoutBC)
|
||||
)
|
||||
|
||||
internal val compileTimeEvaluatePhase = makeKonanFileLoweringPhase(
|
||||
|
||||
+1
@@ -390,6 +390,7 @@ private val backendCodegen = namedUnitPhase(
|
||||
name = "Backend codegen",
|
||||
description = "Backend code generation",
|
||||
lower = takeFromContext<Context, Unit, IrModuleFragment> { it.irModule!! } then
|
||||
functionsWithoutBC then
|
||||
allLoweringsPhase then // Lower current module first.
|
||||
dependenciesLowerPhase then // Then lower all libraries in topological order.
|
||||
// With that we guarantee that inline functions are unlowered while being inlined.
|
||||
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||
import org.jetbrains.kotlin.backend.common.ir.createDispatchReceiverParameter
|
||||
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
||||
import org.jetbrains.kotlin.backend.konan.KonanFqNames
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.getAnnotationStringValue
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.addMember
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
||||
import org.jetbrains.kotlin.ir.util.functions
|
||||
import org.jetbrains.kotlin.ir.util.isAnnotationWithEqualFqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
// Generate additional functions for array set and get operators without bounds checking.
|
||||
internal class FunctionsWithoutBCGenerator(val context: KonanBackendContext) {
|
||||
private val symbols = context.ir.symbols
|
||||
|
||||
private fun generateFunction(baseFunction: IrSimpleFunction, functionName: Name) =
|
||||
context.irFactory.createFunction(
|
||||
baseFunction.startOffset, baseFunction.endOffset,
|
||||
IrDeclarationOrigin.GENERATED_SETTER_GETTER,
|
||||
IrSimpleFunctionSymbolImpl(),
|
||||
functionName,
|
||||
DescriptorVisibilities.PUBLIC,
|
||||
Modality.FINAL,
|
||||
baseFunction.returnType,
|
||||
isInline = baseFunction.isInline,
|
||||
isExternal = baseFunction.isExternal,
|
||||
isTailrec = baseFunction.isTailrec,
|
||||
isSuspend = baseFunction.isSuspend,
|
||||
isExpect = baseFunction.isExpect,
|
||||
isFakeOverride = baseFunction.isFakeOverride,
|
||||
isOperator = baseFunction.isOperator,
|
||||
isInfix = baseFunction.isInfix
|
||||
).also { function ->
|
||||
function.parent = baseFunction.parent
|
||||
function.createDispatchReceiverParameter()
|
||||
function.valueParameters = baseFunction.valueParameters.map { it.copyTo(function) }
|
||||
// Copy annotations.
|
||||
val setWithoutBEAnnotations = baseFunction.annotations.map { annotation ->
|
||||
annotation.deepCopyWithSymbols().also { copy ->
|
||||
if (copy.isAnnotationWithEqualFqName(KonanFqNames.gcUnsafeCall)) {
|
||||
val value = "${annotation.getAnnotationStringValue("callee")}_without_BC"
|
||||
copy.putValueArgument(0,
|
||||
IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.stringType, value))
|
||||
}
|
||||
}
|
||||
}
|
||||
function.annotations = setWithoutBEAnnotations
|
||||
}
|
||||
|
||||
|
||||
fun generate() {
|
||||
val arraysClasses = symbols.primitiveArrays.values + symbols.array
|
||||
arraysClasses.forEach { classSymbol ->
|
||||
val setFunction = classSymbol.owner.functions.single { it.name == OperatorNameConventions.SET }
|
||||
classSymbol.owner.addMember(generateFunction(setFunction, KonanNameConventions.setWithoutBC))
|
||||
|
||||
val getFunction = classSymbol.owner.functions.single { it.descriptor.name == OperatorNameConventions.GET }
|
||||
classSymbol.owner.addMember(generateFunction(getFunction, KonanNameConventions.getWithoutBC))
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -39,6 +39,11 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
object KonanNameConventions {
|
||||
val setWithoutBC = Name.special("<setWithoutBC>")
|
||||
val getWithoutBC = Name.special("<getWithoutBC>")
|
||||
}
|
||||
|
||||
// This is what Context collects about IR.
|
||||
internal class KonanIr(context: Context, irModule: IrModuleFragment): Ir<Context>(context, irModule) {
|
||||
override var symbols: KonanSymbols by Delegates.notNull()
|
||||
|
||||
@@ -71,21 +71,57 @@ inline void copyImpl(KConstRef thiz, KInt fromIndex,
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
template <class T, bool BoundsCheck = true>
|
||||
inline void PrimitiveArraySet(KRef thiz, KInt index, T value) {
|
||||
ArrayHeader* array = thiz->array();
|
||||
boundsCheck(array, index);
|
||||
if (BoundsCheck)
|
||||
boundsCheck(array, index);
|
||||
mutabilityCheck(thiz);
|
||||
*PrimitiveArrayAddressOfElementAt<T>(array, index) = value;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
template <class T, bool BoundsCheck = true>
|
||||
inline T PrimitiveArrayGet(KConstRef thiz, KInt index) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
boundsCheck(array, index);
|
||||
if (BoundsCheck)
|
||||
boundsCheck(array, index);
|
||||
return *PrimitiveArrayAddressOfElementAt<T>(array, index);
|
||||
}
|
||||
|
||||
template<bool BoundsCheck = true>
|
||||
ALWAYS_INLINE const KRef* Kotlin_Array_get_value(KConstRef thiz, KInt index) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
if (BoundsCheck)
|
||||
boundsCheck(array, index);
|
||||
return ArrayAddressOfElementAt(array, index);
|
||||
}
|
||||
|
||||
template<bool BoundsCheck = true>
|
||||
ALWAYS_INLINE void Kotlin_Array_set_value(KRef thiz, KInt index, KConstRef value) {
|
||||
ArrayHeader* array = thiz->array();
|
||||
if (BoundsCheck)
|
||||
boundsCheck(array, index);
|
||||
mutabilityCheck(thiz);
|
||||
UpdateHeapRef(ArrayAddressOfElementAt(array, index), value);
|
||||
}
|
||||
|
||||
template<bool BoundsCheck = true>
|
||||
ALWAYS_INLINE KByte Kotlin_ByteArray_get_value(KConstRef thiz, KInt index) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
if (BoundsCheck)
|
||||
boundsCheck(array, index);
|
||||
return *ByteArrayAddressOfElementAt(array, index);
|
||||
}
|
||||
|
||||
template<bool BoundsCheck = true>
|
||||
ALWAYS_INLINE void Kotlin_ByteArray_set_value(KRef thiz, KInt index, KByte value) {
|
||||
ArrayHeader* array = thiz->array();
|
||||
if (BoundsCheck)
|
||||
boundsCheck(array, index);
|
||||
mutabilityCheck(thiz);
|
||||
*ByteArrayAddressOfElementAt(array, index) = value;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
@@ -97,16 +133,19 @@ extern const ObjHeader theEmptyArray;
|
||||
|
||||
// Array.kt
|
||||
OBJ_GETTER(Kotlin_Array_get, KConstRef thiz, KInt index) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
boundsCheck(array, index);
|
||||
RETURN_OBJ(*ArrayAddressOfElementAt(array, index));
|
||||
RETURN_OBJ(*Kotlin_Array_get_value(thiz, index));
|
||||
}
|
||||
|
||||
OBJ_GETTER(Kotlin_Array_get_without_BC, KConstRef thiz, KInt index){
|
||||
RETURN_OBJ(*Kotlin_Array_get_value<false>(thiz, index));
|
||||
}
|
||||
|
||||
void Kotlin_Array_set(KRef thiz, KInt index, KConstRef value) {
|
||||
ArrayHeader* array = thiz->array();
|
||||
boundsCheck(array, index);
|
||||
mutabilityCheck(thiz);
|
||||
UpdateHeapRef(ArrayAddressOfElementAt(array, index), value);
|
||||
Kotlin_Array_set_value(thiz, index, value);
|
||||
}
|
||||
|
||||
void Kotlin_Array_set_without_BC(KRef thiz, KInt index, KConstRef value) {
|
||||
Kotlin_Array_set_value<false>(thiz, index, value);
|
||||
}
|
||||
|
||||
KInt Kotlin_Array_getArrayLength(KConstRef thiz) {
|
||||
@@ -157,16 +196,19 @@ OBJ_GETTER0(Kotlin_emptyArray) {
|
||||
}
|
||||
|
||||
KByte Kotlin_ByteArray_get(KConstRef thiz, KInt index) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
boundsCheck(array, index);
|
||||
return *ByteArrayAddressOfElementAt(array, index);
|
||||
return Kotlin_ByteArray_get_value(thiz, index);
|
||||
}
|
||||
|
||||
KByte Kotlin_ByteArray_get_without_BC(KConstRef thiz, KInt index) {
|
||||
return Kotlin_ByteArray_get_value<false>(thiz, index);
|
||||
}
|
||||
|
||||
void Kotlin_ByteArray_set(KRef thiz, KInt index, KByte value) {
|
||||
ArrayHeader* array = thiz->array();
|
||||
boundsCheck(array, index);
|
||||
mutabilityCheck(thiz);
|
||||
*ByteArrayAddressOfElementAt(array, index) = value;
|
||||
Kotlin_ByteArray_set_value(thiz, index, value);
|
||||
}
|
||||
|
||||
void Kotlin_ByteArray_set_without_BC(KRef thiz, KInt index, KByte value) {
|
||||
Kotlin_ByteArray_set_value<false>(thiz, index, value);
|
||||
}
|
||||
|
||||
KInt Kotlin_ByteArray_getArrayLength(KConstRef thiz) {
|
||||
@@ -447,10 +489,18 @@ KChar Kotlin_CharArray_get(KConstRef thiz, KInt index) {
|
||||
return PrimitiveArrayGet<KChar>(thiz, index);
|
||||
}
|
||||
|
||||
KChar Kotlin_CharArray_get_without_BC(KConstRef thiz, KInt index) {
|
||||
return PrimitiveArrayGet<KChar, false>(thiz, index);
|
||||
}
|
||||
|
||||
void Kotlin_CharArray_set(KRef thiz, KInt index, KChar value) {
|
||||
PrimitiveArraySet(thiz, index, value);
|
||||
}
|
||||
|
||||
void Kotlin_CharArray_set_without_BC(KRef thiz, KInt index, KChar value) {
|
||||
PrimitiveArraySet<KChar, false>(thiz, index, value);
|
||||
}
|
||||
|
||||
OBJ_GETTER(Kotlin_CharArray_copyOf, KConstRef thiz, KInt newSize) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
if (newSize < 0) {
|
||||
@@ -474,10 +524,18 @@ KShort Kotlin_ShortArray_get(KConstRef thiz, KInt index) {
|
||||
return PrimitiveArrayGet<KShort>(thiz, index);
|
||||
}
|
||||
|
||||
KShort Kotlin_ShortArray_get_without_BC(KConstRef thiz, KInt index) {
|
||||
return PrimitiveArrayGet<KShort, false>(thiz, index);
|
||||
}
|
||||
|
||||
void Kotlin_ShortArray_set(KRef thiz, KInt index, KShort value) {
|
||||
PrimitiveArraySet(thiz, index, value);
|
||||
}
|
||||
|
||||
void Kotlin_ShortArray_set_without_BC(KRef thiz, KInt index, KShort value) {
|
||||
PrimitiveArraySet<KShort, false>(thiz, index, value);
|
||||
}
|
||||
|
||||
KInt Kotlin_ShortArray_getArrayLength(KConstRef thiz) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
return array->count_;
|
||||
@@ -487,10 +545,18 @@ KInt Kotlin_IntArray_get(KConstRef thiz, KInt index) {
|
||||
return PrimitiveArrayGet<KInt>(thiz, index);
|
||||
}
|
||||
|
||||
KInt Kotlin_IntArray_get_without_BC(KConstRef thiz, KInt index) {
|
||||
return PrimitiveArrayGet<KInt, false>(thiz, index);
|
||||
}
|
||||
|
||||
void Kotlin_IntArray_set(KRef thiz, KInt index, KInt value) {
|
||||
PrimitiveArraySet(thiz, index, value);
|
||||
}
|
||||
|
||||
void Kotlin_IntArray_set_without_BC(KRef thiz, KInt index, KInt value) {
|
||||
PrimitiveArraySet<KInt, false>(thiz, index, value);
|
||||
}
|
||||
|
||||
KInt Kotlin_IntArray_getArrayLength(KConstRef thiz) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
return array->count_;
|
||||
@@ -572,10 +638,18 @@ KLong Kotlin_LongArray_get(KConstRef thiz, KInt index) {
|
||||
return PrimitiveArrayGet<KLong>(thiz, index);
|
||||
}
|
||||
|
||||
KLong Kotlin_LongArray_get_without_BC(KConstRef thiz, KInt index) {
|
||||
return PrimitiveArrayGet<KLong, false>(thiz, index);
|
||||
}
|
||||
|
||||
void Kotlin_LongArray_set(KRef thiz, KInt index, KLong value) {
|
||||
PrimitiveArraySet(thiz, index, value);
|
||||
}
|
||||
|
||||
void Kotlin_LongArray_set_without_BC(KRef thiz, KInt index, KLong value) {
|
||||
PrimitiveArraySet<KLong, false>(thiz, index, value);
|
||||
}
|
||||
|
||||
KInt Kotlin_LongArray_getArrayLength(KConstRef thiz) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
return array->count_;
|
||||
@@ -585,10 +659,18 @@ KFloat Kotlin_FloatArray_get(KConstRef thiz, KInt index) {
|
||||
return PrimitiveArrayGet<KFloat>(thiz, index);
|
||||
}
|
||||
|
||||
KFloat Kotlin_FloatArray_get_without_BC(KConstRef thiz, KInt index) {
|
||||
return PrimitiveArrayGet<KFloat, false>(thiz, index);
|
||||
}
|
||||
|
||||
void Kotlin_FloatArray_set(KRef thiz, KInt index, KFloat value) {
|
||||
PrimitiveArraySet(thiz, index, value);
|
||||
}
|
||||
|
||||
void Kotlin_FloatArray_set_without_BC(KRef thiz, KInt index, KFloat value) {
|
||||
PrimitiveArraySet<KFloat, false>(thiz, index, value);
|
||||
}
|
||||
|
||||
KInt Kotlin_FloatArray_getArrayLength(KConstRef thiz) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
return array->count_;
|
||||
@@ -598,10 +680,18 @@ KDouble Kotlin_DoubleArray_get(KConstRef thiz, KInt index) {
|
||||
return PrimitiveArrayGet<KDouble>(thiz, index);
|
||||
}
|
||||
|
||||
KDouble Kotlin_DoubleArray_get_without_BC(KConstRef thiz, KInt index) {
|
||||
return PrimitiveArrayGet<KDouble, false>(thiz, index);
|
||||
}
|
||||
|
||||
void Kotlin_DoubleArray_set(KRef thiz, KInt index, KDouble value) {
|
||||
PrimitiveArraySet(thiz, index, value);
|
||||
}
|
||||
|
||||
void Kotlin_DoubleArray_set_without_BC(KRef thiz, KInt index, KDouble value) {
|
||||
PrimitiveArraySet<KDouble, false>(thiz, index, value);
|
||||
}
|
||||
|
||||
KInt Kotlin_DoubleArray_getArrayLength(KConstRef thiz) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
return array->count_;
|
||||
@@ -611,10 +701,18 @@ KBoolean Kotlin_BooleanArray_get(KConstRef thiz, KInt index) {
|
||||
return PrimitiveArrayGet<KBoolean>(thiz, index);
|
||||
}
|
||||
|
||||
KBoolean Kotlin_BooleanArray_get_without_BC(KConstRef thiz, KInt index) {
|
||||
return PrimitiveArrayGet<KBoolean, false>(thiz, index);
|
||||
}
|
||||
|
||||
void Kotlin_BooleanArray_set(KRef thiz, KInt index, KBoolean value) {
|
||||
PrimitiveArraySet(thiz, index, value);
|
||||
}
|
||||
|
||||
void Kotlin_BooleanArray_set_without_BC(KRef thiz, KInt index, KBoolean value) {
|
||||
PrimitiveArraySet<KBoolean, false>(thiz, index, value);
|
||||
}
|
||||
|
||||
KInt Kotlin_BooleanArray_getArrayLength(KConstRef thiz) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
return array->count_;
|
||||
@@ -624,10 +722,18 @@ KNativePtr Kotlin_NativePtrArray_get(KConstRef thiz, KInt index) {
|
||||
return PrimitiveArrayGet<KNativePtr>(thiz, index);
|
||||
}
|
||||
|
||||
KNativePtr Kotlin_NativePtrArray_get_without_BC(KConstRef thiz, KInt index) {
|
||||
return PrimitiveArrayGet<KNativePtr, false>(thiz, index);
|
||||
}
|
||||
|
||||
void Kotlin_NativePtrArray_set(KRef thiz, KInt index, KNativePtr value) {
|
||||
PrimitiveArraySet(thiz, index, value);
|
||||
}
|
||||
|
||||
void Kotlin_NativePtrArray_set_without_BC(KRef thiz, KInt index, KNativePtr value) {
|
||||
PrimitiveArraySet<KNativePtr, false>(thiz, index, value);
|
||||
}
|
||||
|
||||
KInt Kotlin_NativePtrArray_getArrayLength(KConstRef thiz) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
return array->count_;
|
||||
|
||||
Reference in New Issue
Block a user