Interop/Indexer: simplify native memory management by using memScoped

This commit is contained in:
Svyatoslav Scherbina
2017-02-16 13:25:44 +07:00
committed by SvyatoslavScherbina
parent a52a51b7fa
commit 53b347b75a
@@ -22,10 +22,6 @@ private class EnumDefImpl(spelling: String, type: PrimitiveType) : EnumDef(spell
private class NativeIndexImpl : NativeIndex() { private class NativeIndexImpl : NativeIndex() {
val arena = Arena()
fun clearNativeMem() = arena.clear()
private data class DeclarationID(val usr: String) private data class DeclarationID(val usr: String)
val structById = mutableMapOf<DeclarationID, StructDeclImpl>() val structById = mutableMapOf<DeclarationID, StructDeclImpl>()
@@ -48,33 +44,22 @@ private class NativeIndexImpl : NativeIndex() {
override val functions: List<FunctionDecl> override val functions: List<FunctionDecl>
get() = functionByName.values.toList() get() = functionByName.values.toList()
fun getDeclarationId(cursor: CXCursor) = DeclarationID(clang_getCursorUSR(cursor, arena).convertAndDispose()) fun getDeclarationId(cursor: CXCursor): DeclarationID = memScoped {
val usr = clang_getCursorUSR(cursor, memScope).convertAndDispose()
fun getStructTypeDecl(type: CXType): StructDeclImpl { DeclarationID(usr)
assert (type.kind.value == CXType_Record)
return getStructDeclAt(clang_getTypeDeclaration(type, arena))
} }
fun getStructDeclAt(cursor: CXCursor): StructDeclImpl { fun getStructDeclAt(cursor: CXCursor): StructDeclImpl {
val declId = getDeclarationId(cursor) val declId = getDeclarationId(cursor)
val decl = structById[declId] return structById.getOrPut(declId) {
if (decl != null) { memScoped {
return decl val cursorType = clang_getCursorType(cursor, memScope)
val typeSpelling = clang_getTypeSpelling(cursorType, memScope).convertAndDispose()
StructDeclImpl(typeSpelling)
}
} }
val cursorType = clang_getCursorType(cursor, arena)
val typeSpelling = clang_getTypeSpelling(cursorType, arena).convertAndDispose()
val res = StructDeclImpl(typeSpelling)
structById[declId] = res
return res
}
fun getEnumTypeDef(type: CXType): EnumDefImpl {
assert (type.kind.value == CXType_Enum)
val declCursor = clang_getTypeDeclaration(type, arena)
return getEnumDefAt(declCursor)
} }
fun getEnumDefAt(cursor: CXCursor): EnumDefImpl { fun getEnumDefAt(cursor: CXCursor): EnumDefImpl {
@@ -84,19 +69,16 @@ private class NativeIndexImpl : NativeIndex() {
val declId = getDeclarationId(cursor) val declId = getDeclarationId(cursor)
val enum = enumById[declId] return enumById.getOrPut(declId) {
if (enum != null) { memScoped {
return enum val cursorType = clang_getCursorType(cursor, memScope)
val typeSpelling = clang_getTypeSpelling(cursorType, memScope).convertAndDispose()
val baseType = convertType(clang_getEnumDeclIntegerType(cursor, memScope)) as PrimitiveType
EnumDefImpl(typeSpelling, baseType)
}
} }
val cursorType = clang_getCursorType(cursor, arena)
val typeSpelling = clang_getTypeSpelling(cursorType, arena).convertAndDispose()
val baseType = convertType(clang_getEnumDeclIntegerType(cursor, arena)) as PrimitiveType
val res = EnumDefImpl(typeSpelling, baseType)
enumById[declId] = res
return res
} }
private fun builtinVaListType(type: CXType, name: String, underlying: Type): Type { private fun builtinVaListType(type: CXType, name: String, underlying: Type): Type {
@@ -117,11 +99,11 @@ private class NativeIndexImpl : NativeIndex() {
return ConstArrayType(RecordType(structDeclaration), 1) return ConstArrayType(RecordType(structDeclaration), 1)
} }
fun getTypedef(type: CXType): Type { fun getTypedef(type: CXType): Type = memScoped {
val declCursor = clang_getTypeDeclaration(type, arena) val declCursor = clang_getTypeDeclaration(type, memScope)
val name = clang_getCursorSpelling(declCursor, arena).convertAndDispose() val name = clang_getCursorSpelling(declCursor, memScope).convertAndDispose()
val underlying = convertType(clang_getTypedefDeclUnderlyingType(declCursor, arena)) val underlying = convertType(clang_getTypedefDeclUnderlyingType(declCursor, memScope))
if (name == "__builtin_va_list") { if (name == "__builtin_va_list") {
// On some platforms (e.g. macOS) libclang reports `__builtin_va_list` to be defined as array using // On some platforms (e.g. macOS) libclang reports `__builtin_va_list` to be defined as array using
@@ -160,8 +142,8 @@ private class NativeIndexImpl : NativeIndex() {
CXCursorKind.CXCursor_UnionDecl -> return false CXCursorKind.CXCursor_UnionDecl -> return false
CXCursorKind.CXCursor_StructDecl -> { CXCursorKind.CXCursor_StructDecl -> memScoped {
val hasAttributes = arena.alloc<CInt32Var>() val hasAttributes = memScope.alloc<CInt32Var>()
hasAttributes.value = 0 hasAttributes.value = 0
clang_visitChildren(structDefCursor, staticCFunction { cursor, parent, clientData -> clang_visitChildren(structDefCursor, staticCFunction { cursor, parent, clientData ->
if (clang_isAttribute(cursor.kind.value) != 0) { if (clang_isAttribute(cursor.kind.value) != 0) {
@@ -178,11 +160,11 @@ private class NativeIndexImpl : NativeIndex() {
} }
} }
fun convertType(type: CXType): Type { fun convertType(type: CXType): Type = memScoped {
val kind = type.kind.value val kind = type.kind.value
return when (kind) { return when (kind) {
CXType_Unexposed -> { CXType_Unexposed -> {
val canonicalType = clang_getCanonicalType(type, arena) val canonicalType = clang_getCanonicalType(type, memScope)
if (canonicalType.kind.value != CXType_Unexposed) { if (canonicalType.kind.value != CXType_Unexposed) {
convertType(canonicalType) convertType(canonicalType)
} else { } else {
@@ -210,19 +192,19 @@ private class NativeIndexImpl : NativeIndex() {
CXType_Typedef -> getTypedef(type) CXType_Typedef -> getTypedef(type)
CXType_Record -> RecordType(getStructTypeDecl(type)) CXType_Record -> RecordType(getStructDeclAt(clang_getTypeDeclaration(type, memScope)))
CXType_Enum -> EnumType(getEnumTypeDef(type)) CXType_Enum -> EnumType(getEnumDefAt(clang_getTypeDeclaration(type, memScope)))
CXType_Pointer -> PointerType(convertType(clang_getPointeeType(type, arena))) CXType_Pointer -> PointerType(convertType(clang_getPointeeType(type, memScope)))
CXType_ConstantArray -> { CXType_ConstantArray -> {
val elemType = convertType(clang_getArrayElementType(type, arena)) val elemType = convertType(clang_getArrayElementType(type, memScope))
val length = clang_getArraySize(type) val length = clang_getArraySize(type)
ConstArrayType(elemType, length) ConstArrayType(elemType, length)
} }
CXType_IncompleteArray -> { CXType_IncompleteArray -> {
val elemType = convertType(clang_getArrayElementType(type, arena)) val elemType = convertType(clang_getArrayElementType(type, memScope))
IncompleteArrayType(elemType) IncompleteArrayType(elemType)
} }
@@ -230,10 +212,10 @@ private class NativeIndexImpl : NativeIndex() {
if (clang_isFunctionTypeVariadic(type) != 0) { if (clang_isFunctionTypeVariadic(type) != 0) {
UnsupportedType UnsupportedType
} else { } else {
val returnType = convertType(clang_getResultType(type, arena)) val returnType = convertType(clang_getResultType(type, memScope))
val numArgs = clang_getNumArgTypes(type) val numArgs = clang_getNumArgTypes(type)
val paramTypes = (0..numArgs - 1).map { val paramTypes = (0..numArgs - 1).map {
convertType(clang_getArgType(type, it, arena)) convertType(clang_getArgType(type, it, memScope))
} }
FunctionType(paramTypes, returnType) FunctionType(paramTypes, returnType)
} }
@@ -243,7 +225,7 @@ private class NativeIndexImpl : NativeIndex() {
} }
} }
fun indexDeclaration(info: CXIdxDeclInfo) { fun indexDeclaration(info: CXIdxDeclInfo): Unit = memScoped {
val cursor = info.cursor val cursor = info.cursor
val entityInfo = info.entityInfo.pointed!! val entityInfo = info.entityInfo.pointed!!
val entityName = entityInfo.name.value?.asCString()?.toString() val entityName = entityInfo.name.value?.asCString()?.toString()
@@ -252,7 +234,7 @@ private class NativeIndexImpl : NativeIndex() {
when (kind) { when (kind) {
CXIdxEntity_Field -> { CXIdxEntity_Field -> {
val name = entityName!! val name = entityName!!
val type = convertType(clang_getCursorType(cursor, arena)) val type = convertType(clang_getCursorType(cursor, memScope))
val offset = clang_Cursor_getOffsetOfField(cursor) val offset = clang_Cursor_getOffsetOfField(cursor)
val container = info.semanticContainer.pointed!! val container = info.semanticContainer.pointed!!
@@ -263,9 +245,9 @@ private class NativeIndexImpl : NativeIndex() {
CXIdxEntity_Struct, CXIdxEntity_Union -> { CXIdxEntity_Struct, CXIdxEntity_Union -> {
val structDecl = getStructDeclAt(cursor) val structDecl = getStructDeclAt(cursor)
if (clang_isCursorDefinition(cursor) != 0) { if (clang_isCursorDefinition(cursor) != 0) {
val type = clang_getCursorType(cursor, arena) val type = clang_getCursorType(cursor, memScope)
val size = clang_Type_getSizeOf(type) val size = clang_Type_getSizeOf(type)
val align = clang_Type_getAlignOf(clang_getCursorType(cursor, arena)).toInt() val align = clang_Type_getAlignOf(clang_getCursorType(cursor, memScope)).toInt()
val hasNaturalLayout = structHasNaturalLayout(cursor) val hasNaturalLayout = structHasNaturalLayout(cursor)
structDecl.def = StructDefImpl(size, align, structDecl, hasNaturalLayout) structDecl.def = StructDefImpl(size, align, structDecl, hasNaturalLayout)
} }
@@ -273,12 +255,12 @@ private class NativeIndexImpl : NativeIndex() {
CXIdxEntity_Function -> { CXIdxEntity_Function -> {
val name = entityName!! val name = entityName!!
val returnType = convertType(clang_getCursorResultType(cursor, arena)) val returnType = convertType(clang_getCursorResultType(cursor, memScope))
val argNum = clang_Cursor_getNumArguments(cursor) val argNum = clang_Cursor_getNumArguments(cursor)
val args = (0 .. argNum - 1).map { val args = (0 .. argNum - 1).map {
val argCursor = clang_Cursor_getArgument(cursor, it, arena) val argCursor = clang_Cursor_getArgument(cursor, it, memScope)
val argName = clang_getCursorSpelling(argCursor, arena).convertAndDispose() val argName = clang_getCursorSpelling(argCursor, memScope).convertAndDispose()
val type = convertType(clang_getCursorType(argCursor, arena)) val type = convertType(clang_getCursorType(argCursor, memScope))
Parameter(argName, type) Parameter(argName, type)
} }
@@ -326,37 +308,33 @@ fun buildNativeIndexImpl(headerFile: File, args: List<String>): NativeIndex {
val callbacks = nativeHeap.alloc<IndexerCallbacks>() val callbacks = nativeHeap.alloc<IndexerCallbacks>()
val res = NativeIndexImpl() val res = NativeIndexImpl()
val nativeIndexPtr = StableObjPtr.create(res)
val clientData = nativeIndexPtr.value
try { try {
val nativeIndexPtr = StableObjPtr.create(res) with(callbacks) {
val clientData = nativeIndexPtr.value abortQuery.value = null
diagnostic.value = null
try { enteredMainFile.value = null
with(callbacks) { ppIncludedFile.value = null
abortQuery.value = null importedASTFile.value = null
diagnostic.value = null startedTranslationUnit.value = null
enteredMainFile.value = null indexDeclaration.value = staticCFunction { clientData, info ->
ppIncludedFile.value = null val nativeIndex = StableObjPtr.fromValue(clientData!!).get() as NativeIndexImpl
importedASTFile.value = null nativeIndex.indexDeclaration(info!!.pointed)
startedTranslationUnit.value = null
indexDeclaration.value = staticCFunction { clientData, info ->
val nativeIndex = StableObjPtr.fromValue(clientData!!).get() as NativeIndexImpl
nativeIndex.indexDeclaration(info!!.pointed)
}
indexEntityReference.value = null
} }
indexEntityReference.value = null
val commandLineArgs = nativeHeap.allocArrayOfPointersTo(*args1)[0].ptr
clang_indexSourceFile(indexAction, clientData, callbacks.ptr, IndexerCallbacks.size.toInt(),
0, headerFile.path, commandLineArgs, args1.size, null, 0, null, 0)
return res
} finally {
nativeIndexPtr.dispose()
} }
val commandLineArgs = nativeHeap.allocArrayOfPointersTo(*args1)[0].ptr
clang_indexSourceFile(indexAction, clientData, callbacks.ptr, IndexerCallbacks.size.toInt(),
0, headerFile.path, commandLineArgs, args1.size, null, 0, null, 0)
return res
} finally { } finally {
res.clearNativeMem() nativeIndexPtr.dispose()
} }
} }