Allow stateless and constant objects compile-time init . (#3645)
Allow stateless and constant objects compile-time init.
This commit is contained in:
+1
@@ -26,6 +26,7 @@ object KonanFqNames {
|
||||
val sharedImmutable = FqName("kotlin.native.concurrent.SharedImmutable")
|
||||
val frozen = FqName("kotlin.native.internal.Frozen")
|
||||
val leakDetectorCandidate = FqName("kotlin.native.internal.LeakDetectorCandidate")
|
||||
val canBePrecreated = FqName("kotlin.native.internal.CanBePrecreated")
|
||||
val typedIntrinsic = FqName("kotlin.native.internal.TypedIntrinsic")
|
||||
val objCMethod = FqName("kotlinx.cinterop.ObjCMethod")
|
||||
}
|
||||
|
||||
-1
@@ -143,7 +143,6 @@ internal val IrClass.objectInstanceShadowFieldSymbolName: String
|
||||
assert (this.isExported())
|
||||
assert (this.kind.isSingleton)
|
||||
assert (!this.isUnit())
|
||||
assert (this.objectIsShared)
|
||||
|
||||
return "kshadowobjref:$fqNameForIrSerialization"
|
||||
}
|
||||
|
||||
+38
-10
@@ -18,6 +18,28 @@ import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride
|
||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
||||
import org.jetbrains.kotlin.descriptors.konan.CompiledKlibModuleOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrGetObjectValue
|
||||
import org.jetbrains.kotlin.ir.expressions.IrReturn
|
||||
|
||||
private fun IrConstructor.isAnyConstructorDelegation(context: Context): Boolean {
|
||||
val statements = this.body?.statements ?: return false
|
||||
if (statements.size != 2) return false
|
||||
val lastStatement = statements[1]
|
||||
if (lastStatement !is IrReturn ||
|
||||
(lastStatement.value as? IrGetObjectValue)?.symbol != context.irBuiltIns.unitClass) return false
|
||||
val constructorCall = statements[0] as? IrDelegatingConstructorCall ?: return false
|
||||
val constructor = constructorCall.symbol.owner as? IrConstructor ?: return false
|
||||
return constructor.constructedClass.isAny()
|
||||
}
|
||||
|
||||
// TODO: shall we memoize that property?
|
||||
internal fun IrClass.hasConstStateAndNoSideEffects(context: Context): Boolean {
|
||||
if (!context.shouldOptimize()) return false
|
||||
if (this.hasAnnotation(KonanFqNames.canBePrecreated)) return true
|
||||
val fields = context.getLayoutBuilder(this).fields
|
||||
return fields.isEmpty() && this.constructors.all { it.isAnyConstructorDelegation(context) }
|
||||
}
|
||||
|
||||
internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
|
||||
@@ -42,7 +64,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
fun functionEntryPointAddress(function: IrFunction) = function.entryPointAddress.llvm
|
||||
fun functionHash(function: IrFunction): LLVMValueRef = function.functionName.localHash.llvm
|
||||
|
||||
fun getObjectInstanceStorage(irClass: IrClass, shared: Boolean): LLVMValueRef {
|
||||
fun getObjectInstanceStorage(irClass: IrClass, kind: ObjectStorageKind): LLVMValueRef {
|
||||
assert (!irClass.isUnit())
|
||||
val llvmGlobal = if (!isExternal(irClass)) {
|
||||
context.llvmDeclarations.forSingleton(irClass).instanceFieldRef
|
||||
@@ -52,19 +74,21 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
|
||||
irClass.objectInstanceFieldSymbolName,
|
||||
llvmType,
|
||||
origin = irClass.llvmSymbolOrigin,
|
||||
threadLocal = !shared
|
||||
threadLocal = kind == ObjectStorageKind.THREAD_LOCAL
|
||||
)
|
||||
}
|
||||
if (shared)
|
||||
context.llvm.sharedObjects += llvmGlobal
|
||||
else
|
||||
context.llvm.objects += llvmGlobal
|
||||
when (kind) {
|
||||
ObjectStorageKind.SHARED -> context.llvm.sharedObjects += llvmGlobal
|
||||
ObjectStorageKind.THREAD_LOCAL -> context.llvm.objects += llvmGlobal
|
||||
ObjectStorageKind.PERMANENT -> { /* Do nothing, no need to free such an instance. */ }
|
||||
}
|
||||
|
||||
return llvmGlobal
|
||||
}
|
||||
|
||||
fun getObjectInstanceShadowStorage(irClass: IrClass): LLVMValueRef {
|
||||
assert (!irClass.isUnit())
|
||||
assert (irClass.objectIsShared)
|
||||
assert (irClass.storageKind(context) == ObjectStorageKind.SHARED)
|
||||
val llvmGlobal = if (!isExternal(irClass)) {
|
||||
context.llvmDeclarations.forSingleton(irClass).instanceShadowFieldRef!!
|
||||
} else {
|
||||
@@ -893,6 +917,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
startLocationInfo: LocationInfo?,
|
||||
endLocationInfo: LocationInfo? = null
|
||||
): LLVMValueRef {
|
||||
// TODO: could be processed the same way as other stateless objects.
|
||||
if (irClass.isUnit()) {
|
||||
return codegen.theUnitInstanceRef.llvm
|
||||
}
|
||||
@@ -910,9 +935,12 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
)
|
||||
}
|
||||
}
|
||||
val storageKind = irClass.storageKind(context)
|
||||
if (storageKind == ObjectStorageKind.PERMANENT) {
|
||||
return loadSlot(codegen.getObjectInstanceStorage(irClass, storageKind), false)
|
||||
}
|
||||
|
||||
val shared = irClass.objectIsShared && context.config.threadsAreAllowed
|
||||
val objectPtr = codegen.getObjectInstanceStorage(irClass, shared)
|
||||
val objectPtr = codegen.getObjectInstanceStorage(irClass, storageKind)
|
||||
val bbInit = basicBlock("label_init", startLocationInfo, endLocationInfo)
|
||||
val bbExit = basicBlock("label_continue", startLocationInfo, endLocationInfo)
|
||||
val objectVal = loadSlot(objectPtr, false)
|
||||
@@ -925,7 +953,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
||||
val defaultConstructor = irClass.constructors.single { it.valueParameters.size == 0 }
|
||||
val ctor = codegen.llvmFunction(defaultConstructor)
|
||||
val (initFunction, args) =
|
||||
if (shared) {
|
||||
if (storageKind == ObjectStorageKind.SHARED && context.config.threadsAreAllowed) {
|
||||
val shadowObjectPtr = codegen.getObjectInstanceShadowStorage(irClass)
|
||||
context.llvm.initSharedInstanceFunction to listOf(objectPtr, shadowObjectPtr, typeInfo, ctor)
|
||||
} else {
|
||||
|
||||
+41
-19
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.coverage.LLVMCoverageInstrumentation
|
||||
import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
@@ -33,33 +32,43 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
|
||||
internal enum class FieldStorage {
|
||||
internal enum class FieldStorageKind {
|
||||
MAIN_THREAD,
|
||||
SHARED,
|
||||
THREAD_LOCAL
|
||||
}
|
||||
|
||||
// TODO: maybe unannotated singleton objects shall be accessed from main thread only as well?
|
||||
val IrClass.objectIsShared get() =
|
||||
!annotations.hasAnnotation(KonanFqNames.threadLocal)
|
||||
internal enum class ObjectStorageKind {
|
||||
PERMANENT,
|
||||
THREAD_LOCAL,
|
||||
SHARED
|
||||
}
|
||||
|
||||
internal val IrField.storageClass: FieldStorage get() {
|
||||
// TODO: maybe unannotated singleton objects shall be accessed from main thread only as well?
|
||||
internal val IrField.storageKind: FieldStorageKind get() {
|
||||
// TODO: Is this correct?
|
||||
val annotations = correspondingPropertySymbol?.owner?.annotations ?: annotations
|
||||
return when {
|
||||
annotations.hasAnnotation(KonanFqNames.threadLocal) -> FieldStorage.THREAD_LOCAL
|
||||
!isFinal -> FieldStorage.MAIN_THREAD
|
||||
annotations.hasAnnotation(KonanFqNames.sharedImmutable) -> FieldStorage.SHARED
|
||||
annotations.hasAnnotation(KonanFqNames.threadLocal) -> FieldStorageKind.THREAD_LOCAL
|
||||
!isFinal -> FieldStorageKind.MAIN_THREAD
|
||||
annotations.hasAnnotation(KonanFqNames.sharedImmutable) -> FieldStorageKind.SHARED
|
||||
// TODO: simplify, once IR types are fully there.
|
||||
(type.classifierOrNull?.owner as? IrAnnotationContainer)
|
||||
?.annotations?.hasAnnotation(KonanFqNames.frozen) == true -> FieldStorage.SHARED
|
||||
else -> FieldStorage.MAIN_THREAD
|
||||
?.annotations?.hasAnnotation(KonanFqNames.frozen) == true -> FieldStorageKind.SHARED
|
||||
else -> FieldStorageKind.MAIN_THREAD
|
||||
}
|
||||
}
|
||||
|
||||
internal fun IrClass.storageKind(context: Context): ObjectStorageKind = when {
|
||||
this.annotations.hasAnnotation(KonanFqNames.threadLocal) &&
|
||||
context.config.threadsAreAllowed -> ObjectStorageKind.THREAD_LOCAL
|
||||
this.hasConstStateAndNoSideEffects(context) -> ObjectStorageKind.PERMANENT
|
||||
else -> ObjectStorageKind.SHARED
|
||||
}
|
||||
|
||||
val IrField.isMainOnlyNonPrimitive get() = when {
|
||||
descriptor.type.computePrimitiveBinaryTypeOrNull() != null -> false
|
||||
else -> storageClass == FieldStorage.MAIN_THREAD
|
||||
else -> storageKind == FieldStorageKind.MAIN_THREAD
|
||||
}
|
||||
|
||||
internal fun verifyModule(llvmModule: LLVMModuleRef, current: String = "") {
|
||||
@@ -384,10 +393,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
context.llvm.fileInitializers
|
||||
.forEach {
|
||||
if (it.initializer?.expression !is IrConst<*>?) {
|
||||
if (it.storageClass != FieldStorage.THREAD_LOCAL) {
|
||||
if (it.storageKind != FieldStorageKind.THREAD_LOCAL) {
|
||||
val initialization = evaluateExpression(it.initializer!!.expression)
|
||||
val address = context.llvmDeclarations.forStaticField(it).storage
|
||||
if (it.storageClass == FieldStorage.SHARED)
|
||||
if (it.storageKind == FieldStorageKind.SHARED)
|
||||
freeze(initialization, currentCodeContext.exceptionHandler)
|
||||
storeAny(initialization, address, false)
|
||||
}
|
||||
@@ -400,7 +409,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
context.llvm.fileInitializers
|
||||
.forEach {
|
||||
if (it.initializer?.expression !is IrConst<*>?) {
|
||||
if (it.storageClass == FieldStorage.THREAD_LOCAL) {
|
||||
if (it.storageKind == FieldStorageKind.THREAD_LOCAL) {
|
||||
val initialization = evaluateExpression(it.initializer!!.expression)
|
||||
val address = context.llvmDeclarations.forStaticField(it).storage
|
||||
storeAny(initialization, address, false)
|
||||
@@ -413,7 +422,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
appendingTo(bbLocalDeinit) {
|
||||
context.llvm.fileInitializers.forEach {
|
||||
// Only if a subject for memory management.
|
||||
if (it.type.binaryTypeIsReference() && it.storageClass == FieldStorage.THREAD_LOCAL) {
|
||||
if (it.type.binaryTypeIsReference() && it.storageKind == FieldStorageKind.THREAD_LOCAL) {
|
||||
val address = context.llvmDeclarations.forStaticField(it).storage
|
||||
storeHeapRef(codegen.kNullObjHeaderPtr, address)
|
||||
}
|
||||
@@ -426,7 +435,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
context.llvm.fileInitializers
|
||||
// Only if a subject for memory management.
|
||||
.forEach {
|
||||
if (it.type.binaryTypeIsReference() && it.storageClass != FieldStorage.THREAD_LOCAL) {
|
||||
if (it.type.binaryTypeIsReference() && it.storageKind != FieldStorageKind.THREAD_LOCAL) {
|
||||
val address = context.llvmDeclarations.forStaticField(it).storage
|
||||
storeHeapRef(codegen.kNullObjHeaderPtr, address)
|
||||
}
|
||||
@@ -738,9 +747,22 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
it.acceptVoid(this)
|
||||
}
|
||||
}
|
||||
|
||||
if (declaration.kind.isSingleton && !declaration.isUnit()) {
|
||||
val value = context.llvmDeclarations.forSingleton(declaration).instanceFieldRef
|
||||
LLVMSetInitializer(value, if (declaration.storageKind(context) == ObjectStorageKind.PERMANENT)
|
||||
context.llvm.staticData.createConstKotlinObject(declaration,
|
||||
*computeFields(declaration)).llvm else codegen.kNullObjHeaderPtr)
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
private fun computeFields(declaration: IrClass): Array<ConstValue> {
|
||||
val fields = context.getLayoutBuilder(declaration).fields
|
||||
return Array(fields.size) { index ->
|
||||
val initializer = fields[index].initializer!!.expression as IrConst<*>
|
||||
constValue(evaluateConst(initializer))
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitProperty(declaration: IrProperty) {
|
||||
declaration.getter?.acceptVoid(this)
|
||||
@@ -1527,7 +1549,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
val globalValue = context.llvmDeclarations.forStaticField(value.symbol.owner).storage
|
||||
if (context.config.threadsAreAllowed && value.symbol.owner.isMainOnlyNonPrimitive)
|
||||
functionGenerationContext.checkMainThread(currentCodeContext.exceptionHandler)
|
||||
if (value.symbol.owner.storageClass == FieldStorage.SHARED)
|
||||
if (value.symbol.owner.storageKind == FieldStorageKind.SHARED)
|
||||
functionGenerationContext.freeze(valueToAssign, currentCodeContext.exceptionHandler)
|
||||
functionGenerationContext.storeAny(valueToAssign, globalValue, false)
|
||||
}
|
||||
|
||||
+2
-4
@@ -273,12 +273,10 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
} else {
|
||||
"kobjref:" + qualifyInternalName(irClass)
|
||||
}
|
||||
val threadLocal = !(irClass.objectIsShared && context.config.threadsAreAllowed)
|
||||
val threadLocal = irClass.storageKind(context) == ObjectStorageKind.THREAD_LOCAL
|
||||
val instanceFieldRef = addGlobal(
|
||||
symbolName, getLLVMType(irClass.defaultType), isExported = isExported, threadLocal = threadLocal)
|
||||
|
||||
LLVMSetInitializer(instanceFieldRef, kNullObjHeaderPtr)
|
||||
|
||||
val instanceShadowFieldRef =
|
||||
if (threadLocal) null
|
||||
else {
|
||||
@@ -329,7 +327,7 @@ private class DeclarationsGeneratorVisitor(override val context: Context) :
|
||||
val name = "kvar:" + qualifyInternalName(declaration)
|
||||
val storage = addGlobal(
|
||||
name, getLLVMType(declaration.type), isExported = false,
|
||||
threadLocal = declaration.storageClass == FieldStorage.THREAD_LOCAL)
|
||||
threadLocal = declaration.storageKind == FieldStorageKind.THREAD_LOCAL)
|
||||
|
||||
this.staticFields[declaration] = StaticFieldLlvmDeclarations(storage)
|
||||
}
|
||||
|
||||
+13
-2
@@ -22,6 +22,8 @@ import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.isPrimitiveType
|
||||
import org.jetbrains.kotlin.ir.types.isString
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
@@ -64,6 +66,7 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
val initializer = declaration.initializer ?: return declaration
|
||||
val startOffset = initializer.startOffset
|
||||
val endOffset = initializer.endOffset
|
||||
val initExpression = initializer.expression
|
||||
initializers.add(IrBlockImpl(startOffset, endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER,
|
||||
@@ -73,11 +76,19 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
startOffset, endOffset,
|
||||
irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol
|
||||
),
|
||||
initializer.expression,
|
||||
initExpression,
|
||||
context.irBuiltIns.unitType,
|
||||
STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER)))
|
||||
)
|
||||
declaration.initializer = null
|
||||
|
||||
// We shall keep initializer for constants for compile-time instantiation.
|
||||
declaration.initializer =
|
||||
if (initExpression is IrConst<*> &&
|
||||
(initExpression.type.isPrimitiveType() || initExpression.type.isString())) {
|
||||
IrExpressionBodyImpl(initExpression.copy())
|
||||
} else {
|
||||
null
|
||||
}
|
||||
return declaration
|
||||
}
|
||||
})
|
||||
|
||||
+8
-7
@@ -225,14 +225,15 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
}
|
||||
|
||||
override fun visitField(declaration: IrField) {
|
||||
declaration.initializer?.let {
|
||||
DEBUG_OUTPUT(0) {
|
||||
println("Analysing global field ${declaration.descriptor}")
|
||||
println("IR: ${ir2stringWhole(declaration)}")
|
||||
if (declaration.parent is IrFile)
|
||||
declaration.initializer?.let {
|
||||
DEBUG_OUTPUT(0) {
|
||||
println("Analysing global field ${declaration.descriptor}")
|
||||
println("IR: ${ir2stringWhole(declaration)}")
|
||||
}
|
||||
analyze(declaration, IrSetFieldImpl(it.startOffset, it.endOffset, declaration.symbol, null,
|
||||
it.expression, context.irBuiltIns.unitType))
|
||||
}
|
||||
analyze(declaration, IrSetFieldImpl(it.startOffset, it.endOffset, declaration.symbol, null,
|
||||
it.expression, context.irBuiltIns.unitType))
|
||||
}
|
||||
}
|
||||
|
||||
private fun analyze(declaration: IrDeclaration, body: IrElement?) {
|
||||
|
||||
+5
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.optimizations
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.ir2stringWhole
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isAbstract
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.target
|
||||
@@ -487,7 +488,10 @@ internal object DataFlowIR {
|
||||
}
|
||||
|
||||
override fun visitField(declaration: IrField) {
|
||||
declaration.initializer?.let { mapFunction(declaration) }
|
||||
if (declaration.parent is IrFile)
|
||||
declaration.initializer?.let {
|
||||
mapFunction(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
|
||||
@@ -16,7 +16,7 @@ fun foo(x: Any, y: Any) {
|
||||
y.use()
|
||||
}
|
||||
|
||||
@Test fun runTest() {
|
||||
@Test fun runTest1() {
|
||||
var x = Integer(0)
|
||||
|
||||
for (i in 0..1) {
|
||||
@@ -31,4 +31,32 @@ fun foo(x: Any, y: Any) {
|
||||
|
||||
fun Any?.use() {
|
||||
var x = this
|
||||
}
|
||||
|
||||
@kotlin.native.internal.CanBePrecreated
|
||||
object CompileTime {
|
||||
|
||||
const val int = Int.MIN_VALUE
|
||||
const val byte = Byte.MIN_VALUE
|
||||
const val short = Short.MIN_VALUE
|
||||
const val long = Long.MIN_VALUE
|
||||
const val boolean = true
|
||||
const val float = 1.0f
|
||||
const val double = 1.0
|
||||
const val char = Char.MIN_VALUE
|
||||
}
|
||||
|
||||
class AClass {
|
||||
companion object {}
|
||||
}
|
||||
|
||||
@Test fun runTest2() {
|
||||
assertEquals(Int.MIN_VALUE, CompileTime.int)
|
||||
assertEquals(Byte.MIN_VALUE, CompileTime.byte)
|
||||
assertEquals(Short.MIN_VALUE, CompileTime.short)
|
||||
assertEquals(Long.MIN_VALUE, CompileTime.long)
|
||||
assertEquals(true, CompileTime.boolean)
|
||||
assertEquals(1.0f, CompileTime.float)
|
||||
assertEquals(1.0, CompileTime.double)
|
||||
assertEquals(Char.MIN_VALUE, CompileTime.char)
|
||||
}
|
||||
@@ -65,6 +65,7 @@ public class Char private constructor() : Comparable<Char> {
|
||||
@TypedIntrinsic(IntrinsicType.UNSIGNED_TO_FLOAT)
|
||||
external public fun toDouble(): Double
|
||||
|
||||
@kotlin.native.internal.CanBePrecreated
|
||||
companion object {
|
||||
/**
|
||||
* The minimum value of a character code unit.
|
||||
|
||||
@@ -7,15 +7,16 @@
|
||||
|
||||
package kotlin
|
||||
|
||||
import kotlin.native.internal.CanBePrecreated
|
||||
import kotlin.native.internal.IntrinsicType
|
||||
import kotlin.native.internal.NumberConverter
|
||||
import kotlin.native.internal.TypedIntrinsic
|
||||
import kotlin.native.internal.IntrinsicType
|
||||
|
||||
/**
|
||||
* Represents a 8-bit signed integer.
|
||||
*/
|
||||
public final class Byte private constructor() : Number(), Comparable<Byte> {
|
||||
|
||||
@CanBePrecreated
|
||||
companion object {
|
||||
/**
|
||||
* A constant holding the minimum value an instance of Byte can have.
|
||||
@@ -284,6 +285,7 @@ public final class Byte private constructor() : Number(), Comparable<Byte> {
|
||||
* Represents a 16-bit signed integer.
|
||||
*/
|
||||
public final class Short private constructor() : Number(), Comparable<Short> {
|
||||
@CanBePrecreated
|
||||
companion object {
|
||||
/**
|
||||
* A constant holding the minimum value an instance of Short can have.
|
||||
@@ -551,6 +553,7 @@ public final class Short private constructor() : Number(), Comparable<Short> {
|
||||
* Represents a 32-bit signed integer.
|
||||
*/
|
||||
public final class Int private constructor() : Number(), Comparable<Int> {
|
||||
@CanBePrecreated
|
||||
companion object {
|
||||
/**
|
||||
* A constant holding the minimum value an instance of Int can have.
|
||||
@@ -844,6 +847,7 @@ public final class Int private constructor() : Number(), Comparable<Int> {
|
||||
* Represents a 64-bit signed integer.
|
||||
*/
|
||||
public final class Long private constructor() : Number(), Comparable<Long> {
|
||||
@CanBePrecreated
|
||||
companion object {
|
||||
/**
|
||||
* A constant holding the minimum value an instance of Long can have.
|
||||
|
||||
@@ -505,8 +505,9 @@ actual class HashMap<K, V> private constructor(
|
||||
internal fun valuesIterator() = ValuesItr(this)
|
||||
internal fun entriesIterator() = EntriesItr(this)
|
||||
|
||||
@kotlin.native.internal.CanBePrecreated
|
||||
private companion object {
|
||||
const val MAGIC = 2654435769L.toInt() // golden ratio
|
||||
const val MAGIC = -1640531527 // 2654435769L.toInt(), golden ratio
|
||||
const val INITIAL_CAPACITY = 8
|
||||
const val INITIAL_MAX_PROBE_DISTANCE = 2
|
||||
const val TOMBSTONE = -1
|
||||
|
||||
@@ -13,6 +13,7 @@ package kotlin.native
|
||||
*/
|
||||
public class BitSet(size: Int = ELEMENT_SIZE) {
|
||||
|
||||
@kotlin.native.internal.CanBePrecreated
|
||||
companion object {
|
||||
// Default size of one element in the array used to store bits.
|
||||
private const val ELEMENT_SIZE = 64
|
||||
|
||||
@@ -121,4 +121,13 @@ annotation class Independent
|
||||
* Marks a class whose instances to be added to the list of leak detector candidates.
|
||||
*/
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@PublishedApi internal annotation class LeakDetectorCandidate
|
||||
@PublishedApi internal annotation class LeakDetectorCandidate
|
||||
|
||||
/**
|
||||
* Indicates that given top level signleton object can be created in compile time and thus
|
||||
* members access doesn't need to use an init barrier and allow better optimizations for
|
||||
* field access, such as constant folding.
|
||||
*/
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
public annotation class CanBePrecreated
|
||||
|
||||
@@ -12,6 +12,7 @@ external fun getNativeNullPtr(): NativePtr
|
||||
|
||||
class NativePtr @PublishedApi internal constructor(private val value: NonNullNativePtr?) {
|
||||
companion object {
|
||||
// TODO: make it properly precreated, maybe use an intrinsic for that.
|
||||
val NULL = getNativeNullPtr()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user