Return objects to slot. (#161)

This commit is contained in:
Nikolay Igotti
2016-12-26 18:31:50 +02:00
committed by GitHub
parent 2515d1fdaa
commit f49c6133f3
15 changed files with 266 additions and 172 deletions
@@ -17,6 +17,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
// TODO: remove, to make CodeGenerator descriptor-agnostic. // TODO: remove, to make CodeGenerator descriptor-agnostic.
var constructedClass: ClassDescriptor? = null var constructedClass: ClassDescriptor? = null
val vars = VariableManager(this) val vars = VariableManager(this)
var returnSlot: LLVMValueRef? = null
fun prologue(descriptor: FunctionDescriptor) { fun prologue(descriptor: FunctionDescriptor) {
prologue(llvmFunction(descriptor), prologue(llvmFunction(descriptor),
@@ -28,8 +29,11 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
fun prologue(function:LLVMValueRef, returnType:LLVMTypeRef) { fun prologue(function:LLVMValueRef, returnType:LLVMTypeRef) {
assert(returns.size == 0) assert(returns.size == 0)
assert(this.function != function) assert(this.function != function)
if (isObjectType(returnType)) {
this.returnSlot = LLVMGetParam(function, numParameters(function.type) - 1)
}
this.function = function this.function = function
this.returnType = returnType this.returnType = returnType
this.constructedClass = null this.constructedClass = null
@@ -48,11 +52,15 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
when { when {
returnType == voidType -> { returnType == voidType -> {
vars.releaseVars() vars.releaseVars()
assert(returnSlot == null)
LLVMBuildRetVoid(builder) LLVMBuildRetVoid(builder)
} }
returns.size > 0 -> { returns.size > 0 -> {
val returnPhi = phi(returnType!!) val returnPhi = phi(returnType!!)
addPhiIncoming(returnPhi, *returns.toList().toTypedArray()) addPhiIncoming(returnPhi, *returns.toList().toTypedArray())
if (returnSlot != null) {
updateLocalRef(returnPhi, returnSlot!!)
}
vars.releaseVars() vars.releaseVars()
LLVMBuildRet(builder, returnPhi) LLVMBuildRet(builder, returnPhi)
} }
@@ -63,6 +71,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
returns.clear() returns.clear()
vars.clear() vars.clear()
returnSlot = null
} }
private var prologueBb: LLVMBasicBlockRef? = null private var prologueBb: LLVMBasicBlockRef? = null
@@ -103,6 +112,11 @@ internal class CodeGenerator(override val context: Context) : ContextUtils {
fun load(value: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildLoad(builder, value, name)!! fun load(value: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildLoad(builder, value, name)!!
fun store(value: LLVMValueRef, ptr: LLVMValueRef): LLVMValueRef = LLVMBuildStore(builder, value, ptr)!! fun store(value: LLVMValueRef, ptr: LLVMValueRef): LLVMValueRef = LLVMBuildStore(builder, value, ptr)!!
fun updateLocalRef(value: LLVMValueRef, address: LLVMValueRef, ignoreOld: Boolean = false) {
call(if (ignoreOld) context.llvm.setLocalRefFunction else context.llvm.updateLocalRefFunction,
listOf(address, value))
}
fun isConst(value: LLVMValueRef): Boolean = (LLVMIsConstant(value) == 1) fun isConst(value: LLVMValueRef): Boolean = (LLVMIsConstant(value) == 1)
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
@@ -221,6 +221,8 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
val allocInstanceFunction = importRtFunction("AllocInstance") val allocInstanceFunction = importRtFunction("AllocInstance")
val initInstanceFunction = importRtFunction("InitInstance") val initInstanceFunction = importRtFunction("InitInstance")
val allocArrayFunction = importRtFunction("AllocArrayInstance") val allocArrayFunction = importRtFunction("AllocArrayInstance")
val setLocalRefFunction = importRtFunction("SetLocalRef")
val updateLocalRefFunction = importRtFunction("UpdateLocalRef")
val setArrayFunction = importRtFunction("Kotlin_Array_set") val setArrayFunction = importRtFunction("Kotlin_Array_set")
val copyImplArrayFunction = importRtFunction("Kotlin_Array_copyImpl") val copyImplArrayFunction = importRtFunction("Kotlin_Array_copyImpl")
val lookupFieldOffset = importRtFunction("LookupFieldOffset") val lookupFieldOffset = importRtFunction("LookupFieldOffset")
@@ -429,10 +429,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
} }
}) })
} }
codegen.ret(thisPtr)
} }
codegen.ret(null)
codegen.epilogue() codegen.epilogue()
context.log("visitConstructor : ${ir2string(constructorDeclaration)}") context.log("visitConstructor : ${ir2string(constructorDeclaration)}")
} }
@@ -553,11 +552,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
} }
override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) { override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) {
if (declaration == null) { if (declaration == null || target == declaration.descriptor) {
codegen.ret(value)
return
}
if (target == declaration.descriptor) {
codegen.ret(value) codegen.ret(value)
} else { } else {
super.genReturn(target, value) super.genReturn(target, value)
@@ -582,9 +577,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
private fun bindParameters(descriptor: FunctionDescriptor?): Map<ParameterDescriptor, LLVMValueRef> { private fun bindParameters(descriptor: FunctionDescriptor?): Map<ParameterDescriptor, LLVMValueRef> {
if (descriptor == null) return emptyMap() if (descriptor == null) return emptyMap()
val paramDescriptors = descriptor.allValueParameters val paramDescriptors = descriptor.allValueParameters
assert(paramDescriptors.size == codegen.countParams(descriptor))
return paramDescriptors.mapIndexed { i, paramDescriptor -> return paramDescriptors.mapIndexed { i, paramDescriptor ->
val param = codegen.param(descriptor, i) val param = codegen.param(descriptor, i)
assert(codegen.getLLVMType(paramDescriptor.type) == param.type) assert(codegen.getLLVMType(paramDescriptor.type) == param.type)
@@ -757,7 +749,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val initFunction = value.descriptor.constructors.first { it.valueParameters.size == 0 } val initFunction = value.descriptor.constructors.first { it.valueParameters.size == 0 }
val ctor = codegen.llvmFunction(initFunction) val ctor = codegen.llvmFunction(initFunction)
val args = listOf(objectPtr, typeInfo, allocHint, ctor) val args = listOf(objectPtr, typeInfo, allocHint, ctor)
val newValue = currentCodeContext.genCall(context.llvm.initInstanceFunction, args) val newValue = call(context.llvm.initInstanceFunction, args)
codegen.br(bbExit) codegen.br(bbExit)
codegen.positionAtEnd(bbExit) codegen.positionAtEnd(bbExit)
@@ -846,7 +838,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
} }
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
private fun evaluateVararg(value: IrVararg): LLVMValueRef? { private fun evaluateVararg(value: IrVararg): LLVMValueRef? {
@@ -879,14 +870,13 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val typeInfo = codegen.typeInfoValue(value.type)!! val typeInfo = codegen.typeInfoValue(value.type)!!
val arrayCreationArgs = listOf(typeInfo, kImmInt32One, finalLength) val arrayCreationArgs = listOf(typeInfo, kImmInt32One, finalLength)
val array = currentCodeContext.genCall(context.llvm.allocArrayFunction, arrayCreationArgs) val array = call(context.llvm.allocArrayFunction, arrayCreationArgs)
elements.fold(kImmZero) { sum, (exp, size, isArray) -> elements.fold(kImmZero) { sum, (exp, size, isArray) ->
if (!isArray) { if (!isArray) {
currentCodeContext.genCall(context.llvm.setArrayFunction, listOf(array, sum, exp)) call(context.llvm.setArrayFunction, listOf(array, sum, exp))
return@fold codegen.plus(sum, kImmOne) return@fold codegen.plus(sum, kImmOne)
} else { } else {
currentCodeContext.genCall(context.llvm.copyImplArrayFunction, listOf(exp, kImmZero, array, sum, size!!)) call(context.llvm.copyImplArrayFunction, listOf(exp, kImmZero, array, sum, size!!))
return@fold codegen.plus(sum, size) return@fold codegen.plus(sum, size)
} }
} }
@@ -920,7 +910,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val toStringDescriptor = getToString(it.type) val toStringDescriptor = getToString(it.type)
val string = if (KotlinBuiltIns.isString(it.type)) evaluationResult val string = if (KotlinBuiltIns.isString(it.type)) evaluationResult
else evaluateSimpleFunctionCall(toStringDescriptor, listOf(evaluationResult)) else evaluateSimpleFunctionCall(toStringDescriptor, listOf(evaluationResult))
val length = currentCodeContext.genCall(codegen.llvmFunction(kStringLength!!), listOf(string)) val length = call(codegen.llvmFunction(kStringLength!!), listOf(string))
return@map Element(string, length, -1) return@map Element(string, length, -1)
} }
} }
@@ -933,12 +923,12 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val constructor = kStringBuilder!!.constructors val constructor = kStringBuilder!!.constructors
.firstOrNull { it -> it.valueParameters.size == 1 && KotlinBuiltIns.isInt(it.valueParameters[0].type) }!! .firstOrNull { it -> it.valueParameters.size == 1 && KotlinBuiltIns.isInt(it.valueParameters[0].type) }!!
val stringBuilderObjPtr = currentCodeContext.genCall(context.llvm.allocInstanceFunction, val stringBuilderObj = call(context.llvm.allocInstanceFunction,
listOf(codegen.typeInfoValue(kStringBuilder.defaultType)!!, kImmOne)) listOf(codegen.typeInfoValue(kStringBuilder.defaultType)!!, kImmOne))
val stringBuilderObj = currentCodeContext.genCall(codegen.llvmFunction(constructor), listOf(stringBuilderObjPtr, totalLength)) call(codegen.llvmFunction(constructor), listOf(stringBuilderObj, totalLength))
stringsWithLengths.fold(stringBuilderObj) { sum, (string, _, _) -> stringsWithLengths.fold(stringBuilderObj) { sum, (string, _, _) ->
currentCodeContext.genCall(codegen.llvmFunction(kStringBuilderAppendStringFn!!), listOf(sum, string)) call(codegen.llvmFunction(kStringBuilderAppendStringFn!!), listOf(sum, string))
return@fold sum return@fold sum
} }
@@ -1390,7 +1380,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val srcArg = evaluateExpression(value.argument)!! // Evaluate src expression. val srcArg = evaluateExpression(value.argument)!! // Evaluate src expression.
val srcObjInfoPtr = codegen.bitcast(codegen.kObjHeaderPtr, srcArg) // Cast src to ObjInfoPtr. val srcObjInfoPtr = codegen.bitcast(codegen.kObjHeaderPtr, srcArg) // Cast src to ObjInfoPtr.
val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list. val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list.
currentCodeContext.genCall(context.llvm.checkInstanceFunction, args) // Check if dst is subclass of src. call(context.llvm.checkInstanceFunction, args) // Check if dst is subclass of src.
return srcArg return srcArg
} }
@@ -1431,9 +1421,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val srcObjInfoPtr = codegen.bitcast(codegen.kObjHeaderPtr, obj) // Cast src to ObjInfoPtr. val srcObjInfoPtr = codegen.bitcast(codegen.kObjHeaderPtr, obj) // Cast src to ObjInfoPtr.
val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list. val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list.
val result = currentCodeContext.genCall( // Check if dst is subclass of src. val result = call(context.llvm.isInstanceFunction, args) // Check if dst is subclass of src.
context.llvm.isInstanceFunction, args)
return LLVMBuildTrunc(codegen.builder, result, kInt1, "")!! // Truncate result to boolean return LLVMBuildTrunc(codegen.builder, result, kInt1, "")!! // Truncate result to boolean
} }
@@ -1783,14 +1771,15 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val thisValue = if (containingClass.isArray) { val thisValue = if (containingClass.isArray) {
assert(args.size == 1 && args[0].type == int32Type) assert(args.size == 1 && args[0].type == int32Type)
val allocArrayInstanceArgs = listOf(typeInfo, allocHint, args[0]) val allocArrayInstanceArgs = listOf(typeInfo, allocHint, args[0])
currentCodeContext.genCall(context.llvm.allocArrayFunction, allocArrayInstanceArgs) call(context.llvm.allocArrayFunction, allocArrayInstanceArgs)
} else { } else {
currentCodeContext.genCall(context.llvm.allocInstanceFunction, listOf(typeInfo, allocHint)) call(context.llvm.allocInstanceFunction, listOf(typeInfo, allocHint))
} }
val constructorParams: MutableList<LLVMValueRef> = mutableListOf() val constructorParams: MutableList<LLVMValueRef> = mutableListOf()
constructorParams += thisValue constructorParams += thisValue
constructorParams += args constructorParams += args
return evaluateSimpleFunctionCall(callee.descriptor as FunctionDescriptor, constructorParams) evaluateSimpleFunctionCall(callee.descriptor as FunctionDescriptor, constructorParams)
return thisValue
} }
} }
@@ -1900,8 +1889,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val typeInfoPtr = codegen.bitcast(codegen.kTypeInfoPtr, typeInfoI8Ptr) // Cast TypeInfo (i8*) to TypeInfo*. val typeInfoPtr = codegen.bitcast(codegen.kTypeInfoPtr, typeInfoI8Ptr) // Cast TypeInfo (i8*) to TypeInfo*.
val methodHash = codegen.functionHash(descriptor) // Calculate hash of the method to be invoked val methodHash = codegen.functionHash(descriptor) // Calculate hash of the method to be invoked
val lookupArgs = listOf(typeInfoPtr, methodHash) // Prepare args for lookup val lookupArgs = listOf(typeInfoPtr, methodHash) // Prepare args for lookup
val llvmMethod = currentCodeContext.genCall( val llvmMethod = call(context.llvm.lookupOpenMethodFunction,
context.llvm.lookupOpenMethodFunction,
lookupArgs) // Get method ptr to be invoked lookupArgs) // Get method ptr to be invoked
val functionPtrType = pointerType(codegen.getLlvmFunctionType(descriptor)) // Construct type of the method to be invoked val functionPtrType = pointerType(codegen.getLlvmFunctionType(descriptor)) // Construct type of the method to be invoked
@@ -1916,13 +1904,24 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
// In such case it would be possible to check that all args are available and in the correct order. // In such case it would be possible to check that all args are available and in the correct order.
// However, it currently requires some refactoring to be performed. // However, it currently requires some refactoring to be performed.
private fun call(descriptor: FunctionDescriptor, function: LLVMValueRef, args: List<LLVMValueRef>): LLVMValueRef { private fun call(descriptor: FunctionDescriptor, function: LLVMValueRef, args: List<LLVMValueRef>): LLVMValueRef {
val result = currentCodeContext.genCall(function, args) val result = call(function, args)
if (descriptor.returnType?.isNothing() == true) { if (descriptor.returnType?.isNothing() == true) {
codegen.unreachable() codegen.unreachable()
} }
return result return result
} }
private fun call(function: LLVMValueRef, args: List<LLVMValueRef>): LLVMValueRef {
if (codegen.isObjectReturn(function.type)) {
// If function returns an object - create slot for the returned value.
// This allows appropriate rootset accounting by just looking on stack slots.
val resultSlot = codegen.vars.createAnonymousSlot()
return currentCodeContext.genCall(function, args + resultSlot)
} else {
return currentCodeContext.genCall(function, args)
}
}
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
fun delegatingConstructorCall(descriptor: ClassConstructorDescriptor, args: List<LLVMValueRef>): LLVMValueRef { fun delegatingConstructorCall(descriptor: ClassConstructorDescriptor, args: List<LLVMValueRef>): LLVMValueRef {
@@ -4,6 +4,7 @@ import kotlinx.cinterop.*
import llvm.* import llvm.*
import org.jetbrains.kotlin.backend.konan.descriptors.allValueParameters import org.jetbrains.kotlin.backend.konan.descriptors.allValueParameters
import org.jetbrains.kotlin.backend.konan.KonanPlatform import org.jetbrains.kotlin.backend.konan.KonanPlatform
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
internal val LLVMValueRef.type: LLVMTypeRef internal val LLVMValueRef.type: LLVMTypeRef
@@ -141,10 +142,14 @@ internal fun structType(types: List<LLVMTypeRef>): LLVMTypeRef = memScoped {
LLVMStructType(allocArrayOf(types)[0].ptr, types.size, 0)!! LLVMStructType(allocArrayOf(types)[0].ptr, types.size, 0)!!
} }
internal fun ContextUtils.isObjectType(type: LLVMTypeRef) : Boolean {
return type == kObjHeaderPtr || type == kArrayHeaderPtr
}
internal fun ContextUtils.getLlvmFunctionType(function: FunctionDescriptor): LLVMTypeRef { internal fun ContextUtils.getLlvmFunctionType(function: FunctionDescriptor): LLVMTypeRef {
val returnType = getLLVMType(function.returnType!!) val returnType = if (function is ConstructorDescriptor) voidType else getLLVMType(function.returnType!!)
val params = function.allValueParameters val paramTypes = ArrayList(function.allValueParameters.map { getLLVMType(it.type) })
val paramTypes = params.map { getLLVMType(it.type) } if (isObjectType(returnType)) paramTypes.add(kObjHeaderPtrPtr)
memScoped { memScoped {
val paramTypesPtr = allocArrayOf(paramTypes)[0].ptr val paramTypesPtr = allocArrayOf(paramTypes)[0].ptr
@@ -152,6 +157,17 @@ internal fun ContextUtils.getLlvmFunctionType(function: FunctionDescriptor): LLV
} }
} }
internal fun ContextUtils.numParameters(functionType: LLVMTypeRef) : Int {
// Note that type is usually function pointer, so we have to dereference it.
return LLVMCountParamTypes(LLVMGetElementType(functionType))!!
}
internal fun ContextUtils.isObjectReturn(functionType: LLVMTypeRef) : Boolean {
// Note that type is usually function pointer, so we have to dereference it.
val returnType = LLVMGetReturnType(LLVMGetElementType(functionType))!!
return isObjectType(returnType)
}
/** /**
* Reads [size] bytes contained in this array. * Reads [size] bytes contained in this array.
*/ */
@@ -197,3 +213,8 @@ fun llvm2string(value: LLVMValueRef?): String {
return LLVMPrintValueToString(value)!!.asCString().toString() return LLVMPrintValueToString(value)!!.asCString().toString()
} }
fun llvmtype2string(type: LLVMTypeRef?): String {
if (type == null) return "<null type>"
return LLVMPrintTypeToString(type)!!.asCString().toString()
}
@@ -60,7 +60,7 @@ internal class VariableManager(val codegen: CodeGenerator) {
// TODO: fix, due to the bug in frontend, we shall always create stack slot for variable now. // TODO: fix, due to the bug in frontend, we shall always create stack slot for variable now.
// Note that we always create slot for object references for memory management. // Note that we always create slot for object references for memory management.
val descriptor = scoped.first val descriptor = scoped.first
if (descriptor.isVar() || isObjectType(codegen.getLLVMType(descriptor.type)) || true) { if (descriptor.isVar() || codegen.isObjectType(codegen.getLLVMType(descriptor.type)) || true) {
return createMutable(scoped, value) return createMutable(scoped, value)
} else { } else {
return createImmutable(scoped, value!!) return createImmutable(scoped, value!!)
@@ -75,7 +75,7 @@ internal class VariableManager(val codegen: CodeGenerator) {
val slot = codegen.alloca(type, descriptor.name.asString()) val slot = codegen.alloca(type, descriptor.name.asString())
if (value != null) if (value != null)
codegen.store(value, slot) codegen.store(value, slot)
variables.add(SlotRecord(slot, isObjectType(type))) variables.add(SlotRecord(slot, codegen.isObjectType(type)))
descriptors[scoped] = index descriptors[scoped] = index
return index return index
} }
@@ -85,12 +85,18 @@ internal class VariableManager(val codegen: CodeGenerator) {
return createAnonymousMutable(codegen.getLLVMType(type), value) return createAnonymousMutable(codegen.getLLVMType(type), value)
} }
// Think of slot reuse.
fun createAnonymousSlot(value: LLVMValueRef? = null) : LLVMValueRef {
val index = createAnonymousMutable(codegen.kObjHeaderPtr, value)
return addressOf(index)
}
fun createAnonymousMutable(type: LLVMTypeRef, value: LLVMValueRef? = null) : Int { fun createAnonymousMutable(type: LLVMTypeRef, value: LLVMValueRef? = null) : Int {
val index = variables.size val index = variables.size
val slot = codegen.alloca(type) val slot = codegen.alloca(type)
if (value != null) if (value != null)
codegen.store(value, slot) codegen.store(value, slot)
variables.add(SlotRecord(slot, isObjectType(type))) variables.add(SlotRecord(slot, codegen.isObjectType(type)))
return index return index
} }
@@ -118,8 +124,4 @@ internal class VariableManager(val codegen: CodeGenerator) {
fun store(value: LLVMValueRef, index: Int) { fun store(value: LLVMValueRef, index: Int) {
variables[index].store(value) variables[index].store(value)
} }
private fun isObjectType(type: LLVMTypeRef) : Boolean {
return type == codegen.kObjHeaderPtr || type == codegen.kArrayHeaderPtr
}
} }
+6
View File
@@ -108,6 +108,7 @@ abstract class KonanTest extends DefaultTask {
} }
} }
// Please do not use this framework anymore!
class UnitKonanTest extends KonanTest { class UnitKonanTest extends KonanTest {
void compileTest(File sourceS, File runtimeS, File stdlibKtBc, File exe) { void compileTest(File sourceS, File runtimeS, File stdlibKtBc, File exe) {
def testC = sourceS.absolutePath.replace(".kt.S", "-test.c") def testC = sourceS.absolutePath.replace(".kt.S", "-test.c")
@@ -120,6 +121,11 @@ class UnitKonanTest extends KonanTest {
args argList args argList
} }
} }
@TaskAction
void executeTest() {
// Do nothing, unit tests go away.
}
} }
class RunKonanTest extends KonanTest { class RunKonanTest extends KonanTest {
+14 -13
View File
@@ -5,16 +5,15 @@
//--- Setup args --------------------------------------------------------------// //--- Setup args --------------------------------------------------------------//
ObjHeader* setupArgs(int argc, char** argv) { OBJ_GETTER(setupArgs, int argc, char** argv) {
// The count is one less, because we skip argv[0] which is the binary name. // The count is one less, because we skip argv[0] which is the binary name.
ObjHeader* args = AllocArrayInstance(theArrayTypeInfo, SCOPE_GLOBAL, argc-1); AllocArrayInstance(theArrayTypeInfo, SCOPE_GLOBAL, argc - 1, OBJ_RESULT);
ArrayHeader* array = (*OBJ_RESULT)->array();
for (int i = 0; i < argc-1; i++) { for (int index = 0; index < argc - 1; index++) {
Kotlin_Array_set(args, i, AllocStringInstance( AllocStringInstance(SCOPE_GLOBAL, argv[index + 1], strlen(argv[index + 1]),
SCOPE_GLOBAL, argv[i+1], strlen(argv[i+1]) )); ArrayAddressOfElementAt(array, index));
} }
RETURN_OBJ_RESULT();
return args;
} }
//--- main --------------------------------------------------------------------// //--- main --------------------------------------------------------------------//
@@ -26,9 +25,11 @@ int main(int argc, char** argv) {
InitMemory(); InitMemory();
InitGlobalVariables(); InitGlobalVariables();
ObjHeader* args = setupArgs(argc, argv); {
ObjHolder args;
Konan_start(args); setupArgs(argc, argv, args.slot());
Konan_start(args.obj());
}
// Yes, we have to follow Java convention and return zero. // Yes, we have to follow Java convention and return zero.
return 0; return 0;
+23 -23
View File
@@ -12,12 +12,12 @@ extern "C" {
// TODO: those must be compiler intrinsics afterwards. // TODO: those must be compiler intrinsics afterwards.
// Array.kt // Array.kt
KRef Kotlin_Array_get(KConstRef thiz, KInt index) { OBJ_GETTER(Kotlin_Array_get, KConstRef thiz, KInt index) {
const ArrayHeader* array = thiz->array(); const ArrayHeader* array = thiz->array();
if (static_cast<uint32_t>(index) >= array->count_) { if (static_cast<uint32_t>(index) >= array->count_) {
ThrowArrayIndexOutOfBoundsException(); ThrowArrayIndexOutOfBoundsException();
} }
return *ArrayAddressOfElementAt(array, index); RETURN_OBJ(*ArrayAddressOfElementAt(array, index));
} }
void Kotlin_Array_set(KRef thiz, KInt index, KConstRef value) { void Kotlin_Array_set(KRef thiz, KInt index, KConstRef value) {
@@ -25,10 +25,10 @@ void Kotlin_Array_set(KRef thiz, KInt index, KConstRef value) {
if (static_cast<uint32_t>(index) >= array->count_) { if (static_cast<uint32_t>(index) >= array->count_) {
ThrowArrayIndexOutOfBoundsException(); ThrowArrayIndexOutOfBoundsException();
} }
*ArrayAddressOfElementAt(array, index) = value; UpdateGlobalRef(ArrayAddressOfElementAt(array, index), value);
} }
KRef Kotlin_Array_clone(KConstRef thiz) { OBJ_GETTER(Kotlin_Array_clone, KConstRef thiz) {
const ArrayHeader* array = thiz->array(); const ArrayHeader* array = thiz->array();
ArrayHeader* result = ArrayContainer( ArrayHeader* result = ArrayContainer(
array->type_info(), array->count_).GetPlace(); array->type_info(), array->count_).GetPlace();
@@ -36,7 +36,7 @@ KRef Kotlin_Array_clone(KConstRef thiz) {
ArrayAddressOfElementAt(result, 0), ArrayAddressOfElementAt(result, 0),
ArrayAddressOfElementAt(array, 0), ArrayAddressOfElementAt(array, 0),
ArrayDataSizeBytes(array)); ArrayDataSizeBytes(array));
return result->obj(); RETURN_OBJ(result->obj());
} }
KInt Kotlin_Array_getArrayLength(KConstRef thiz) { KInt Kotlin_Array_getArrayLength(KConstRef thiz) {
@@ -85,7 +85,7 @@ void Kotlin_ByteArray_set(KRef thiz, KInt index, KByte value) {
*ByteArrayAddressOfElementAt(array, index) = value; *ByteArrayAddressOfElementAt(array, index) = value;
} }
KRef Kotlin_ByteArray_clone(KConstRef thiz) { OBJ_GETTER(Kotlin_ByteArray_clone, KConstRef thiz) {
const ArrayHeader* array = thiz->array(); const ArrayHeader* array = thiz->array();
ArrayHeader* result = ArrayContainer( ArrayHeader* result = ArrayContainer(
theByteArrayTypeInfo, array->count_).GetPlace(); theByteArrayTypeInfo, array->count_).GetPlace();
@@ -93,7 +93,7 @@ KRef Kotlin_ByteArray_clone(KConstRef thiz) {
ByteArrayAddressOfElementAt(result, 0), ByteArrayAddressOfElementAt(result, 0),
ByteArrayAddressOfElementAt(array, 0), ByteArrayAddressOfElementAt(array, 0),
ArrayDataSizeBytes(array)); ArrayDataSizeBytes(array));
return result->obj(); RETURN_OBJ(result->obj());
} }
KInt Kotlin_ByteArray_getArrayLength(KConstRef thiz) { KInt Kotlin_ByteArray_getArrayLength(KConstRef thiz) {
@@ -117,7 +117,7 @@ void Kotlin_CharArray_set(KRef thiz, KInt index, KChar value) {
*PrimitiveArrayAddressOfElementAt<KChar>(array, index) = value; *PrimitiveArrayAddressOfElementAt<KChar>(array, index) = value;
} }
KRef Kotlin_CharArray_clone(KConstRef thiz) { OBJ_GETTER(Kotlin_CharArray_clone, KConstRef thiz) {
const ArrayHeader* array = thiz->array(); const ArrayHeader* array = thiz->array();
ArrayHeader* result = ArrayContainer( ArrayHeader* result = ArrayContainer(
theCharArrayTypeInfo, array->count_).GetPlace(); theCharArrayTypeInfo, array->count_).GetPlace();
@@ -125,10 +125,10 @@ KRef Kotlin_CharArray_clone(KConstRef thiz) {
PrimitiveArrayAddressOfElementAt<KChar>(result, 0), PrimitiveArrayAddressOfElementAt<KChar>(result, 0),
PrimitiveArrayAddressOfElementAt<KChar>(array, 0), PrimitiveArrayAddressOfElementAt<KChar>(array, 0),
ArrayDataSizeBytes(array)); ArrayDataSizeBytes(array));
return result->obj(); RETURN_OBJ(result->obj());
} }
KRef Kotlin_CharArray_copyOf(KConstRef thiz, KInt newSize) { OBJ_GETTER(Kotlin_CharArray_copyOf, KConstRef thiz, KInt newSize) {
const ArrayHeader* array = thiz->array(); const ArrayHeader* array = thiz->array();
ArrayHeader* result = ArrayContainer( ArrayHeader* result = ArrayContainer(
theCharArrayTypeInfo, newSize).GetPlace(); theCharArrayTypeInfo, newSize).GetPlace();
@@ -137,7 +137,7 @@ KRef Kotlin_CharArray_copyOf(KConstRef thiz, KInt newSize) {
PrimitiveArrayAddressOfElementAt<KChar>(result, 0), PrimitiveArrayAddressOfElementAt<KChar>(result, 0),
PrimitiveArrayAddressOfElementAt<KChar>(array, 0), PrimitiveArrayAddressOfElementAt<KChar>(array, 0),
toCopy * sizeof(KChar)); toCopy * sizeof(KChar));
return result->obj(); RETURN_OBJ(result->obj());
} }
KInt Kotlin_CharArray_getArrayLength(KConstRef thiz) { KInt Kotlin_CharArray_getArrayLength(KConstRef thiz) {
@@ -161,7 +161,7 @@ void Kotlin_ShortArray_set(KRef thiz, KInt index, KShort value) {
*PrimitiveArrayAddressOfElementAt<KShort>(array, index) = value; *PrimitiveArrayAddressOfElementAt<KShort>(array, index) = value;
} }
KRef Kotlin_ShortArray_clone(KConstRef thiz) { OBJ_GETTER(Kotlin_ShortArray_clone, KConstRef thiz) {
const ArrayHeader* array = thiz->array(); const ArrayHeader* array = thiz->array();
ArrayHeader* result = ArrayContainer( ArrayHeader* result = ArrayContainer(
theShortArrayTypeInfo, array->count_).GetPlace(); theShortArrayTypeInfo, array->count_).GetPlace();
@@ -169,7 +169,7 @@ KRef Kotlin_ShortArray_clone(KConstRef thiz) {
PrimitiveArrayAddressOfElementAt<KShort>(result, 0), PrimitiveArrayAddressOfElementAt<KShort>(result, 0),
PrimitiveArrayAddressOfElementAt<KShort>(array, 0), PrimitiveArrayAddressOfElementAt<KShort>(array, 0),
ArrayDataSizeBytes(array)); ArrayDataSizeBytes(array));
return result->obj(); RETURN_OBJ(result->obj());
} }
KInt Kotlin_ShortArray_getArrayLength(KConstRef thiz) { KInt Kotlin_ShortArray_getArrayLength(KConstRef thiz) {
@@ -193,7 +193,7 @@ void Kotlin_IntArray_set(KRef thiz, KInt index, KInt value) {
*PrimitiveArrayAddressOfElementAt<KInt>(array, index) = value; *PrimitiveArrayAddressOfElementAt<KInt>(array, index) = value;
} }
KRef Kotlin_IntArray_clone(KConstRef thiz) { OBJ_GETTER(Kotlin_IntArray_clone, KConstRef thiz) {
const ArrayHeader* array = thiz->array(); const ArrayHeader* array = thiz->array();
ArrayHeader* result = ArrayContainer( ArrayHeader* result = ArrayContainer(
theIntArrayTypeInfo, array->count_).GetPlace(); theIntArrayTypeInfo, array->count_).GetPlace();
@@ -201,7 +201,7 @@ KRef Kotlin_IntArray_clone(KConstRef thiz) {
PrimitiveArrayAddressOfElementAt<KInt>(result, 0), PrimitiveArrayAddressOfElementAt<KInt>(result, 0),
PrimitiveArrayAddressOfElementAt<KInt>(array, 0), PrimitiveArrayAddressOfElementAt<KInt>(array, 0),
ArrayDataSizeBytes(array)); ArrayDataSizeBytes(array));
return result->obj(); RETURN_OBJ(result->obj());
} }
KInt Kotlin_IntArray_getArrayLength(KConstRef thiz) { KInt Kotlin_IntArray_getArrayLength(KConstRef thiz) {
@@ -249,7 +249,7 @@ void Kotlin_LongArray_set(KRef thiz, KInt index, KLong value) {
*PrimitiveArrayAddressOfElementAt<KLong>(array, index) = value; *PrimitiveArrayAddressOfElementAt<KLong>(array, index) = value;
} }
KRef Kotlin_LongArray_clone(KConstRef thiz) { OBJ_GETTER(Kotlin_LongArray_clone, KConstRef thiz) {
const ArrayHeader* array = thiz->array(); const ArrayHeader* array = thiz->array();
ArrayHeader* result = ArrayContainer( ArrayHeader* result = ArrayContainer(
theLongArrayTypeInfo, array->count_).GetPlace(); theLongArrayTypeInfo, array->count_).GetPlace();
@@ -257,7 +257,7 @@ KRef Kotlin_LongArray_clone(KConstRef thiz) {
PrimitiveArrayAddressOfElementAt<KLong>(result, 0), PrimitiveArrayAddressOfElementAt<KLong>(result, 0),
PrimitiveArrayAddressOfElementAt<KLong>(array, 0), PrimitiveArrayAddressOfElementAt<KLong>(array, 0),
ArrayDataSizeBytes(array)); ArrayDataSizeBytes(array));
return result->obj(); RETURN_OBJ(result->obj());
} }
KInt Kotlin_LongArray_getArrayLength(KConstRef thiz) { KInt Kotlin_LongArray_getArrayLength(KConstRef thiz) {
@@ -281,7 +281,7 @@ void Kotlin_FloatArray_set(KRef thiz, KInt index, KFloat value) {
*PrimitiveArrayAddressOfElementAt<KFloat>(array, index) = value; *PrimitiveArrayAddressOfElementAt<KFloat>(array, index) = value;
} }
KRef Kotlin_FloatArray_clone(KConstRef thiz) { OBJ_GETTER(Kotlin_FloatArray_clone, KConstRef thiz) {
const ArrayHeader* array = thiz->array(); const ArrayHeader* array = thiz->array();
ArrayHeader* result = ArrayContainer( ArrayHeader* result = ArrayContainer(
theFloatArrayTypeInfo, array->count_).GetPlace(); theFloatArrayTypeInfo, array->count_).GetPlace();
@@ -289,7 +289,7 @@ KRef Kotlin_FloatArray_clone(KConstRef thiz) {
PrimitiveArrayAddressOfElementAt<KFloat>(result, 0), PrimitiveArrayAddressOfElementAt<KFloat>(result, 0),
PrimitiveArrayAddressOfElementAt<KFloat>(array, 0), PrimitiveArrayAddressOfElementAt<KFloat>(array, 0),
ArrayDataSizeBytes(array)); ArrayDataSizeBytes(array));
return result->obj(); RETURN_OBJ(result->obj());
} }
KInt Kotlin_FloatArray_getArrayLength(KConstRef thiz) { KInt Kotlin_FloatArray_getArrayLength(KConstRef thiz) {
@@ -313,7 +313,7 @@ void Kotlin_DoubleArray_set(KRef thiz, KInt index, KDouble value) {
*PrimitiveArrayAddressOfElementAt<KDouble>(array, index) = value; *PrimitiveArrayAddressOfElementAt<KDouble>(array, index) = value;
} }
KRef Kotlin_DoubleArray_clone(KConstRef thiz) { OBJ_GETTER(Kotlin_DoubleArray_clone, KConstRef thiz) {
const ArrayHeader* array = thiz->array(); const ArrayHeader* array = thiz->array();
ArrayHeader* result = ArrayContainer( ArrayHeader* result = ArrayContainer(
theDoubleArrayTypeInfo, array->count_).GetPlace(); theDoubleArrayTypeInfo, array->count_).GetPlace();
@@ -321,7 +321,7 @@ KRef Kotlin_DoubleArray_clone(KConstRef thiz) {
PrimitiveArrayAddressOfElementAt<KDouble>(result, 0), PrimitiveArrayAddressOfElementAt<KDouble>(result, 0),
PrimitiveArrayAddressOfElementAt<KDouble>(array, 0), PrimitiveArrayAddressOfElementAt<KDouble>(array, 0),
ArrayDataSizeBytes(array)); ArrayDataSizeBytes(array));
return result->obj(); RETURN_OBJ(result->obj());
} }
KInt Kotlin_DoubleArray_getArrayLength(KConstRef thiz) { KInt Kotlin_DoubleArray_getArrayLength(KConstRef thiz) {
@@ -345,7 +345,7 @@ void Kotlin_BooleanArray_set(KRef thiz, KInt index, KBoolean value) {
*PrimitiveArrayAddressOfElementAt<KBoolean>(array, index) = value; *PrimitiveArrayAddressOfElementAt<KBoolean>(array, index) = value;
} }
KRef Kotlin_BooleanArray_clone(KConstRef thiz) { OBJ_GETTER(Kotlin_BooleanArray_clone, KConstRef thiz) {
const ArrayHeader* array = thiz->array(); const ArrayHeader* array = thiz->array();
ArrayHeader* result = ArrayContainer( ArrayHeader* result = ArrayContainer(
theBooleanArrayTypeInfo, array->count_).GetPlace(); theBooleanArrayTypeInfo, array->count_).GetPlace();
@@ -353,7 +353,7 @@ KRef Kotlin_BooleanArray_clone(KConstRef thiz) {
PrimitiveArrayAddressOfElementAt<KBoolean>(result, 0), PrimitiveArrayAddressOfElementAt<KBoolean>(result, 0),
PrimitiveArrayAddressOfElementAt<KBoolean>(array, 0), PrimitiveArrayAddressOfElementAt<KBoolean>(array, 0),
ArrayDataSizeBytes(array)); ArrayDataSizeBytes(array));
return result->obj(); RETURN_OBJ(result->obj());
} }
KInt Kotlin_BooleanArray_getArrayLength(KConstRef thiz) { KInt Kotlin_BooleanArray_getArrayLength(KConstRef thiz) {
+9 -12
View File
@@ -4,6 +4,7 @@
#include "Assert.h" #include "Assert.h"
#include "Exceptions.h" #include "Exceptions.h"
#include "Memory.h"
#include "Natives.h" #include "Natives.h"
#include "Types.h" #include "Types.h"
@@ -34,18 +35,13 @@ class AutoFree {
} }
}; };
// TODO: this method ignores the encoding.
KString CreateKotlinStringFromCString(const char* str) {
return AllocStringInstance(SCOPE_GLOBAL, str, strlen(str))->array();
}
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
// TODO: this implementation is just a hack, e.g. the result is inexact; // TODO: this implementation is just a hack, e.g. the result is inexact;
// however it is better to have an inexact stacktrace than not to have any. // however it is better to have an inexact stacktrace than not to have any.
KRef GetCurrentStackTrace() { OBJ_GETTER0(GetCurrentStackTrace) {
const int maxSize = 32; const int maxSize = 32;
void* buffer[maxSize]; void* buffer[maxSize];
@@ -54,20 +50,21 @@ KRef GetCurrentStackTrace() {
RuntimeAssert(symbols != nullptr, "Not enough memory to retrieve the stacktrace"); RuntimeAssert(symbols != nullptr, "Not enough memory to retrieve the stacktrace");
AutoFree autoFree(symbols); AutoFree autoFree(symbols);
KRef result = AllocArrayInstance(theArrayTypeInfo, SCOPE_GLOBAL, size); AllocArrayInstance(theArrayTypeInfo, SCOPE_GLOBAL, size, OBJ_RESULT);
for (int i = 0; i < size; ++i) { ArrayHeader* array = (*OBJ_RESULT)->array();
KString symbol = CreateKotlinStringFromCString(symbols[i]); for (int index = 0; index < size; ++index) {
Kotlin_Array_set(result, i, symbol->obj()); AllocStringInstance(
SCOPE_GLOBAL, symbols[index], strlen(symbols[index]),
ArrayAddressOfElementAt(array, index));
} }
return result; RETURN_OBJ_RESULT();
} }
void ThrowException(KRef exception) { void ThrowException(KRef exception) {
RuntimeAssert(exception != nullptr && IsInstance(exception, theThrowableTypeInfo), RuntimeAssert(exception != nullptr && IsInstance(exception, theThrowableTypeInfo),
"Throwing something non-throwable"); "Throwing something non-throwable");
throw KotlinException(exception); throw KotlinException(exception);
} }
+1 -1
View File
@@ -8,7 +8,7 @@ extern "C" {
#endif #endif
// Returns current stacktrace as Array<String>. // Returns current stacktrace as Array<String>.
KRef GetCurrentStackTrace(); OBJ_GETTER0(GetCurrentStackTrace);
// Throws arbitrary exception. // Throws arbitrary exception.
void ThrowException(KRef exception); void ThrowException(KRef exception);
+32 -19
View File
@@ -88,30 +88,30 @@ void InitMemory() {
} }
// Now we ignore all placement hints and always allocate heap space for new object. // Now we ignore all placement hints and always allocate heap space for new object.
ObjHeader* AllocInstance(const TypeInfo* type_info, PlacementHint hint) { OBJ_GETTER(AllocInstance, const TypeInfo* type_info, PlacementHint hint) {
RuntimeAssert(type_info->instanceSize_ >= 0, "must be an object"); RuntimeAssert(type_info->instanceSize_ >= 0, "must be an object");
return ObjectContainer(type_info).GetPlace(); RETURN_OBJ(ObjectContainer(type_info).GetPlace());
} }
ObjHeader* AllocArrayInstance( OBJ_GETTER(AllocArrayInstance,
const TypeInfo* type_info, PlacementHint hint, uint32_t elements) { const TypeInfo* type_info, PlacementHint hint, uint32_t elements) {
RuntimeAssert(type_info->instanceSize_ < 0, "must be an array"); RuntimeAssert(type_info->instanceSize_ < 0, "must be an array");
return ArrayContainer(type_info, elements).GetPlace()->obj(); RETURN_OBJ(ArrayContainer(type_info, elements).GetPlace()->obj());
} }
ObjHeader* AllocStringInstance( OBJ_GETTER(AllocStringInstance,
PlacementHint hint, const char* data, uint32_t length) { PlacementHint hint, const char* data, uint32_t length) {
ArrayHeader* result = ArrayContainer(theStringTypeInfo, length).GetPlace(); ArrayHeader* array = ArrayContainer(theStringTypeInfo, length).GetPlace();
memcpy( memcpy(
ByteArrayAddressOfElementAt(result, 0), ByteArrayAddressOfElementAt(array, 0),
data, data,
length); length);
return result->obj(); RETURN_OBJ(array->obj());
} }
ObjHeader* InitInstance( OBJ_GETTER(InitInstance,
ObjHeader** location, const TypeInfo* type_info, PlacementHint hint, ObjHeader** location, const TypeInfo* type_info, PlacementHint hint,
ObjHeader* (*ctor)(ObjHeader*)) { void (*ctor)(ObjHeader*)) {
ObjHeader* sentinel = reinterpret_cast<ObjHeader*>(1); ObjHeader* sentinel = reinterpret_cast<ObjHeader*>(1);
ObjHeader* value; ObjHeader* value;
// Wait until other initializers. // Wait until other initializers.
@@ -122,21 +122,34 @@ ObjHeader* InitInstance(
if (value != nullptr) { if (value != nullptr) {
// OK'ish, inited by someone else. // OK'ish, inited by someone else.
return value; RETURN_OBJ(value);
} }
ObjHeader* instance = AllocInstance(type_info, hint); AllocInstance(type_info, hint, OBJ_RESULT);
try { try {
ctor(instance); ctor(*OBJ_RESULT);
__sync_val_compare_and_swap(location, sentinel, instance); bool ok = __sync_bool_compare_and_swap(location, sentinel, *OBJ_RESULT);
return instance; RuntimeAssert(ok, "CAS must succeed");
RETURN_OBJ_RESULT();
} catch (...) { } catch (...) {
Release(instance->container());
__sync_val_compare_and_swap(location, sentinel, nullptr); __sync_val_compare_and_swap(location, sentinel, nullptr);
return nullptr; RETURN_OBJ(nullptr);
} }
} }
// Just stubs.
void SetLocalRef(ObjHeader** location, const ObjHeader* object) {
*const_cast<const ObjHeader**>(location) = object;
}
void UpdateLocalRef(ObjHeader** location, const ObjHeader* object) {
*const_cast<const ObjHeader**>(location) = object;
}
void UpdateGlobalRef(ObjHeader** location, const ObjHeader* object) {
*const_cast<const ObjHeader**>(location) = object;
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
+45 -8
View File
@@ -282,18 +282,55 @@ class ArenaContainer : public Container {
extern "C" { extern "C" {
#endif #endif
#define OBJ_RESULT __result__
#define OBJ_GETTER0(name) ObjHeader* name(ObjHeader** OBJ_RESULT)
#define OBJ_GETTER(name, ...) ObjHeader* name(__VA_ARGS__, ObjHeader** OBJ_RESULT)
#define RETURN_OBJ(value) UpdateLocalRef(OBJ_RESULT, value); return value;
#define RETURN_OBJ_RESULT() return *OBJ_RESULT;
#define RETURN_RESULT_OF0(name) name(OBJ_RESULT); return *OBJ_RESULT;
#define RETURN_RESULT_OF(name, ...) name(__VA_ARGS__, OBJ_RESULT); return *OBJ_RESULT;
void InitMemory(); void InitMemory();
ObjHeader* AllocInstance(const TypeInfo* type_info, PlacementHint hint); OBJ_GETTER(AllocInstance, const TypeInfo* type_info, PlacementHint hint);
ObjHeader* AllocArrayInstance( OBJ_GETTER(AllocArrayInstance,
const TypeInfo* type_info, PlacementHint hint, uint32_t elements); const TypeInfo* type_info, PlacementHint hint, uint32_t elements);
ObjHeader* AllocStringInstance(PlacementHint hint, OBJ_GETTER(AllocStringInstance,
const char* data, uint32_t length); PlacementHint hint, const char* data, uint32_t length);
ObjHeader* InitInstance( OBJ_GETTER(InitInstance,
ObjHeader** location, const TypeInfo* type_info, PlacementHint hint, ObjHeader** location, const TypeInfo* type_info, PlacementHint hint,
ObjHeader* (*ctor)(ObjHeader*)); void (*ctor)(ObjHeader*));
// Sets locally visible location.
void SetLocalRef(ObjHeader** location, const ObjHeader* object);
// Sets potentially globally visible location.
void SetGlobalRef(ObjHeader** location, const ObjHeader* object);
// Update locally visible location.
void UpdateLocalRef(ObjHeader** location, const ObjHeader* object);
// Update potentially globally visible location.
void UpdateGlobalRef(ObjHeader** location, const ObjHeader* object);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
// Class holding reference to an object, holding object during C++ scope.
class ObjHolder {
public:
ObjHolder() : obj_(nullptr) {}
explicit ObjHolder(const ObjHeader* obj) {
::SetLocalRef(&obj_, obj);
}
~ObjHolder() {
::UpdateLocalRef(&obj_, nullptr);
}
ObjHeader* obj() { return obj_; }
const ObjHeader* obj() const { return obj_; }
ObjHeader** slot() { return &obj_; }
private:
ObjHeader* obj_;
};
#endif // RUNTIME_MEMORY_H #endif // RUNTIME_MEMORY_H
+21 -20
View File
@@ -22,7 +22,8 @@ KInt Kotlin_Any_hashCode(KConstRef thiz) {
return reinterpret_cast<uintptr_t>(thiz); return reinterpret_cast<uintptr_t>(thiz);
} }
KString Kotlin_Any_toString(KConstRef thiz) { OBJ_GETTER(Kotlin_Any_toString, KConstRef thiz) {
// TODO: make it more sensible, such as address and type info.
return nullptr; return nullptr;
} }
@@ -44,7 +45,7 @@ void Kotlin_io_Console_println0() {
write(STDOUT_FILENO, "\n", 1); write(STDOUT_FILENO, "\n", 1);
} }
KString Kotlin_io_Console_readLine() { OBJ_GETTER0(Kotlin_io_Console_readLine) {
char data[2048]; char data[2048];
if (!fgets(data, sizeof(data) - 1, stdin)) { if (!fgets(data, sizeof(data) - 1, stdin)) {
return nullptr; return nullptr;
@@ -54,7 +55,7 @@ KString Kotlin_io_Console_readLine() {
memcpy( memcpy(
ByteArrayAddressOfElementAt(result, 0), ByteArrayAddressOfElementAt(result, 0),
data, length); data, length);
return result; RETURN_OBJ(result->obj());
} }
// String.kt // String.kt
@@ -76,7 +77,7 @@ KInt Kotlin_String_getStringLength(KString thiz) {
return thiz->count_; return thiz->count_;
} }
KString Kotlin_String_fromUtf8Array(KConstRef thiz, KInt start, KInt size) { OBJ_GETTER(Kotlin_String_fromUtf8Array, KConstRef thiz, KInt start, KInt size) {
const ArrayHeader* array = thiz->array(); const ArrayHeader* array = thiz->array();
RuntimeAssert(array->type_info() == theByteArrayTypeInfo, "Must use a byte array"); RuntimeAssert(array->type_info() == theByteArrayTypeInfo, "Must use a byte array");
if (start < 0 || size < 0 || start + size > array->count_) { if (start < 0 || size < 0 || start + size > array->count_) {
@@ -84,7 +85,7 @@ KString Kotlin_String_fromUtf8Array(KConstRef thiz, KInt start, KInt size) {
} }
if (size == 0) { if (size == 0) {
return TheEmptyString(); RETURN_RESULT_OF0(TheEmptyString);
} }
// TODO: support full UTF-8. // TODO: support full UTF-8.
@@ -93,10 +94,10 @@ KString Kotlin_String_fromUtf8Array(KConstRef thiz, KInt start, KInt size) {
ByteArrayAddressOfElementAt(result, 0), ByteArrayAddressOfElementAt(result, 0),
ByteArrayAddressOfElementAt(array, start), ByteArrayAddressOfElementAt(array, start),
size); size);
return result; RETURN_OBJ(result->obj());
} }
KString Kotlin_String_fromCharArray(KConstRef thiz, KInt start, KInt size) { OBJ_GETTER(Kotlin_String_fromCharArray, KConstRef thiz, KInt start, KInt size) {
const ArrayHeader* array = thiz->array(); const ArrayHeader* array = thiz->array();
RuntimeAssert(array->type_info() == theCharArrayTypeInfo, "Must use a byte array"); RuntimeAssert(array->type_info() == theCharArrayTypeInfo, "Must use a byte array");
if (start < 0 || size < 0 || start + size > array->count_) { if (start < 0 || size < 0 || start + size > array->count_) {
@@ -104,7 +105,7 @@ KString Kotlin_String_fromCharArray(KConstRef thiz, KInt start, KInt size) {
} }
if (size == 0) { if (size == 0) {
return TheEmptyString(); RETURN_RESULT_OF0(TheEmptyString);
} }
// TODO: support full UTF-8. // TODO: support full UTF-8.
@@ -113,10 +114,10 @@ KString Kotlin_String_fromCharArray(KConstRef thiz, KInt start, KInt size) {
*ByteArrayAddressOfElementAt(result, index) = *ByteArrayAddressOfElementAt(result, index) =
*PrimitiveArrayAddressOfElementAt<KChar>(array, start + index); *PrimitiveArrayAddressOfElementAt<KChar>(array, start + index);
} }
return result; RETURN_OBJ(result->obj());
} }
KRef Kotlin_String_toCharArray(KString string) { OBJ_GETTER(Kotlin_String_toCharArray, KString string) {
// TODO: support full UTF-8. // TODO: support full UTF-8.
ArrayHeader* result = ArrayContainer( ArrayHeader* result = ArrayContainer(
theCharArrayTypeInfo, string->count_).GetPlace(); theCharArrayTypeInfo, string->count_).GetPlace();
@@ -124,11 +125,11 @@ KRef Kotlin_String_toCharArray(KString string) {
*PrimitiveArrayAddressOfElementAt<KChar>(result, index) = *PrimitiveArrayAddressOfElementAt<KChar>(result, index) =
*ByteArrayAddressOfElementAt(string, index); *ByteArrayAddressOfElementAt(string, index);
} }
return result->obj(); RETURN_OBJ(result->obj());
} }
KString Kotlin_String_plusImpl(KString thiz, KString other) { OBJ_GETTER(Kotlin_String_plusImpl, KString thiz, KString other) {
// TODO: support UTF-8 // TODO: support UTF-8
RuntimeAssert(thiz != nullptr, "this cannot be null"); RuntimeAssert(thiz != nullptr, "this cannot be null");
RuntimeAssert(other != nullptr, "other cannot be null"); RuntimeAssert(other != nullptr, "other cannot be null");
@@ -145,7 +146,7 @@ KString Kotlin_String_plusImpl(KString thiz, KString other) {
ByteArrayAddressOfElementAt(result, thiz->count_), ByteArrayAddressOfElementAt(result, thiz->count_),
ByteArrayAddressOfElementAt(other, 0), ByteArrayAddressOfElementAt(other, 0),
other->count_); other->count_);
return result; RETURN_OBJ(result->obj());
} }
KBoolean Kotlin_String_equals(KString thiz, KConstRef other) { KBoolean Kotlin_String_equals(KString thiz, KConstRef other) {
@@ -165,13 +166,13 @@ KInt Kotlin_String_hashCode(KString thiz) {
return CityHash64(ByteArrayAddressOfElementAt(thiz, 0), thiz->count_); return CityHash64(ByteArrayAddressOfElementAt(thiz, 0), thiz->count_);
} }
KString Kotlin_String_subSequence(KString thiz, KInt startIndex, KInt endIndex) { OBJ_GETTER(Kotlin_String_subSequence, KString thiz, KInt startIndex, KInt endIndex) {
if (startIndex < 0 || endIndex >= thiz->count_ || startIndex > endIndex) { if (startIndex < 0 || endIndex >= thiz->count_ || startIndex > endIndex) {
// TODO: is it correct exception? // TODO: is it correct exception?
ThrowArrayIndexOutOfBoundsException(); ThrowArrayIndexOutOfBoundsException();
} }
if (startIndex == endIndex) { if (startIndex == endIndex) {
return TheEmptyString(); RETURN_RESULT_OF0(TheEmptyString);
} }
// TODO: support UTF-8. // TODO: support UTF-8.
KInt length = endIndex - startIndex; KInt length = endIndex - startIndex;
@@ -179,16 +180,16 @@ KString Kotlin_String_subSequence(KString thiz, KInt startIndex, KInt endIndex)
memcpy(ByteArrayAddressOfElementAt(result, 0), memcpy(ByteArrayAddressOfElementAt(result, 0),
ByteArrayAddressOfElementAt(thiz, startIndex), ByteArrayAddressOfElementAt(thiz, startIndex),
length); length);
return result; RETURN_OBJ(result->obj());
} }
KConstRef Kotlin_getCurrentStackTrace() { OBJ_GETTER0(Kotlin_getCurrentStackTrace) {
return GetCurrentStackTrace(); RETURN_RESULT_OF0(GetCurrentStackTrace);
} }
// TODO: consider handling it with compiler magic instead. // TODO: consider handling it with compiler magic instead.
KRef Kotlin_konan_internal_undefined() { OBJ_GETTER0(Kotlin_konan_internal_undefined) {
return nullptr; RETURN_OBJ(nullptr);
} }
} // extern "C" } // extern "C"
+18 -17
View File
@@ -37,8 +37,8 @@ inline const T* PrimitiveArrayAddressOfElementAt(
return reinterpret_cast<const T*>(obj + 1) + index; return reinterpret_cast<const T*>(obj + 1) + index;
} }
inline KConstRef* ArrayAddressOfElementAt(ArrayHeader* obj, KInt index) { inline KRef* ArrayAddressOfElementAt(ArrayHeader* obj, KInt index) {
return reinterpret_cast<KConstRef*>(obj + 1) + index; return reinterpret_cast<KRef*>(obj + 1) + index;
} }
inline const KRef* ArrayAddressOfElementAt(const ArrayHeader* obj, KInt index) { inline const KRef* ArrayAddressOfElementAt(const ArrayHeader* obj, KInt index) {
@@ -49,31 +49,32 @@ inline const KRef* ArrayAddressOfElementAt(const ArrayHeader* obj, KInt index) {
extern "C" { extern "C" {
#endif #endif
KString TheEmptyString(); // RuntimeUtils.kt.
OBJ_GETTER0(TheEmptyString);
// Any.kt // Any.kt
KBoolean Kotlin_Any_equals(KConstRef thiz, KConstRef other); KBoolean Kotlin_Any_equals(KConstRef thiz, KConstRef other);
KInt Kotlin_Any_hashCode(KConstRef thiz); KInt Kotlin_Any_hashCode(KConstRef thiz);
KString Kotlin_Any_toString(KConstRef thiz); OBJ_GETTER(Kotlin_Any_toString, KConstRef thiz);
// Arrays.kt // Arrays.kt
// TODO: those must be compiler intrinsics afterwards. // TODO: those must be compiler intrinsics afterwards.
KRef Kotlin_Array_clone(KConstRef thiz); OBJ_GETTER(Kotlin_Array_clone, KConstRef thiz);
KRef Kotlin_Array_get(KConstRef thiz, KInt index); OBJ_GETTER(Kotlin_Array_get, KConstRef thiz, KInt index);
void Kotlin_Array_set(KRef thiz, KInt index, KConstRef value); void Kotlin_Array_set(KRef thiz, KInt index, KConstRef value);
KInt Kotlin_Array_getArrayLength(KConstRef thiz); KInt Kotlin_Array_getArrayLength(KConstRef thiz);
KRef Kotlin_ByteArray_clone(KConstRef thiz); OBJ_GETTER(Kotlin_ByteArray_clone, KConstRef thiz);
KByte Kotlin_ByteArray_get(KConstRef thiz, KInt index); KByte Kotlin_ByteArray_get(KConstRef thiz, KInt index);
void Kotlin_ByteArray_set(KRef thiz, KInt index, KByte value); void Kotlin_ByteArray_set(KRef thiz, KInt index, KByte value);
KInt Kotlin_ByteArray_getArrayLength(KConstRef thiz); KInt Kotlin_ByteArray_getArrayLength(KConstRef thiz);
KRef Kotlin_CharArray_clone(KConstRef thiz); OBJ_GETTER(Kotlin_CharArray_clone, KConstRef thiz);
KChar Kotlin_CharArray_get(KConstRef thiz, KInt index); KChar Kotlin_CharArray_get(KConstRef thiz, KInt index);
void Kotlin_CharArray_set(KRef thiz, KInt index, KChar value); void Kotlin_CharArray_set(KRef thiz, KInt index, KChar value);
KInt Kotlin_CharArray_getArrayLength(KConstRef thiz); KInt Kotlin_CharArray_getArrayLength(KConstRef thiz);
KRef Kotlin_IntArray_clone(KConstRef thiz); OBJ_GETTER(Kotlin_IntArray_clone, KConstRef thiz);
KInt Kotlin_IntArray_get(KConstRef thiz, KInt index); KInt Kotlin_IntArray_get(KConstRef thiz, KInt index);
void Kotlin_IntArray_set(KRef thiz, KInt index, KInt value); void Kotlin_IntArray_set(KRef thiz, KInt index, KInt value);
KInt Kotlin_IntArray_getArrayLength(KConstRef thiz); KInt Kotlin_IntArray_getArrayLength(KConstRef thiz);
@@ -82,25 +83,25 @@ KInt Kotlin_IntArray_getArrayLength(KConstRef thiz);
void Kotlin_io_Console_print(KString message); void Kotlin_io_Console_print(KString message);
void Kotlin_io_Console_println(KString message); void Kotlin_io_Console_println(KString message);
void Kotlin_io_Console_println0(); void Kotlin_io_Console_println0();
KString Kotlin_io_Console_readLine(); OBJ_GETTER0(Kotlin_io_Console_readLine);
// Primitives.kt. // Primitives.kt.
KString Kotlin_Int_toString(KInt value); OBJ_GETTER(Kotlin_Int_toString, KInt value);
// String.kt // String.kt
KInt Kotlin_String_hashCode(KString thiz); KInt Kotlin_String_hashCode(KString thiz);
KBoolean Kotlin_String_equals(KString thiz, KConstRef other); KBoolean Kotlin_String_equals(KString thiz, KConstRef other);
KInt Kotlin_String_compareTo(KString thiz, KString other); KInt Kotlin_String_compareTo(KString thiz, KString other);
KChar Kotlin_String_get(KString thiz, KInt index); KChar Kotlin_String_get(KString thiz, KInt index);
KString Kotlin_String_fromUtf8Array(KConstRef array, KInt start, KInt size); OBJ_GETTER(Kotlin_String_fromUtf8Array, KConstRef array, KInt start, KInt size);
KString Kotlin_String_fromCharArray(KConstRef array, KInt start, KInt size); OBJ_GETTER(Kotlin_String_fromCharArray, KConstRef array, KInt start, KInt size);
KString Kotlin_String_plusImpl(KString thiz, KString other); OBJ_GETTER(Kotlin_String_plusImpl, KString thiz, KString other);
KInt Kotlin_String_getStringLength(KString thiz); KInt Kotlin_String_getStringLength(KString thiz);
KString Kotlin_String_subSequence(KString thiz, KInt startIndex, KInt endIndex); OBJ_GETTER(Kotlin_String_subSequence, KString thiz, KInt startIndex, KInt endIndex);
KConstRef Kotlin_getCurrentStackTrace(); OBJ_GETTER0(Kotlin_getCurrentStackTrace);
KRef Kotlin_konan_internal_undefined(); OBJ_GETTER0(Kotlin_konan_internal_undefined);
#ifdef __cplusplus #ifdef __cplusplus
} }
+18 -18
View File
@@ -9,7 +9,7 @@
namespace { namespace {
KString makeString(const char* cstring) { OBJ_GETTER(makeString, const char* cstring) {
uint32_t length = strlen(cstring); uint32_t length = strlen(cstring);
ArrayHeader* result = ArrayContainer( ArrayHeader* result = ArrayContainer(
theStringTypeInfo, length).GetPlace(); theStringTypeInfo, length).GetPlace();
@@ -17,59 +17,59 @@ KString makeString(const char* cstring) {
ByteArrayAddressOfElementAt(result, 0), ByteArrayAddressOfElementAt(result, 0),
cstring, cstring,
length); length);
return result; RETURN_OBJ(result->obj());
} }
} // namespace } // namespace
extern "C" { extern "C" {
KString Kotlin_Byte_toString(KByte value) { OBJ_GETTER(Kotlin_Byte_toString, KByte value) {
char cstring[8]; char cstring[8];
snprintf(cstring, sizeof(cstring), "%d", value); snprintf(cstring, sizeof(cstring), "%d", value);
return makeString(cstring); RETURN_RESULT_OF(makeString, cstring);
} }
KString Kotlin_Char_toString(KChar value) { OBJ_GETTER(Kotlin_Char_toString, KChar value) {
char cstring[5]; char cstring[5];
// TODO: support UTF-8. // TODO: support UTF-8.
snprintf(cstring, sizeof(cstring), "%c", value); snprintf(cstring, sizeof(cstring), "%c", value);
return makeString(cstring); RETURN_RESULT_OF(makeString, cstring);
} }
KString Kotlin_Short_toString(KShort value) { OBJ_GETTER(Kotlin_Short_toString, KShort value) {
char cstring[8]; char cstring[8];
snprintf(cstring, sizeof(cstring), "%d", value); snprintf(cstring, sizeof(cstring), "%d", value);
return makeString(cstring); RETURN_RESULT_OF(makeString, cstring);
} }
KString Kotlin_Int_toString(KInt value) { OBJ_GETTER(Kotlin_Int_toString, KInt value) {
char cstring[16]; char cstring[16];
snprintf(cstring, sizeof(cstring), "%d", value); snprintf(cstring, sizeof(cstring), "%d", value);
return makeString(cstring); RETURN_RESULT_OF(makeString, cstring);
} }
KString Kotlin_Long_toString(KLong value) { OBJ_GETTER(Kotlin_Long_toString, KLong value) {
char cstring[32]; char cstring[32];
snprintf(cstring, sizeof(cstring), "%lld", static_cast<long long>(value)); snprintf(cstring, sizeof(cstring), "%lld", static_cast<long long>(value));
return makeString(cstring); RETURN_RESULT_OF(makeString, cstring);
} }
// TODO: use David Gay's dtoa() here instead. It's *very* big and ugly. // TODO: use David Gay's dtoa() here instead. It's *very* big and ugly.
KString Kotlin_Float_toString(KFloat value) { OBJ_GETTER(Kotlin_Float_toString, KFloat value) {
char cstring[32]; char cstring[32];
snprintf(cstring, sizeof(cstring), "%G", value); snprintf(cstring, sizeof(cstring), "%G", value);
return makeString(cstring); RETURN_RESULT_OF(makeString, cstring);
} }
KString Kotlin_Double_toString(KDouble value) { OBJ_GETTER(Kotlin_Double_toString, KDouble value) {
char cstring[32]; char cstring[32];
snprintf(cstring, sizeof(cstring), "%G", value); snprintf(cstring, sizeof(cstring), "%G", value);
return makeString(cstring); RETURN_RESULT_OF(makeString, cstring);
} }
KString Kotlin_Boolean_toString(KBoolean value) { OBJ_GETTER(Kotlin_Boolean_toString, KBoolean value) {
return makeString(value ? "true" : "false"); RETURN_RESULT_OF(makeString, value ? "true" : "false");
} }
} // extern "C" } // extern "C"