diff --git a/runtime/src/main/cpp/Exceptions.cpp b/runtime/src/main/cpp/Exceptions.cpp index f0703ed881f..9f1e7693d8c 100644 --- a/runtime/src/main/cpp/Exceptions.cpp +++ b/runtime/src/main/cpp/Exceptions.cpp @@ -22,7 +22,7 @@ // GCC unwinder for backtrace. #include #else -// Glibc backtrace function. +// Glibc backtrace() function. #include #endif #endif // OMIT_BACKTRACE @@ -37,20 +37,6 @@ namespace { -class KotlinException { - public: - - KRef exception_; - - KotlinException(KRef exception) : exception_(exception) { - ::AddRef(exception_->container()); - }; - - ~KotlinException() { - ::Release(exception_->container()); - }; -}; - // TODO: it seems to be very common case; does C++ std library provide something like this? class AutoFree { private: @@ -66,20 +52,25 @@ class AutoFree { #if USE_GCC_UNWIND struct Backtrace { - Backtrace(int count, int skip) : index(0), skipCount(skip), array(nullptr) { + Backtrace(int count, int skip) : index(0), skipCount(skip) { auto result = AllocArrayInstance( - theArrayTypeInfo, count - skipCount, &array); + theArrayTypeInfo, count - skipCount, arrayHolder.slot()); + // TODO: throw cached OOME? RuntimeAssert(result != nullptr, "Cannot create backtrace array"); } void setNextElement(const char* element) { - CreateStringFromCString( - element, ArrayAddressOfElementAt(array->array(), index++)); + auto result = CreateStringFromCString( + element, ArrayAddressOfElementAt(obj()->array(), index++)); + // TODO: throw cached OOME? + RuntimeAssert(result != nullptr, "Cannot create backtrace array element"); } + ObjHeader* obj() { return arrayHolder.obj(); } + int index; int skipCount; - ObjHeader* array; + ObjHolder arrayHolder; }; _Unwind_Reason_Code depthCountCallback( @@ -132,13 +123,15 @@ OBJ_GETTER0(GetCurrentStackTrace) { CreateStringFromCString("", ArrayAddressOfElementAt(array, 0)); return result; #else + // Skips first 3 elements as irrelevant. + constexpr int kSkipFrames = 3; #if USE_GCC_UNWIND int depth = 0; _Unwind_Backtrace(depthCountCallback, &depth); - // Skips first 3 elements as irrelevant. - Backtrace result(depth, 3); + if (depth < kSkipFrames) RETURN_OBJ(nullptr); + Backtrace result(depth, kSkipFrames); _Unwind_Backtrace(unwindCallback, &result); - RETURN_OBJ(result.array); + RETURN_OBJ(result.obj()); #else const int maxSize = 32; void* buffer[maxSize]; @@ -146,15 +139,17 @@ OBJ_GETTER0(GetCurrentStackTrace) { int size = backtrace(buffer, maxSize); char** symbols = backtrace_symbols(buffer, size); RuntimeAssert(symbols != nullptr, "Not enough memory to retrieve the stacktrace"); - + if (size < kSkipFrames) RETURN_OBJ(nullptr); AutoFree autoFree(symbols); - ObjHeader* result = AllocArrayInstance(theArrayTypeInfo, size, OBJ_RESULT); + ObjHolder resultHolder; + ObjHeader* result = AllocArrayInstance( + theArrayTypeInfo, size - kSkipFrames, resultHolder.slot()); ArrayHeader* array = result->array(); - for (int index = 0; index < size; ++index) { + for (int index = kSkipFrames; index < size; ++index) { CreateStringFromCString( - symbols[index], ArrayAddressOfElementAt(array, index)); + symbols[index], ArrayAddressOfElementAt(array, index - kSkipFrames)); } - return result; + RETURN_OBJ(result); #endif #endif // !OMIT_BACKTRACE } @@ -162,7 +157,7 @@ OBJ_GETTER0(GetCurrentStackTrace) { void ThrowException(KRef exception) { RuntimeAssert(exception != nullptr && IsInstance(exception, theThrowableTypeInfo), "Throwing something non-throwable"); - throw KotlinException(exception); + throw ObjHolder(exception); }