Changed an order of processing loops in ForLoopsLowering
This commit is contained in:
@@ -332,9 +332,9 @@ abstract class Symbols<out T : CommonBackendContext>(val context: T, irBuiltIns:
|
|||||||
|
|
||||||
open val unsafeCoerceIntrinsic: IrSimpleFunctionSymbol? = null
|
open val unsafeCoerceIntrinsic: IrSimpleFunctionSymbol? = null
|
||||||
|
|
||||||
open val getWithoutBCName: Name? = null
|
open val getWithoutBoundCheckName: Name? = null
|
||||||
|
|
||||||
open val setWithoutBCName: Name? = null
|
open val setWithoutBoundCheckName: Name? = null
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun isLateinitIsInitializedPropertyGetter(symbol: IrFunctionSymbol): Boolean =
|
fun isLateinitIsInitializedPropertyGetter(symbol: IrFunctionSymbol): Boolean =
|
||||||
|
|||||||
+10
-30
@@ -118,35 +118,14 @@ class ForLoopsLowering(val context: CommonBackendContext, val loopBodyTransforme
|
|||||||
* Abstract class for additional for-loop bodies transformations.
|
* Abstract class for additional for-loop bodies transformations.
|
||||||
*/
|
*/
|
||||||
abstract class ForLoopBodyTransformer : IrElementTransformerVoid() {
|
abstract class ForLoopBodyTransformer : IrElementTransformerVoid() {
|
||||||
protected lateinit var mainLoopVariable: IrVariable
|
|
||||||
protected lateinit var loopHeader: ForLoopHeader
|
|
||||||
protected lateinit var loopVariableComponents: Map<Int, IrVariable>
|
|
||||||
protected lateinit var context: CommonBackendContext
|
|
||||||
|
|
||||||
open fun initialize(
|
abstract fun transform(
|
||||||
context: CommonBackendContext,
|
|
||||||
loopVariable: IrVariable,
|
|
||||||
forLoopHeader: ForLoopHeader,
|
|
||||||
loopComponents: Map<Int, IrVariable>
|
|
||||||
) {
|
|
||||||
this.context = context
|
|
||||||
mainLoopVariable = loopVariable
|
|
||||||
loopHeader = forLoopHeader
|
|
||||||
loopVariableComponents = loopComponents
|
|
||||||
}
|
|
||||||
|
|
||||||
fun transform(
|
|
||||||
context: CommonBackendContext,
|
context: CommonBackendContext,
|
||||||
irExpression: IrExpression,
|
irExpression: IrExpression,
|
||||||
loopVariable: IrVariable,
|
loopVariable: IrVariable,
|
||||||
forLoopHeader: ForLoopHeader,
|
forLoopHeader: ForLoopHeader,
|
||||||
loopComponents: Map<Int, IrVariable>
|
loopComponents: Map<Int, IrVariable>
|
||||||
) {
|
)
|
||||||
initialize(context, loopVariable, forLoopHeader, loopComponents)
|
|
||||||
irExpression.transformChildrenVoid(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun shouldTransform(context: CommonBackendContext) = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RangeLoopTransformer(
|
private class RangeLoopTransformer(
|
||||||
@@ -162,6 +141,7 @@ private class RangeLoopTransformer(
|
|||||||
fun getScopeOwnerSymbol() = currentScope?.scope?.scopeOwnerSymbol ?: container.symbol
|
fun getScopeOwnerSymbol() = currentScope?.scope?.scopeOwnerSymbol ?: container.symbol
|
||||||
|
|
||||||
override fun visitBlock(expression: IrBlock): IrExpression {
|
override fun visitBlock(expression: IrBlock): IrExpression {
|
||||||
|
val returnExpression = super.visitBlock(expression) as IrBlock
|
||||||
// LoopExpressionGenerator in psi2ir lowers `for (loopVar in <someIterable>) { // Loop body }` into an IrBlock with origin FOR_LOOP.
|
// LoopExpressionGenerator in psi2ir lowers `for (loopVar in <someIterable>) { // Loop body }` into an IrBlock with origin FOR_LOOP.
|
||||||
// This block has 2 statements:
|
// This block has 2 statements:
|
||||||
//
|
//
|
||||||
@@ -178,21 +158,21 @@ private class RangeLoopTransformer(
|
|||||||
// `withIndex()` call, a progression such as `10 downTo 1`). However in some cases (e.g., for `withIndex()`), we also need to
|
// `withIndex()` call, a progression such as `10 downTo 1`). However in some cases (e.g., for `withIndex()`), we also need to
|
||||||
// examine the while loop to determine if we CAN optimize the loop.
|
// examine the while loop to determine if we CAN optimize the loop.
|
||||||
if (expression.origin != IrStatementOrigin.FOR_LOOP) {
|
if (expression.origin != IrStatementOrigin.FOR_LOOP) {
|
||||||
return super.visitBlock(expression) // Not a for-loop block.
|
return returnExpression // Not a for-loop block.
|
||||||
}
|
}
|
||||||
|
|
||||||
with(expression.statements) {
|
with(returnExpression.statements) {
|
||||||
assert(size == 2) { "Expected 2 statements in for-loop block, was:\n${expression.dump()}" }
|
assert(size == 2) { "Expected 2 statements in for-loop block, was:\n${returnExpression.dump()}" }
|
||||||
val iteratorVariable = get(0) as IrVariable
|
val iteratorVariable = get(0) as IrVariable
|
||||||
assert(iteratorVariable.origin == IrDeclarationOrigin.FOR_LOOP_ITERATOR) { "Expected FOR_LOOP_ITERATOR origin for iterator variable, was:\n${iteratorVariable.dump()}" }
|
assert(iteratorVariable.origin == IrDeclarationOrigin.FOR_LOOP_ITERATOR) { "Expected FOR_LOOP_ITERATOR origin for iterator variable, was:\n${iteratorVariable.dump()}" }
|
||||||
val loopHeader = headerProcessor.extractHeader(iteratorVariable)
|
val loopHeader = headerProcessor.extractHeader(iteratorVariable)
|
||||||
?: return super.visitBlock(expression) // The iterable in the header is not supported.
|
?: return returnExpression // The iterable in the header is not supported.
|
||||||
val loweredHeader = lowerHeader(iteratorVariable, loopHeader)
|
val loweredHeader = lowerHeader(iteratorVariable, loopHeader)
|
||||||
|
|
||||||
val oldLoop = get(1) as IrWhileLoop
|
val oldLoop = get(1) as IrWhileLoop
|
||||||
assert(oldLoop.origin == IrStatementOrigin.FOR_LOOP_INNER_WHILE) { "Expected FOR_LOOP_INNER_WHILE origin for while loop, was:\n${oldLoop.dump()}" }
|
assert(oldLoop.origin == IrStatementOrigin.FOR_LOOP_INNER_WHILE) { "Expected FOR_LOOP_INNER_WHILE origin for while loop, was:\n${oldLoop.dump()}" }
|
||||||
val (newLoop, loopReplacementExpression) = lowerWhileLoop(oldLoop, loopHeader)
|
val (newLoop, loopReplacementExpression) = lowerWhileLoop(oldLoop, loopHeader)
|
||||||
?: return super.visitBlock(expression) // Cannot lower the loop.
|
?: return returnExpression // Cannot lower the loop.
|
||||||
|
|
||||||
// We can lower both the header and while loop.
|
// We can lower both the header and while loop.
|
||||||
// Update mapping from old to new loop so we can later update references in break/continue.
|
// Update mapping from old to new loop so we can later update references in break/continue.
|
||||||
@@ -202,7 +182,7 @@ private class RangeLoopTransformer(
|
|||||||
set(1, loopReplacementExpression)
|
set(1, loopReplacementExpression)
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.visitBlock(expression)
|
return returnExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -296,7 +276,7 @@ private class RangeLoopTransformer(
|
|||||||
it
|
it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newBody != null && loopBodyTransformer != null && loopBodyTransformer.shouldTransform(context)) {
|
if (newBody != null && loopBodyTransformer != null) {
|
||||||
loopBodyTransformer.transform(context, newBody, mainLoopVariable, loopHeader, loopVariableComponents)
|
loopBodyTransformer.transform(context, newBody, mainLoopVariable, loopHeader, loopVariableComponents)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -81,7 +81,7 @@ internal class ArrayIterationHandler(context: CommonBackendContext) : IndexedGet
|
|||||||
get() = getClass()!!.getPropertyGetter("size")!!.owner
|
get() = getClass()!!.getPropertyGetter("size")!!.owner
|
||||||
|
|
||||||
private val getFunctionName: Name
|
private val getFunctionName: Name
|
||||||
get() = context.ir.symbols.getWithoutBCName ?: OperatorNameConventions.GET
|
get() = context.ir.symbols.getWithoutBoundCheckName ?: OperatorNameConventions.GET
|
||||||
|
|
||||||
override val IrType.getFunction
|
override val IrType.getFunction
|
||||||
get() = getClass()!!.functions.single {
|
get() = getClass()!!.functions.single {
|
||||||
|
|||||||
+12
-11
@@ -10,7 +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.FoldConstantLowering
|
||||||
import org.jetbrains.kotlin.backend.common.lower.optimizations.PropertyAccessorInlineLowering
|
import org.jetbrains.kotlin.backend.common.lower.optimizations.PropertyAccessorInlineLowering
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.*
|
import org.jetbrains.kotlin.backend.common.phaser.*
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.FunctionsWithoutBCGenerator
|
import org.jetbrains.kotlin.backend.konan.ir.FunctionsWithoutBoundCheckGenerator
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.*
|
import org.jetbrains.kotlin.backend.konan.lower.*
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.FinallyBlocksLowering
|
import org.jetbrains.kotlin.backend.konan.lower.FinallyBlocksLowering
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.InitializersLowering
|
import org.jetbrains.kotlin.backend.konan.lower.InitializersLowering
|
||||||
@@ -258,12 +258,21 @@ internal val rangeContainsLoweringPhase = makeKonanFileLoweringPhase(
|
|||||||
description = "Optimizes calls to contains() for ClosedRanges"
|
description = "Optimizes calls to contains() for ClosedRanges"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
internal val functionsWithoutBoundCheck = makeKonanModuleOpPhase(
|
||||||
|
name = "FunctionsWithoutBoundCheckGenerator",
|
||||||
|
description = "Functions without bounds check generation",
|
||||||
|
op = { context, _ ->
|
||||||
|
FunctionsWithoutBoundCheckGenerator(context).generate()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
internal val forLoopsPhase = makeKonanFileOpPhase(
|
internal val forLoopsPhase = makeKonanFileOpPhase(
|
||||||
{ context, irFile ->
|
{ context, irFile ->
|
||||||
ForLoopsLowering(context, KonanBCEForLoopBodyTransformer()).lower(irFile)
|
ForLoopsLowering(context, KonanBCEForLoopBodyTransformer()).lower(irFile)
|
||||||
},
|
},
|
||||||
name = "ForLoops",
|
name = "ForLoops",
|
||||||
description = "For loops lowering"
|
description = "For loops lowering",
|
||||||
|
prerequisite = setOf(functionsWithoutBoundCheck)
|
||||||
)
|
)
|
||||||
|
|
||||||
internal val dataClassesPhase = makeKonanFileLoweringPhase(
|
internal val dataClassesPhase = makeKonanFileLoweringPhase(
|
||||||
@@ -341,19 +350,11 @@ internal val interopPhase = makeKonanFileLoweringPhase(
|
|||||||
prerequisite = setOf(inlinePhase, localFunctionsPhase, functionReferencePhase)
|
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(
|
internal val varargPhase = makeKonanFileLoweringPhase(
|
||||||
::VarargInjectionLowering,
|
::VarargInjectionLowering,
|
||||||
name = "Vararg",
|
name = "Vararg",
|
||||||
description = "Vararg lowering",
|
description = "Vararg lowering",
|
||||||
prerequisite = setOf(functionReferencePhase, defaultParameterExtentPhase, interopPhase, functionsWithoutBC)
|
prerequisite = setOf(functionReferencePhase, defaultParameterExtentPhase, interopPhase, functionsWithoutBoundCheck)
|
||||||
)
|
)
|
||||||
|
|
||||||
internal val compileTimeEvaluatePhase = makeKonanFileLoweringPhase(
|
internal val compileTimeEvaluatePhase = makeKonanFileLoweringPhase(
|
||||||
|
|||||||
+1
-1
@@ -393,7 +393,7 @@ private val backendCodegen = namedUnitPhase(
|
|||||||
name = "Backend codegen",
|
name = "Backend codegen",
|
||||||
description = "Backend code generation",
|
description = "Backend code generation",
|
||||||
lower = takeFromContext<Context, Unit, IrModuleFragment> { it.irModule!! } then
|
lower = takeFromContext<Context, Unit, IrModuleFragment> { it.irModule!! } then
|
||||||
functionsWithoutBC then
|
functionsWithoutBoundCheck then
|
||||||
allLoweringsPhase then // Lower current module first.
|
allLoweringsPhase then // Lower current module first.
|
||||||
dependenciesLowerPhase then // Then lower all libraries in topological order.
|
dependenciesLowerPhase then // Then lower all libraries in topological order.
|
||||||
// With that we guarantee that inline functions are unlowered while being inlined.
|
// With that we guarantee that inline functions are unlowered while being inlined.
|
||||||
|
|||||||
+4
-4
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
// Generate additional functions for array set and get operators without bounds checking.
|
// Generate additional functions for array set and get operators without bounds checking.
|
||||||
internal class FunctionsWithoutBCGenerator(val context: KonanBackendContext) {
|
internal class FunctionsWithoutBoundCheckGenerator(val context: KonanBackendContext) {
|
||||||
private val symbols = context.ir.symbols
|
private val symbols = context.ir.symbols
|
||||||
|
|
||||||
private fun generateFunction(baseFunction: IrSimpleFunction, functionName: Name) =
|
private fun generateFunction(baseFunction: IrSimpleFunction, functionName: Name) =
|
||||||
@@ -55,7 +55,7 @@ internal class FunctionsWithoutBCGenerator(val context: KonanBackendContext) {
|
|||||||
val setWithoutBEAnnotations = baseFunction.annotations.map { annotation ->
|
val setWithoutBEAnnotations = baseFunction.annotations.map { annotation ->
|
||||||
annotation.deepCopyWithSymbols().also { copy ->
|
annotation.deepCopyWithSymbols().also { copy ->
|
||||||
if (copy.isAnnotationWithEqualFqName(KonanFqNames.gcUnsafeCall)) {
|
if (copy.isAnnotationWithEqualFqName(KonanFqNames.gcUnsafeCall)) {
|
||||||
val value = "${annotation.getAnnotationStringValue("callee")}_without_BC"
|
val value = "${annotation.getAnnotationStringValue("callee")}_without_BoundCheck"
|
||||||
copy.putValueArgument(0,
|
copy.putValueArgument(0,
|
||||||
IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.stringType, value))
|
IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.stringType, value))
|
||||||
}
|
}
|
||||||
@@ -69,10 +69,10 @@ internal class FunctionsWithoutBCGenerator(val context: KonanBackendContext) {
|
|||||||
val arraysClasses = symbols.primitiveArrays.values + symbols.array
|
val arraysClasses = symbols.primitiveArrays.values + symbols.array
|
||||||
arraysClasses.forEach { classSymbol ->
|
arraysClasses.forEach { classSymbol ->
|
||||||
val setFunction = classSymbol.owner.functions.single { it.name == OperatorNameConventions.SET }
|
val setFunction = classSymbol.owner.functions.single { it.name == OperatorNameConventions.SET }
|
||||||
classSymbol.owner.addMember(generateFunction(setFunction, KonanNameConventions.setWithoutBC))
|
classSymbol.owner.addMember(generateFunction(setFunction, KonanNameConventions.setWithoutBoundCheck))
|
||||||
|
|
||||||
val getFunction = classSymbol.owner.functions.single { it.descriptor.name == OperatorNameConventions.GET }
|
val getFunction = classSymbol.owner.functions.single { it.descriptor.name == OperatorNameConventions.GET }
|
||||||
classSymbol.owner.addMember(generateFunction(getFunction, KonanNameConventions.getWithoutBC))
|
classSymbol.owner.addMember(generateFunction(getFunction, KonanNameConventions.getWithoutBoundCheck))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+4
-4
@@ -43,8 +43,8 @@ import org.jetbrains.kotlin.types.Variance
|
|||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
object KonanNameConventions {
|
object KonanNameConventions {
|
||||||
val setWithoutBC = Name.special("<setWithoutBC>")
|
val setWithoutBoundCheck = Name.special("<setWithoutBoundCheck>")
|
||||||
val getWithoutBC = Name.special("<getWithoutBC>")
|
val getWithoutBoundCheck = Name.special("<getWithoutBoundCheck>")
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is what Context collects about IR.
|
// This is what Context collects about IR.
|
||||||
@@ -575,9 +575,9 @@ internal class KonanSymbols(
|
|||||||
val topLevelSuite = getKonanTestClass("TopLevelSuite")
|
val topLevelSuite = getKonanTestClass("TopLevelSuite")
|
||||||
val testFunctionKind = getKonanTestClass("TestFunctionKind")
|
val testFunctionKind = getKonanTestClass("TestFunctionKind")
|
||||||
|
|
||||||
override val getWithoutBCName: Name? = KonanNameConventions.getWithoutBC
|
override val getWithoutBoundCheckName: Name? = KonanNameConventions.getWithoutBoundCheck
|
||||||
|
|
||||||
override val setWithoutBCName: Name? = KonanNameConventions.setWithoutBC
|
override val setWithoutBoundCheckName: Name? = KonanNameConventions.setWithoutBoundCheck
|
||||||
|
|
||||||
private val testFunctionKindCache = TestProcessor.FunctionKind.values().associate {
|
private val testFunctionKindCache = TestProcessor.FunctionKind.values().associate {
|
||||||
val symbol = if (it.runtimeKindString.isEmpty())
|
val symbol = if (it.runtimeKindString.isEmpty())
|
||||||
|
|||||||
+1
-1
@@ -208,7 +208,7 @@ internal class VarargInjectionLowering constructor(val context: KonanBackendCont
|
|||||||
abstract inner class ArrayHandle(val arraySymbol: IrClassSymbol) {
|
abstract inner class ArrayHandle(val arraySymbol: IrClassSymbol) {
|
||||||
val setMethodSymbol = with(arraySymbol.owner.functions) {
|
val setMethodSymbol = with(arraySymbol.owner.functions) {
|
||||||
// For unsigned types use set method.
|
// For unsigned types use set method.
|
||||||
singleOrNull { it.name == KonanNameConventions.setWithoutBC } ?: single { it.name == OperatorNameConventions.SET }
|
singleOrNull { it.name == KonanNameConventions.setWithoutBoundCheck } ?: single { it.name == OperatorNameConventions.SET }
|
||||||
}
|
}
|
||||||
val sizeGetterSymbol = arraySymbol.getPropertyGetter("size")!!
|
val sizeGetterSymbol = arraySymbol.getPropertyGetter("size")!!
|
||||||
val copyIntoSymbol = symbols.copyInto[arraySymbol.descriptor]!!
|
val copyIntoSymbol = symbols.copyInto[arraySymbol.descriptor]!!
|
||||||
|
|||||||
+57
-50
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.util.IdSignature
|
|||||||
import org.jetbrains.kotlin.ir.util.functions
|
import org.jetbrains.kotlin.ir.util.functions
|
||||||
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
||||||
import org.jetbrains.kotlin.ir.util.isPrimitiveArray
|
import org.jetbrains.kotlin.ir.util.isPrimitiveArray
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
// Class contains information about analyzed loop.
|
// Class contains information about analyzed loop.
|
||||||
@@ -30,16 +31,22 @@ internal data class BoundsCheckAnalysisResult(val boundsAreSafe: Boolean, val ar
|
|||||||
* Transformer for for loops bodies replacing get/set operators on analogs without bounds check where it's possible.
|
* Transformer for for loops bodies replacing get/set operators on analogs without bounds check where it's possible.
|
||||||
*/
|
*/
|
||||||
class KonanBCEForLoopBodyTransformer : ForLoopBodyTransformer() {
|
class KonanBCEForLoopBodyTransformer : ForLoopBodyTransformer() {
|
||||||
|
lateinit var mainLoopVariable: IrVariable
|
||||||
|
lateinit var loopHeader: ForLoopHeader
|
||||||
|
lateinit var loopVariableComponents: Map<Int, IrVariable>
|
||||||
|
lateinit var context: CommonBackendContext
|
||||||
|
|
||||||
private var analysisResult: BoundsCheckAnalysisResult = BoundsCheckAnalysisResult(false, null)
|
private var analysisResult: BoundsCheckAnalysisResult = BoundsCheckAnalysisResult(false, null)
|
||||||
|
|
||||||
override fun shouldTransform(context: CommonBackendContext): Boolean {
|
override fun transform(context: CommonBackendContext, irExpression: IrExpression, loopVariable: IrVariable,
|
||||||
return context is Context && context.shouldOptimize()
|
forLoopHeader: ForLoopHeader, loopComponents: Map<Int, IrVariable>) {
|
||||||
}
|
this.context = context
|
||||||
|
mainLoopVariable = loopVariable
|
||||||
override fun initialize(context: CommonBackendContext, loopVariable: IrVariable,
|
loopHeader = forLoopHeader
|
||||||
forLoopHeader: ForLoopHeader, loopComponents: Map<Int, IrVariable>) {
|
loopVariableComponents = loopComponents
|
||||||
super.initialize(context, loopVariable, forLoopHeader, loopComponents)
|
|
||||||
analysisResult = analyzeLoopHeader(loopHeader)
|
analysisResult = analyzeLoopHeader(loopHeader)
|
||||||
|
if (analysisResult.boundsAreSafe && analysisResult.arrayInLoop != null)
|
||||||
|
irExpression.transformChildrenVoid(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrExpression.compareIntegerNumericConst(compare: (Long) -> Boolean): Boolean {
|
private fun IrExpression.compareIntegerNumericConst(compare: (Long) -> Boolean): Boolean {
|
||||||
@@ -60,46 +67,45 @@ class KonanBCEForLoopBodyTransformer : ForLoopBodyTransformer() {
|
|||||||
private fun IrCall.dispatchReceiverIsGetSizeCall() = (dispatchReceiver as? IrCall)?.let { it.isGetSizeCall() } ?: false
|
private fun IrCall.dispatchReceiverIsGetSizeCall() = (dispatchReceiver as? IrCall)?.let { it.isGetSizeCall() } ?: false
|
||||||
|
|
||||||
private fun lessThanSize(functionCall: IrCall): BoundsCheckAnalysisResult {
|
private fun lessThanSize(functionCall: IrCall): BoundsCheckAnalysisResult {
|
||||||
var result = false
|
val boundsAreSafe = when (functionCall.symbol.owner.name) {
|
||||||
when (functionCall.symbol.owner.name) {
|
|
||||||
OperatorNameConventions.DEC ->
|
OperatorNameConventions.DEC ->
|
||||||
if (functionCall.dispatchReceiverIsGetSizeCall()) {
|
functionCall.dispatchReceiverIsGetSizeCall()
|
||||||
result = true
|
|
||||||
}
|
|
||||||
OperatorNameConventions.MINUS -> {
|
OperatorNameConventions.MINUS -> {
|
||||||
val value = functionCall.getValueArgument(0)
|
val value = functionCall.getValueArgument(0)
|
||||||
result = functionCall.dispatchReceiverIsGetSizeCall() &&
|
functionCall.dispatchReceiverIsGetSizeCall() &&
|
||||||
value?.compareIntegerNumericConst { it > 0 } == true
|
value?.compareIntegerNumericConst { it > 0 } == true
|
||||||
}
|
}
|
||||||
OperatorNameConventions.DIV-> {
|
OperatorNameConventions.DIV -> {
|
||||||
val value = functionCall.getValueArgument(0)
|
val value = functionCall.getValueArgument(0)
|
||||||
result = functionCall.dispatchReceiverIsGetSizeCall() &&
|
functionCall.dispatchReceiverIsGetSizeCall() &&
|
||||||
value?.compareFloatNumericConst { it > 1 } == true
|
value?.compareFloatNumericConst { it > 1 } == true
|
||||||
}
|
}
|
||||||
|
else -> false
|
||||||
}
|
}
|
||||||
val array = ((functionCall.dispatchReceiver as? IrCall)?.dispatchReceiver as? IrGetValue)?.symbol
|
val array = ((functionCall.dispatchReceiver as? IrCall)?.dispatchReceiver as? IrGetValue)?.symbol
|
||||||
return BoundsCheckAnalysisResult(result, array)
|
return BoundsCheckAnalysisResult(boundsAreSafe, array)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkLastElement(last: IrExpression, loopHeader: ProgressionLoopHeader): BoundsCheckAnalysisResult {
|
private fun checkLastElement(last: IrExpression, loopHeader: ProgressionLoopHeader): BoundsCheckAnalysisResult {
|
||||||
var result = BoundsCheckAnalysisResult(false, null)
|
return if (last is IrCall) {
|
||||||
if (last is IrCall) {
|
|
||||||
result = lessThanSize(last)
|
|
||||||
if (last.isGetSizeCall() && !loopHeader.headerInfo.isLastInclusive) {
|
if (last.isGetSizeCall() && !loopHeader.headerInfo.isLastInclusive) {
|
||||||
result = BoundsCheckAnalysisResult(true, (last.dispatchReceiver as? IrGetValue)?.symbol)
|
BoundsCheckAnalysisResult(true, (last.dispatchReceiver as? IrGetValue)?.symbol)
|
||||||
|
} else {
|
||||||
|
lessThanSize(last)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
BoundsCheckAnalysisResult(false, null)
|
||||||
}
|
}
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrExpression.isProgressionPropertyGetter(propertyName: String) =
|
private fun IrExpression.isProgressionPropertyGetter(propertyName: String) =
|
||||||
this is IrCall && symbol.owner.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR &&
|
this is IrCall && symbol.owner.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR &&
|
||||||
(symbol.signature as? IdSignature.AccessorSignature)?.propertySignature?.asPublic()?.shortName == propertyName &&
|
(symbol.signature as? IdSignature.AccessorSignature)?.propertySignature?.asPublic()?.shortName == propertyName &&
|
||||||
dispatchReceiver?.type?.getClass()?.symbol in context.ir.symbols.progressionClasses
|
dispatchReceiver?.type?.getClass()?.symbol in context.ir.symbols.progressionClasses
|
||||||
|
|
||||||
private fun analyzeLoopHeader(loopHeader: ForLoopHeader): BoundsCheckAnalysisResult {
|
private fun analyzeLoopHeader(loopHeader: ForLoopHeader): BoundsCheckAnalysisResult {
|
||||||
analysisResult = BoundsCheckAnalysisResult(false, null)
|
var analysisResult = BoundsCheckAnalysisResult(false, null)
|
||||||
when(loopHeader) {
|
when (loopHeader) {
|
||||||
is ProgressionLoopHeader ->
|
is ProgressionLoopHeader ->
|
||||||
when (loopHeader.headerInfo.direction) {
|
when (loopHeader.headerInfo.direction) {
|
||||||
ProgressionDirection.INCREASING -> {
|
ProgressionDirection.INCREASING -> {
|
||||||
@@ -112,6 +118,8 @@ class KonanBCEForLoopBodyTransformer : ForLoopBodyTransformer() {
|
|||||||
if (loopHeader.headerInfo.last is IrCall) {
|
if (loopHeader.headerInfo.last is IrCall) {
|
||||||
val functionCall = (loopHeader.headerInfo.last as IrCall)
|
val functionCall = (loopHeader.headerInfo.last as IrCall)
|
||||||
// Case of range with step - `for (i in 0..array.size - 1 step n)`.
|
// Case of range with step - `for (i in 0..array.size - 1 step n)`.
|
||||||
|
// There is a temporary variable `val nestedLast = array.size - 1`
|
||||||
|
// and `last` is computed as `getProgressionLastElement(0, nestedLast, n)`
|
||||||
if (loopHeader.headerInfo.progressionType.getProgressionLastElementFunction == functionCall.symbol) {
|
if (loopHeader.headerInfo.progressionType.getProgressionLastElementFunction == functionCall.symbol) {
|
||||||
val nestedLastVariable = functionCall.getValueArgument(1)
|
val nestedLastVariable = functionCall.getValueArgument(1)
|
||||||
if (nestedLastVariable is IrGetValue && nestedLastVariable.symbol.owner is IrVariable) {
|
if (nestedLastVariable is IrGetValue && nestedLastVariable.symbol.owner is IrVariable) {
|
||||||
@@ -130,6 +138,8 @@ class KonanBCEForLoopBodyTransformer : ForLoopBodyTransformer() {
|
|||||||
if (loopHeader.headerInfo.last is IrCall) {
|
if (loopHeader.headerInfo.last is IrCall) {
|
||||||
val functionCall = (loopHeader.headerInfo.last as IrCall)
|
val functionCall = (loopHeader.headerInfo.last as IrCall)
|
||||||
// Case of range with step - for (i in array.size - 1 downTo 0 step n).
|
// Case of range with step - for (i in array.size - 1 downTo 0 step n).
|
||||||
|
// There is a temporary variable `val nestedFirst = array.size - 1`
|
||||||
|
// and `last` is computed as `getProgressionLastElement(nestedFirst, 0, n)`
|
||||||
if (loopHeader.headerInfo.progressionType.getProgressionLastElementFunction == functionCall.symbol) {
|
if (loopHeader.headerInfo.progressionType.getProgressionLastElementFunction == functionCall.symbol) {
|
||||||
if (functionCall.getValueArgument(1)?.compareIntegerNumericConst { it >= valueToCompare } == true) {
|
if (functionCall.getValueArgument(1)?.compareIntegerNumericConst { it >= valueToCompare } == true) {
|
||||||
boundsAreSafe = true
|
boundsAreSafe = true
|
||||||
@@ -140,16 +150,13 @@ class KonanBCEForLoopBodyTransformer : ForLoopBodyTransformer() {
|
|||||||
}
|
}
|
||||||
if (!boundsAreSafe)
|
if (!boundsAreSafe)
|
||||||
return analysisResult
|
return analysisResult
|
||||||
when (loopHeader.headerInfo.first) {
|
when (val first = loopHeader.headerInfo.first) {
|
||||||
is IrCall -> {
|
is IrCall ->
|
||||||
val functionCall = (loopHeader.headerInfo.first as IrCall)
|
analysisResult = lessThanSize(first)
|
||||||
analysisResult = lessThanSize(functionCall)
|
is IrGetValue ->
|
||||||
}
|
((first.symbol.owner as? IrVariable)?.initializer as? IrCall)?.let {
|
||||||
is IrGetValue -> {
|
|
||||||
(((loopHeader.headerInfo.first as IrGetValue).symbol.owner as? IrVariable)?.initializer as? IrCall)?.let {
|
|
||||||
analysisResult = lessThanSize(it)
|
analysisResult = lessThanSize(it)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ProgressionDirection.UNKNOWN ->
|
ProgressionDirection.UNKNOWN ->
|
||||||
@@ -177,7 +184,7 @@ class KonanBCEForLoopBodyTransformer : ForLoopBodyTransformer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
is WithIndexLoopHeader ->
|
is WithIndexLoopHeader ->
|
||||||
when(loopHeader.nestedLoopHeader) {
|
when (loopHeader.nestedLoopHeader) {
|
||||||
is IndexedGetLoopHeader -> {
|
is IndexedGetLoopHeader -> {
|
||||||
analysisResult = BoundsCheckAnalysisResult(true,
|
analysisResult = BoundsCheckAnalysisResult(true,
|
||||||
((loopHeader.loopInitStatements[0] as? IrVariable)?.initializer as? IrGetValue)?.symbol)
|
((loopHeader.loopInitStatements[0] as? IrVariable)?.initializer as? IrGetValue)?.symbol)
|
||||||
@@ -190,14 +197,14 @@ class KonanBCEForLoopBodyTransformer : ForLoopBodyTransformer() {
|
|||||||
|
|
||||||
private fun replaceOperators(expression: IrCall, index: IrExpression, safeIndexVariables: List<IrVariable>): IrExpression {
|
private fun replaceOperators(expression: IrCall, index: IrExpression, safeIndexVariables: List<IrVariable>): IrExpression {
|
||||||
if (index is IrGetValue && index.symbol.owner in safeIndexVariables) {
|
if (index is IrGetValue && index.symbol.owner in safeIndexVariables) {
|
||||||
val operatorWithoutBC = expression.dispatchReceiver!!.type.getClass()!!.functions.singleOrNull {
|
val operatorWithoutBoundCheck = expression.dispatchReceiver!!.type.getClass()!!.functions.singleOrNull {
|
||||||
if (expression.symbol.owner.name == OperatorNameConventions.SET)
|
if (expression.symbol.owner.name == OperatorNameConventions.SET)
|
||||||
it.name == KonanNameConventions.setWithoutBC
|
it.name == KonanNameConventions.setWithoutBoundCheck
|
||||||
else
|
else
|
||||||
it.name == KonanNameConventions.getWithoutBC
|
it.name == KonanNameConventions.getWithoutBoundCheck
|
||||||
} ?: return expression
|
} ?: return expression
|
||||||
return IrCallImpl(
|
return IrCallImpl(
|
||||||
expression.startOffset, expression.endOffset, expression.type, operatorWithoutBC.symbol,
|
expression.startOffset, expression.endOffset, expression.type, operatorWithoutBoundCheck.symbol,
|
||||||
typeArgumentsCount = expression.typeArgumentsCount,
|
typeArgumentsCount = expression.typeArgumentsCount,
|
||||||
valueArgumentsCount = expression.valueArgumentsCount).apply {
|
valueArgumentsCount = expression.valueArgumentsCount).apply {
|
||||||
dispatchReceiver = expression.dispatchReceiver
|
dispatchReceiver = expression.dispatchReceiver
|
||||||
@@ -210,28 +217,28 @@ class KonanBCEForLoopBodyTransformer : ForLoopBodyTransformer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
if (!analysisResult.boundsAreSafe || analysisResult.arrayInLoop == null)
|
if (expression.symbol.owner.name != OperatorNameConventions.SET && expression.symbol.owner.name != OperatorNameConventions.GET)
|
||||||
return expression
|
return super.visitCall(expression)
|
||||||
if (expression.symbol.owner.name != OperatorNameConventions.SET && expression.symbol.owner.name != OperatorNameConventions.GET) {
|
|
||||||
expression.transformChildrenVoid()
|
|
||||||
return expression
|
|
||||||
}
|
|
||||||
if (expression.dispatchReceiver?.type?.isBasicArray() != true ||
|
if (expression.dispatchReceiver?.type?.isBasicArray() != true ||
|
||||||
(expression.dispatchReceiver as? IrGetValue)?.symbol != analysisResult.arrayInLoop)
|
(expression.dispatchReceiver as? IrGetValue)?.symbol != analysisResult.arrayInLoop)
|
||||||
return expression
|
return super.visitCall(expression)
|
||||||
// Analyze arguments of set/get operator.
|
// Analyze arguments of set/get operator.
|
||||||
val index = expression.getValueArgument(0)
|
val index = expression.getValueArgument(0)!!
|
||||||
return when(loopHeader) {
|
return when (loopHeader) {
|
||||||
is ProgressionLoopHeader -> with(loopHeader as ProgressionLoopHeader) {
|
is ProgressionLoopHeader -> with(loopHeader as ProgressionLoopHeader) {
|
||||||
replaceOperators(expression, index!!, listOf(mainLoopVariable, inductionVariable))
|
replaceOperators(expression, index, listOf(mainLoopVariable, inductionVariable))
|
||||||
}
|
}
|
||||||
|
|
||||||
is WithIndexLoopHeader -> with(loopHeader as WithIndexLoopHeader) {
|
is WithIndexLoopHeader -> with(loopHeader as WithIndexLoopHeader) {
|
||||||
when(nestedLoopHeader) {
|
when (nestedLoopHeader) {
|
||||||
is IndexedGetLoopHeader ->
|
is IndexedGetLoopHeader ->
|
||||||
replaceOperators(expression, index!!, listOfNotNull(indexVariable, loopVariableComponents[1]))
|
replaceOperators(expression, index, listOfNotNull(indexVariable, loopVariableComponents[1]))
|
||||||
is ProgressionLoopHeader ->
|
is ProgressionLoopHeader ->
|
||||||
replaceOperators(expression, index!!,
|
// Case of `for ((index, value) in (0..array.size - 1 step n).withIndex())`.
|
||||||
|
// Both `index` (progression size less than array size)
|
||||||
|
// and `value` (progression start and end element are inside bounds)
|
||||||
|
// are safe variables if use them in get/set operators.
|
||||||
|
replaceOperators(expression, index,
|
||||||
listOfNotNull(indexVariable, loopVariableComponents[1], loopVariableComponents[2])
|
listOfNotNull(indexVariable, loopVariableComponents[1], loopVariableComponents[2])
|
||||||
)
|
)
|
||||||
else -> expression
|
else -> expression
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
* 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.
|
* that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
package codegen.bce.arraysForLoops
|
||||||
|
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
@Test fun forEachIndexedTest() {
|
@Test fun forEachIndexedTest() {
|
||||||
@@ -159,7 +161,7 @@ import kotlin.test.*
|
|||||||
@Test fun forRangeToWithStep() {
|
@Test fun forRangeToWithStep() {
|
||||||
val array = Array(10) { 0L }
|
val array = Array(10) { 0L }
|
||||||
val array1 = Array(3) { 0L }
|
val array1 = Array(3) { 0L }
|
||||||
var j = 4
|
var j = 8
|
||||||
|
|
||||||
assertFailsWith<ArrayIndexOutOfBoundsException> {
|
assertFailsWith<ArrayIndexOutOfBoundsException> {
|
||||||
for (i in 0..array.size - 1 step 2) {
|
for (i in 0..array.size - 1 step 2) {
|
||||||
@@ -202,7 +204,7 @@ import kotlin.test.*
|
|||||||
@Test fun forUntilWithStep() {
|
@Test fun forUntilWithStep() {
|
||||||
val array = CharArray(10) { '0' }
|
val array = CharArray(10) { '0' }
|
||||||
val array1 = CharArray(3) { '0' }
|
val array1 = CharArray(3) { '0' }
|
||||||
var j = 4
|
var j = 8
|
||||||
|
|
||||||
assertFailsWith<ArrayIndexOutOfBoundsException> {
|
assertFailsWith<ArrayIndexOutOfBoundsException> {
|
||||||
for (i in 0 until array.size step 2) {
|
for (i in 0 until array.size step 2) {
|
||||||
@@ -213,7 +215,7 @@ import kotlin.test.*
|
|||||||
|
|
||||||
assertFailsWith<ArrayIndexOutOfBoundsException> {
|
assertFailsWith<ArrayIndexOutOfBoundsException> {
|
||||||
for (i in 0 until array.size step 2) {
|
for (i in 0 until array.size step 2) {
|
||||||
array[i + 1] = '6'
|
array[i + 3] = '6'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,7 +241,7 @@ import kotlin.test.*
|
|||||||
@Test fun forDownToWithStep() {
|
@Test fun forDownToWithStep() {
|
||||||
val array = Array(10) { 0L }
|
val array = Array(10) { 0L }
|
||||||
val array1 = Array(3) { 0L }
|
val array1 = Array(3) { 0L }
|
||||||
var j = 4
|
var j = 8
|
||||||
|
|
||||||
assertFailsWith<ArrayIndexOutOfBoundsException> {
|
assertFailsWith<ArrayIndexOutOfBoundsException> {
|
||||||
for (i in array.size - 1 downTo 0 step 2) {
|
for (i in array.size - 1 downTo 0 step 2) {
|
||||||
@@ -282,7 +284,7 @@ import kotlin.test.*
|
|||||||
@Test fun forIndiciesWithStep() {
|
@Test fun forIndiciesWithStep() {
|
||||||
val array = Array(10) { 0L }
|
val array = Array(10) { 0L }
|
||||||
val array1 = Array(3) { 0L }
|
val array1 = Array(3) { 0L }
|
||||||
var j = 4
|
var j = 8
|
||||||
|
|
||||||
assertFailsWith<ArrayIndexOutOfBoundsException> {
|
assertFailsWith<ArrayIndexOutOfBoundsException> {
|
||||||
for (i in array.indices step 2) {
|
for (i in array.indices step 2) {
|
||||||
@@ -307,7 +309,7 @@ import kotlin.test.*
|
|||||||
@Test fun forWithIndex() {
|
@Test fun forWithIndex() {
|
||||||
val array = Array(10) { 100 }
|
val array = Array(10) { 100 }
|
||||||
val array1 = Array(3) { 0 }
|
val array1 = Array(3) { 0 }
|
||||||
var j = 4
|
var j = 8
|
||||||
|
|
||||||
assertFailsWith<ArrayIndexOutOfBoundsException> {
|
assertFailsWith<ArrayIndexOutOfBoundsException> {
|
||||||
for ((index, value) in array.withIndex()) {
|
for ((index, value) in array.withIndex()) {
|
||||||
@@ -329,7 +331,7 @@ import kotlin.test.*
|
|||||||
}
|
}
|
||||||
|
|
||||||
assertFailsWith<ArrayIndexOutOfBoundsException> {
|
assertFailsWith<ArrayIndexOutOfBoundsException> {
|
||||||
for ((i, v) in (0..array.size + 1 step 2).withIndex()) {
|
for ((i, v) in (0..array.size + 30 step 2).withIndex()) {
|
||||||
array[i] = 6
|
array[i] = 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -344,7 +346,7 @@ import kotlin.test.*
|
|||||||
@Test fun forReversed() {
|
@Test fun forReversed() {
|
||||||
val array = Array(10) { 100 }
|
val array = Array(10) { 100 }
|
||||||
val array1 = Array(3) { 0 }
|
val array1 = Array(3) { 0 }
|
||||||
var j = 4
|
var j = 8
|
||||||
|
|
||||||
assertFailsWith<ArrayIndexOutOfBoundsException> {
|
assertFailsWith<ArrayIndexOutOfBoundsException> {
|
||||||
for (i in (0..array.size-1).reversed()) {
|
for (i in (0..array.size-1).reversed()) {
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ OBJ_GETTER(Kotlin_Array_get, KConstRef thiz, KInt index) {
|
|||||||
RETURN_OBJ(*Kotlin_Array_get_value(thiz, index));
|
RETURN_OBJ(*Kotlin_Array_get_value(thiz, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
OBJ_GETTER(Kotlin_Array_get_without_BC, KConstRef thiz, KInt index){
|
OBJ_GETTER(Kotlin_Array_get_without_BoundCheck, KConstRef thiz, KInt index){
|
||||||
RETURN_OBJ(*Kotlin_Array_get_value<false>(thiz, index));
|
RETURN_OBJ(*Kotlin_Array_get_value<false>(thiz, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ void Kotlin_Array_set(KRef thiz, KInt index, KConstRef value) {
|
|||||||
Kotlin_Array_set_value(thiz, index, value);
|
Kotlin_Array_set_value(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_Array_set_without_BC(KRef thiz, KInt index, KConstRef value) {
|
void Kotlin_Array_set_without_BoundCheck(KRef thiz, KInt index, KConstRef value) {
|
||||||
Kotlin_Array_set_value<false>(thiz, index, value);
|
Kotlin_Array_set_value<false>(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +199,7 @@ KByte Kotlin_ByteArray_get(KConstRef thiz, KInt index) {
|
|||||||
return Kotlin_ByteArray_get_value(thiz, index);
|
return Kotlin_ByteArray_get_value(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
KByte Kotlin_ByteArray_get_without_BC(KConstRef thiz, KInt index) {
|
KByte Kotlin_ByteArray_get_without_BoundCheck(KConstRef thiz, KInt index) {
|
||||||
return Kotlin_ByteArray_get_value<false>(thiz, index);
|
return Kotlin_ByteArray_get_value<false>(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@ void Kotlin_ByteArray_set(KRef thiz, KInt index, KByte value) {
|
|||||||
Kotlin_ByteArray_set_value(thiz, index, value);
|
Kotlin_ByteArray_set_value(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_ByteArray_set_without_BC(KRef thiz, KInt index, KByte value) {
|
void Kotlin_ByteArray_set_without_BoundCheck(KRef thiz, KInt index, KByte value) {
|
||||||
Kotlin_ByteArray_set_value<false>(thiz, index, value);
|
Kotlin_ByteArray_set_value<false>(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,7 +489,7 @@ KChar Kotlin_CharArray_get(KConstRef thiz, KInt index) {
|
|||||||
return PrimitiveArrayGet<KChar>(thiz, index);
|
return PrimitiveArrayGet<KChar>(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
KChar Kotlin_CharArray_get_without_BC(KConstRef thiz, KInt index) {
|
KChar Kotlin_CharArray_get_without_BoundCheck(KConstRef thiz, KInt index) {
|
||||||
return PrimitiveArrayGet<KChar, false>(thiz, index);
|
return PrimitiveArrayGet<KChar, false>(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,7 +497,7 @@ void Kotlin_CharArray_set(KRef thiz, KInt index, KChar value) {
|
|||||||
PrimitiveArraySet(thiz, index, value);
|
PrimitiveArraySet(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_CharArray_set_without_BC(KRef thiz, KInt index, KChar value) {
|
void Kotlin_CharArray_set_without_BoundCheck(KRef thiz, KInt index, KChar value) {
|
||||||
PrimitiveArraySet<KChar, false>(thiz, index, value);
|
PrimitiveArraySet<KChar, false>(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -524,7 +524,7 @@ KShort Kotlin_ShortArray_get(KConstRef thiz, KInt index) {
|
|||||||
return PrimitiveArrayGet<KShort>(thiz, index);
|
return PrimitiveArrayGet<KShort>(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
KShort Kotlin_ShortArray_get_without_BC(KConstRef thiz, KInt index) {
|
KShort Kotlin_ShortArray_get_without_BoundCheck(KConstRef thiz, KInt index) {
|
||||||
return PrimitiveArrayGet<KShort, false>(thiz, index);
|
return PrimitiveArrayGet<KShort, false>(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,7 +532,7 @@ void Kotlin_ShortArray_set(KRef thiz, KInt index, KShort value) {
|
|||||||
PrimitiveArraySet(thiz, index, value);
|
PrimitiveArraySet(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_ShortArray_set_without_BC(KRef thiz, KInt index, KShort value) {
|
void Kotlin_ShortArray_set_without_BoundCheck(KRef thiz, KInt index, KShort value) {
|
||||||
PrimitiveArraySet<KShort, false>(thiz, index, value);
|
PrimitiveArraySet<KShort, false>(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -545,7 +545,7 @@ KInt Kotlin_IntArray_get(KConstRef thiz, KInt index) {
|
|||||||
return PrimitiveArrayGet<KInt>(thiz, index);
|
return PrimitiveArrayGet<KInt>(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
KInt Kotlin_IntArray_get_without_BC(KConstRef thiz, KInt index) {
|
KInt Kotlin_IntArray_get_without_BoundCheck(KConstRef thiz, KInt index) {
|
||||||
return PrimitiveArrayGet<KInt, false>(thiz, index);
|
return PrimitiveArrayGet<KInt, false>(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,7 +553,7 @@ void Kotlin_IntArray_set(KRef thiz, KInt index, KInt value) {
|
|||||||
PrimitiveArraySet(thiz, index, value);
|
PrimitiveArraySet(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_IntArray_set_without_BC(KRef thiz, KInt index, KInt value) {
|
void Kotlin_IntArray_set_without_BoundCheck(KRef thiz, KInt index, KInt value) {
|
||||||
PrimitiveArraySet<KInt, false>(thiz, index, value);
|
PrimitiveArraySet<KInt, false>(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,7 +638,7 @@ KLong Kotlin_LongArray_get(KConstRef thiz, KInt index) {
|
|||||||
return PrimitiveArrayGet<KLong>(thiz, index);
|
return PrimitiveArrayGet<KLong>(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
KLong Kotlin_LongArray_get_without_BC(KConstRef thiz, KInt index) {
|
KLong Kotlin_LongArray_get_without_BoundCheck(KConstRef thiz, KInt index) {
|
||||||
return PrimitiveArrayGet<KLong, false>(thiz, index);
|
return PrimitiveArrayGet<KLong, false>(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,7 +646,7 @@ void Kotlin_LongArray_set(KRef thiz, KInt index, KLong value) {
|
|||||||
PrimitiveArraySet(thiz, index, value);
|
PrimitiveArraySet(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_LongArray_set_without_BC(KRef thiz, KInt index, KLong value) {
|
void Kotlin_LongArray_set_without_BoundCheck(KRef thiz, KInt index, KLong value) {
|
||||||
PrimitiveArraySet<KLong, false>(thiz, index, value);
|
PrimitiveArraySet<KLong, false>(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -659,7 +659,7 @@ KFloat Kotlin_FloatArray_get(KConstRef thiz, KInt index) {
|
|||||||
return PrimitiveArrayGet<KFloat>(thiz, index);
|
return PrimitiveArrayGet<KFloat>(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
KFloat Kotlin_FloatArray_get_without_BC(KConstRef thiz, KInt index) {
|
KFloat Kotlin_FloatArray_get_without_BoundCheck(KConstRef thiz, KInt index) {
|
||||||
return PrimitiveArrayGet<KFloat, false>(thiz, index);
|
return PrimitiveArrayGet<KFloat, false>(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -667,7 +667,7 @@ void Kotlin_FloatArray_set(KRef thiz, KInt index, KFloat value) {
|
|||||||
PrimitiveArraySet(thiz, index, value);
|
PrimitiveArraySet(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_FloatArray_set_without_BC(KRef thiz, KInt index, KFloat value) {
|
void Kotlin_FloatArray_set_without_BoundCheck(KRef thiz, KInt index, KFloat value) {
|
||||||
PrimitiveArraySet<KFloat, false>(thiz, index, value);
|
PrimitiveArraySet<KFloat, false>(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -680,7 +680,7 @@ KDouble Kotlin_DoubleArray_get(KConstRef thiz, KInt index) {
|
|||||||
return PrimitiveArrayGet<KDouble>(thiz, index);
|
return PrimitiveArrayGet<KDouble>(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
KDouble Kotlin_DoubleArray_get_without_BC(KConstRef thiz, KInt index) {
|
KDouble Kotlin_DoubleArray_get_without_BoundCheck(KConstRef thiz, KInt index) {
|
||||||
return PrimitiveArrayGet<KDouble, false>(thiz, index);
|
return PrimitiveArrayGet<KDouble, false>(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -688,7 +688,7 @@ void Kotlin_DoubleArray_set(KRef thiz, KInt index, KDouble value) {
|
|||||||
PrimitiveArraySet(thiz, index, value);
|
PrimitiveArraySet(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_DoubleArray_set_without_BC(KRef thiz, KInt index, KDouble value) {
|
void Kotlin_DoubleArray_set_without_BoundCheck(KRef thiz, KInt index, KDouble value) {
|
||||||
PrimitiveArraySet<KDouble, false>(thiz, index, value);
|
PrimitiveArraySet<KDouble, false>(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -701,7 +701,7 @@ KBoolean Kotlin_BooleanArray_get(KConstRef thiz, KInt index) {
|
|||||||
return PrimitiveArrayGet<KBoolean>(thiz, index);
|
return PrimitiveArrayGet<KBoolean>(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
KBoolean Kotlin_BooleanArray_get_without_BC(KConstRef thiz, KInt index) {
|
KBoolean Kotlin_BooleanArray_get_without_BoundCheck(KConstRef thiz, KInt index) {
|
||||||
return PrimitiveArrayGet<KBoolean, false>(thiz, index);
|
return PrimitiveArrayGet<KBoolean, false>(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,7 +709,7 @@ void Kotlin_BooleanArray_set(KRef thiz, KInt index, KBoolean value) {
|
|||||||
PrimitiveArraySet(thiz, index, value);
|
PrimitiveArraySet(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_BooleanArray_set_without_BC(KRef thiz, KInt index, KBoolean value) {
|
void Kotlin_BooleanArray_set_without_BoundCheck(KRef thiz, KInt index, KBoolean value) {
|
||||||
PrimitiveArraySet<KBoolean, false>(thiz, index, value);
|
PrimitiveArraySet<KBoolean, false>(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -722,7 +722,7 @@ KNativePtr Kotlin_NativePtrArray_get(KConstRef thiz, KInt index) {
|
|||||||
return PrimitiveArrayGet<KNativePtr>(thiz, index);
|
return PrimitiveArrayGet<KNativePtr>(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
KNativePtr Kotlin_NativePtrArray_get_without_BC(KConstRef thiz, KInt index) {
|
KNativePtr Kotlin_NativePtrArray_get_without_BoundCheck(KConstRef thiz, KInt index) {
|
||||||
return PrimitiveArrayGet<KNativePtr, false>(thiz, index);
|
return PrimitiveArrayGet<KNativePtr, false>(thiz, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -730,7 +730,7 @@ void Kotlin_NativePtrArray_set(KRef thiz, KInt index, KNativePtr value) {
|
|||||||
PrimitiveArraySet(thiz, index, value);
|
PrimitiveArraySet(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kotlin_NativePtrArray_set_without_BC(KRef thiz, KInt index, KNativePtr value) {
|
void Kotlin_NativePtrArray_set_without_BoundCheck(KRef thiz, KInt index, KNativePtr value) {
|
||||||
PrimitiveArraySet<KNativePtr, false>(thiz, index, value);
|
PrimitiveArraySet<KNativePtr, false>(thiz, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user