Lazy stacktrace (#2036)
* stringify stacktrace lazily * Introduce NativePtrArray * Added Throwable::getStackTrace
This commit is contained in:
+2
-1
@@ -97,7 +97,8 @@ internal val arrayTypes = setOf(
|
||||
"kotlin.FloatArray",
|
||||
"kotlin.DoubleArray",
|
||||
"kotlin.BooleanArray",
|
||||
"kotlin.native.ImmutableBlob"
|
||||
"kotlin.native.ImmutableBlob",
|
||||
"kotlin.native.internal.NativePtrArray"
|
||||
)
|
||||
|
||||
|
||||
|
||||
+2
-1
@@ -109,7 +109,8 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
"kotlin.DoubleArray" to LLVMDoubleType()!!,
|
||||
"kotlin.BooleanArray" to LLVMInt8Type()!!,
|
||||
"kotlin.String" to LLVMInt16Type()!!,
|
||||
"kotlin.native.ImmutableBlob" to LLVMInt8Type()!!
|
||||
"kotlin.native.ImmutableBlob" to LLVMInt8Type()!!,
|
||||
"kotlin.native.internal.NativePtrArray" to kInt8Ptr
|
||||
)
|
||||
|
||||
// Keep in sync with Konan_RuntimeType.
|
||||
|
||||
@@ -48,6 +48,26 @@ inline void copyImpl(KConstRef thiz, KInt fromIndex,
|
||||
count * sizeof(T));
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
inline void PrimitiveArraySet(KRef thiz, KInt index, T value) {
|
||||
ArrayHeader* array = thiz->array();
|
||||
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
mutabilityCheck(thiz);
|
||||
*PrimitiveArrayAddressOfElementAt<T>(array, index) = value;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T PrimitiveArrayGet(KConstRef thiz, KInt index) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
return *PrimitiveArrayAddressOfElementAt<T>(array, index);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
@@ -278,20 +298,11 @@ void Kotlin_ByteArray_setDoubleAt(KRef thiz, KInt index, KDouble value) {
|
||||
}
|
||||
|
||||
KChar Kotlin_CharArray_get(KConstRef thiz, KInt index) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
return *PrimitiveArrayAddressOfElementAt<KChar>(array, index);
|
||||
return PrimitiveArrayGet<KChar>(thiz, index);
|
||||
}
|
||||
|
||||
void Kotlin_CharArray_set(KRef thiz, KInt index, KChar value) {
|
||||
ArrayHeader* array = thiz->array();
|
||||
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
mutabilityCheck(thiz);
|
||||
*PrimitiveArrayAddressOfElementAt<KChar>(array, index) = value;
|
||||
PrimitiveArraySet(thiz, index, value);
|
||||
}
|
||||
|
||||
OBJ_GETTER(Kotlin_CharArray_copyOf, KConstRef thiz, KInt newSize) {
|
||||
@@ -315,20 +326,11 @@ KInt Kotlin_CharArray_getArrayLength(KConstRef thiz) {
|
||||
}
|
||||
|
||||
KShort Kotlin_ShortArray_get(KConstRef thiz, KInt index) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
return *PrimitiveArrayAddressOfElementAt<KShort>(array, index);
|
||||
return PrimitiveArrayGet<KShort>(thiz, index);
|
||||
}
|
||||
|
||||
void Kotlin_ShortArray_set(KRef thiz, KInt index, KShort value) {
|
||||
ArrayHeader* array = thiz->array();
|
||||
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
mutabilityCheck(thiz);
|
||||
*PrimitiveArrayAddressOfElementAt<KShort>(array, index) = value;
|
||||
PrimitiveArraySet(thiz, index, value);
|
||||
}
|
||||
|
||||
KInt Kotlin_ShortArray_getArrayLength(KConstRef thiz) {
|
||||
@@ -337,20 +339,11 @@ KInt Kotlin_ShortArray_getArrayLength(KConstRef thiz) {
|
||||
}
|
||||
|
||||
KInt Kotlin_IntArray_get(KConstRef thiz, KInt index) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
return *PrimitiveArrayAddressOfElementAt<KInt>(array, index);
|
||||
return PrimitiveArrayGet<KInt>(thiz, index);
|
||||
}
|
||||
|
||||
void Kotlin_IntArray_set(KRef thiz, KInt index, KInt value) {
|
||||
ArrayHeader* array = thiz->array();
|
||||
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
mutabilityCheck(thiz);
|
||||
*PrimitiveArrayAddressOfElementAt<KInt>(array, index) = value;
|
||||
PrimitiveArraySet(thiz, index, value);
|
||||
}
|
||||
|
||||
KInt Kotlin_IntArray_getArrayLength(KConstRef thiz) {
|
||||
@@ -410,21 +403,11 @@ void Kotlin_BooleanArray_copyImpl(KConstRef thiz, KInt fromIndex,
|
||||
}
|
||||
|
||||
KLong Kotlin_LongArray_get(KConstRef thiz, KInt index) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
return *PrimitiveArrayAddressOfElementAt<KLong>(array, index);
|
||||
return PrimitiveArrayGet<KLong>(thiz, index);
|
||||
}
|
||||
|
||||
void Kotlin_LongArray_set(KRef thiz, KInt index, KLong value) {
|
||||
ArrayHeader* array = thiz->array();
|
||||
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
mutabilityCheck(thiz);
|
||||
*PrimitiveArrayAddressOfElementAt<KLong>(array, index) = value;
|
||||
PrimitiveArraySet(thiz, index, value);
|
||||
}
|
||||
|
||||
KInt Kotlin_LongArray_getArrayLength(KConstRef thiz) {
|
||||
@@ -433,20 +416,11 @@ KInt Kotlin_LongArray_getArrayLength(KConstRef thiz) {
|
||||
}
|
||||
|
||||
KFloat Kotlin_FloatArray_get(KConstRef thiz, KInt index) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
return *PrimitiveArrayAddressOfElementAt<KFloat>(array, index);
|
||||
return PrimitiveArrayGet<KFloat>(thiz, index);
|
||||
}
|
||||
|
||||
void Kotlin_FloatArray_set(KRef thiz, KInt index, KFloat value) {
|
||||
ArrayHeader* array = thiz->array();
|
||||
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
mutabilityCheck(thiz);
|
||||
*PrimitiveArrayAddressOfElementAt<KFloat>(array, index) = value;
|
||||
PrimitiveArraySet(thiz, index, value);
|
||||
}
|
||||
|
||||
KInt Kotlin_FloatArray_getArrayLength(KConstRef thiz) {
|
||||
@@ -455,20 +429,11 @@ KInt Kotlin_FloatArray_getArrayLength(KConstRef thiz) {
|
||||
}
|
||||
|
||||
KDouble Kotlin_DoubleArray_get(KConstRef thiz, KInt index) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
return *PrimitiveArrayAddressOfElementAt<KDouble>(array, index);
|
||||
return PrimitiveArrayGet<KDouble>(thiz, index);
|
||||
}
|
||||
|
||||
void Kotlin_DoubleArray_set(KRef thiz, KInt index, KDouble value) {
|
||||
ArrayHeader* array = thiz->array();
|
||||
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
mutabilityCheck(thiz);
|
||||
*PrimitiveArrayAddressOfElementAt<KDouble>(array, index) = value;
|
||||
PrimitiveArraySet(thiz, index, value);
|
||||
}
|
||||
|
||||
KInt Kotlin_DoubleArray_getArrayLength(KConstRef thiz) {
|
||||
@@ -477,20 +442,11 @@ KInt Kotlin_DoubleArray_getArrayLength(KConstRef thiz) {
|
||||
}
|
||||
|
||||
KBoolean Kotlin_BooleanArray_get(KConstRef thiz, KInt index) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
return *PrimitiveArrayAddressOfElementAt<KBoolean>(array, index);
|
||||
return PrimitiveArrayGet<KBoolean>(thiz, index);
|
||||
}
|
||||
|
||||
void Kotlin_BooleanArray_set(KRef thiz, KInt index, KBoolean value) {
|
||||
ArrayHeader* array = thiz->array();
|
||||
if (static_cast<uint32_t>(index) >= array->count_) {
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
mutabilityCheck(thiz);
|
||||
*PrimitiveArrayAddressOfElementAt<KBoolean>(array, index) = value;
|
||||
PrimitiveArraySet(thiz, index, value);
|
||||
}
|
||||
|
||||
KInt Kotlin_BooleanArray_getArrayLength(KConstRef thiz) {
|
||||
@@ -498,6 +454,19 @@ KInt Kotlin_BooleanArray_getArrayLength(KConstRef thiz) {
|
||||
return array->count_;
|
||||
}
|
||||
|
||||
KNativePtr Kotlin_NativePtrArray_get(KConstRef thiz, KInt index) {
|
||||
return PrimitiveArrayGet<KNativePtr>(thiz, index);
|
||||
}
|
||||
|
||||
void Kotlin_NativePtrArray_set(KRef thiz, KInt index, KNativePtr value) {
|
||||
PrimitiveArraySet(thiz, index, value);
|
||||
}
|
||||
|
||||
KInt Kotlin_NativePtrArray_getArrayLength(KConstRef thiz) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
return array->count_;
|
||||
}
|
||||
|
||||
OBJ_GETTER(Kotlin_ImmutableBlob_toByteArray, KConstRef thiz, KInt start, KInt count) {
|
||||
const ArrayHeader* array = thiz->array();
|
||||
if (start < 0 || count < 0 || start > array->count_ - count) {
|
||||
|
||||
@@ -60,17 +60,17 @@ class AutoFree {
|
||||
#if USE_GCC_UNWIND
|
||||
struct Backtrace {
|
||||
Backtrace(int count, int skip) : index(0), skipCount(skip) {
|
||||
auto result = AllocArrayInstance(
|
||||
theArrayTypeInfo, count - skipCount, arrayHolder.slot());
|
||||
uint32_t size = count - skipCount;
|
||||
if (size < 0) {
|
||||
size = 0;
|
||||
}
|
||||
auto result = AllocArrayInstance(theNativePtrArrayTypeInfo, size, arrayHolder.slot());
|
||||
// TODO: throw cached OOME?
|
||||
RuntimeCheck(result != nullptr, "Cannot create backtrace array");
|
||||
}
|
||||
|
||||
void setNextElement(const char* element) {
|
||||
auto result = CreateStringFromCString(
|
||||
element, ArrayAddressOfElementAt(obj()->array(), index++));
|
||||
// TODO: throw cached OOME?
|
||||
RuntimeCheck(result != nullptr, "Cannot create backtrace array element");
|
||||
void setNextElement(_Unwind_Ptr element) {
|
||||
Kotlin_NativePtrArray_set(obj(), index++, (KNativePtr) element);
|
||||
}
|
||||
|
||||
ObjHeader* obj() { return arrayHolder.obj(); }
|
||||
@@ -100,17 +100,8 @@ _Unwind_Reason_Code unwindCallback(
|
||||
#else
|
||||
_Unwind_Ptr address = _Unwind_GetIP(context);
|
||||
#endif
|
||||
backtrace->setNextElement(address);
|
||||
|
||||
char symbol[512];
|
||||
if (!AddressToSymbol((const void*)address, symbol, sizeof(symbol))) {
|
||||
// Make empty string:
|
||||
symbol[0] = '\0';
|
||||
}
|
||||
|
||||
char line[512];
|
||||
konan::snprintf(line, sizeof(line) - 1, "%s (%p)",
|
||||
symbol, (void*)(intptr_t)address);
|
||||
backtrace->setNextElement(line);
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
#endif
|
||||
@@ -123,44 +114,71 @@ extern "C" {
|
||||
// however it is better to have an inexact stacktrace than not to have any.
|
||||
OBJ_GETTER0(GetCurrentStackTrace) {
|
||||
#if OMIT_BACKTRACE
|
||||
ObjHeader* result = AllocArrayInstance(theArrayTypeInfo, 1, OBJ_RESULT);
|
||||
ArrayHeader* array = result->array();
|
||||
CreateStringFromCString("<UNIMPLEMENTED>", ArrayAddressOfElementAt(array, 0));
|
||||
return result;
|
||||
return AllocArrayInstance(theNativePtrArrayTypeInfo, 0, OBJ_RESULT);
|
||||
#else
|
||||
// Skips first 3 elements as irrelevant.
|
||||
constexpr int kSkipFrames = 3;
|
||||
#if USE_GCC_UNWIND
|
||||
int depth = 0;
|
||||
_Unwind_Backtrace(depthCountCallback, &depth);
|
||||
if (depth < kSkipFrames)
|
||||
return AllocArrayInstance(theArrayTypeInfo, 0, OBJ_RESULT);
|
||||
Backtrace result(depth, kSkipFrames);
|
||||
_Unwind_Backtrace(unwindCallback, &result);
|
||||
if (result.obj()->array()->count_ > 0) {
|
||||
_Unwind_Backtrace(unwindCallback, &result);
|
||||
}
|
||||
RETURN_OBJ(result.obj());
|
||||
#else
|
||||
const int maxSize = 32;
|
||||
void* buffer[maxSize];
|
||||
|
||||
int size = backtrace(buffer, maxSize);
|
||||
char** symbols = backtrace_symbols(buffer, size);
|
||||
RuntimeCheck(symbols != nullptr, "Not enough memory to retrieve the stacktrace");
|
||||
if (size < kSkipFrames)
|
||||
return AllocArrayInstance(theArrayTypeInfo, 0, OBJ_RESULT);
|
||||
AutoFree autoFree(symbols);
|
||||
return AllocArrayInstance(theNativePtrArrayTypeInfo, 0, OBJ_RESULT);
|
||||
|
||||
ObjHolder resultHolder;
|
||||
ObjHeader* result = AllocArrayInstance(
|
||||
theArrayTypeInfo, size - kSkipFrames, resultHolder.slot());
|
||||
ArrayHeader* array = result->array();
|
||||
ObjHeader* result = AllocArrayInstance(theNativePtrArrayTypeInfo, size - kSkipFrames, resultHolder.slot());
|
||||
for (int index = kSkipFrames; index < size; ++index) {
|
||||
CreateStringFromCString(
|
||||
symbols[index], ArrayAddressOfElementAt(array, index - kSkipFrames));
|
||||
Kotlin_NativePtrArray_set(result, index - kSkipFrames, buffer[index]);
|
||||
}
|
||||
RETURN_OBJ(result);
|
||||
#endif
|
||||
#endif // !OMIT_BACKTRACE
|
||||
}
|
||||
|
||||
OBJ_GETTER(GetStackTraceStrings, KConstRef stackTrace) {
|
||||
#if OMIT_BACKTRACE
|
||||
ObjHeader* result = AllocArrayInstance(theArrayTypeInfo, 1, OBJ_RESULT);
|
||||
CreateStringFromCString("<UNIMPLEMENTED>", ArrayAddressOfElementAt(result->array(), 0));
|
||||
return result;
|
||||
#else
|
||||
uint32_t size = stackTrace->array()->count_;
|
||||
ObjHolder resultHolder;
|
||||
ObjHeader* strings = AllocArrayInstance(theArrayTypeInfo, size, resultHolder.slot());
|
||||
#if USE_GCC_UNWIND
|
||||
for (int index = 0; index < size; ++index) {
|
||||
KNativePtr address = Kotlin_NativePtrArray_get(stackTrace, index);
|
||||
char symbol[512];
|
||||
if (!AddressToSymbol((const void*) address, symbol, sizeof(symbol))) {
|
||||
// Make empty string:
|
||||
symbol[0] = '\0';
|
||||
}
|
||||
char line[512];
|
||||
konan::snprintf(line, sizeof(line) - 1, "%s (%p)", symbol, (void*)(intptr_t)address);
|
||||
CreateStringFromCString(line, ArrayAddressOfElementAt(strings->array(), index));
|
||||
}
|
||||
#else
|
||||
if (size > 0) {
|
||||
char **symbols = backtrace_symbols(PrimitiveArrayAddressOfElementAt<KNativePtr>(stackTrace->array(), 0), size);
|
||||
RuntimeCheck(symbols != nullptr, "Not enough memory to retrieve the stacktrace");
|
||||
AutoFree autoFree(symbols);
|
||||
for (int index = 0; index < size; ++index) {
|
||||
CreateStringFromCString(symbols[index], ArrayAddressOfElementAt(strings->array(), index));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
RETURN_OBJ(strings);
|
||||
#endif // !OMIT_BACKTRACE
|
||||
}
|
||||
|
||||
void ThrowException(KRef exception) {
|
||||
RuntimeAssert(exception != nullptr && IsInstance(exception, theThrowableTypeInfo),
|
||||
"Throwing something non-throwable");
|
||||
|
||||
@@ -26,6 +26,8 @@ extern "C" {
|
||||
// Returns current stacktrace as Array<String>.
|
||||
OBJ_GETTER0(GetCurrentStackTrace);
|
||||
|
||||
OBJ_GETTER(GetStackTraceStrings, KConstRef stackTrace);
|
||||
|
||||
// Throws arbitrary exception.
|
||||
void ThrowException(KRef exception);
|
||||
|
||||
|
||||
@@ -43,6 +43,10 @@ OBJ_GETTER0(Kotlin_getCurrentStackTrace) {
|
||||
RETURN_RESULT_OF0(GetCurrentStackTrace);
|
||||
}
|
||||
|
||||
OBJ_GETTER(Kotlin_getStackTraceStrings, KConstRef stackTrace) {
|
||||
RETURN_RESULT_OF(GetStackTraceStrings, stackTrace);
|
||||
}
|
||||
|
||||
// TODO: consider handling it with compiler magic instead.
|
||||
OBJ_GETTER0(Kotlin_native_internal_undefined) {
|
||||
RETURN_OBJ(nullptr);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#define RUNTIME_NATIVES_H
|
||||
|
||||
#include "Types.h"
|
||||
#include "Exceptions.h"
|
||||
|
||||
inline void* AddressOfElementAt(ArrayHeader* obj, int32_t index) {
|
||||
// Instance size is negative.
|
||||
@@ -109,6 +110,13 @@ KInt Kotlin_IntArray_get(KConstRef thiz, KInt index);
|
||||
void Kotlin_IntArray_set(KRef thiz, KInt index, KInt value);
|
||||
KInt Kotlin_IntArray_getArrayLength(KConstRef thiz);
|
||||
|
||||
KLong Kotlin_LongArray_get(KConstRef thiz, KInt index);
|
||||
void Kotlin_LongArray_set(KRef thiz, KInt index, KLong value);
|
||||
|
||||
KNativePtr Kotlin_NativePtrArray_get(KConstRef thiz, KInt index);
|
||||
void Kotlin_NativePtrArray_set(KRef thiz, KInt index, KNativePtr value);
|
||||
KInt Kotlin_NativePtrArray_getArrayLength(KConstRef thiz);
|
||||
|
||||
// io/Console.kt
|
||||
void Kotlin_io_Console_print(KString message);
|
||||
void Kotlin_io_Console_println(KString message);
|
||||
@@ -132,6 +140,8 @@ OBJ_GETTER(Kotlin_String_subSequence, KString thiz, KInt startIndex, KInt endInd
|
||||
|
||||
OBJ_GETTER0(Kotlin_getCurrentStackTrace);
|
||||
|
||||
OBJ_GETTER(Kotlin_getStackTraceStrings, KConstRef stackTrace);
|
||||
|
||||
OBJ_GETTER0(Kotlin_native_internal_undefined);
|
||||
|
||||
void Kotlin_native_internal_GC_suspend(KRef);
|
||||
|
||||
@@ -91,6 +91,7 @@ extern const TypeInfo* theThrowableTypeInfo;
|
||||
extern const TypeInfo* theUnitTypeInfo;
|
||||
extern const TypeInfo* theForeignObjCObjectTypeInfo;
|
||||
extern const TypeInfo* theObjCObjectWrapperTypeInfo;
|
||||
extern const TypeInfo* theNativePtrArrayTypeInfo;
|
||||
|
||||
KBoolean IsInstance(const ObjHeader* obj, const TypeInfo* type_info) RUNTIME_PURE;
|
||||
void CheckCast(const ObjHeader* obj, const TypeInfo* type_info);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package kotlin
|
||||
|
||||
import kotlin.native.internal.ExportTypeInfo
|
||||
import kotlin.native.internal.NativePtrArray
|
||||
|
||||
/**
|
||||
* The base class for all errors and exceptions. Only instances of this class can be thrown or caught.
|
||||
@@ -22,11 +23,18 @@ public open class Throwable(open val message: String?, open val cause: Throwable
|
||||
|
||||
constructor() : this(null, null)
|
||||
|
||||
private val stacktrace: Array<String> = getCurrentStackTrace()
|
||||
private val stackTrace = getCurrentStackTrace()
|
||||
|
||||
private val stackTraceStrings: Array<String> by lazy {
|
||||
getStackTraceStrings(stackTrace)
|
||||
}
|
||||
|
||||
fun getStackTrace(): Array<String> = stackTraceStrings
|
||||
|
||||
fun printStackTrace() {
|
||||
println(this.toString())
|
||||
for (element in stacktrace) {
|
||||
|
||||
for (element in stackTraceStrings) {
|
||||
println(" at " + element)
|
||||
}
|
||||
|
||||
@@ -48,4 +56,7 @@ public open class Throwable(open val message: String?, open val cause: Throwable
|
||||
}
|
||||
|
||||
@SymbolName("Kotlin_getCurrentStackTrace")
|
||||
private external fun getCurrentStackTrace(): Array<String>
|
||||
private external fun getCurrentStackTrace(): NativePtrArray
|
||||
|
||||
@SymbolName("Kotlin_getStackTraceStrings")
|
||||
private external fun getStackTraceStrings(stackTrace: NativePtrArray): Array<String>
|
||||
@@ -36,3 +36,16 @@ internal inline class NonNullNativePtr(val value: NotNullPointerValue) { // TODO
|
||||
|
||||
override fun equals(other: Any?) = false
|
||||
}
|
||||
|
||||
@ExportTypeInfo("theNativePtrArrayTypeInfo")
|
||||
internal class NativePtrArray {
|
||||
|
||||
@SymbolName("Kotlin_NativePtrArray_get")
|
||||
external public operator fun get(index: Int): NativePtr
|
||||
|
||||
@SymbolName("Kotlin_NativePtrArray_set")
|
||||
external public operator fun set(index: Int, value: NativePtr): Unit
|
||||
|
||||
@SymbolName("Kotlin_NativePtrArray_getArrayLength")
|
||||
external private fun getArrayLength(): Int
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user