Upgrade fbjni
Summary: Upgrades Yoga’s copy of *fbjni* to the latest version. This will enable us - to move from `finalize()` to `PhantomReference` to deallocate native memory, with the potential of making GC more efficient. - to remove the internal dependency to *libfb,* allowing apps without an own dependency to ship less code Reviewed By: passy Differential Revision: D16220924 fbshipit-source-id: e8233fe2b5403946ff51f43cb6def558ded52fda
This commit is contained in:
committed by
Facebook Github Bot
parent
be305b5d0f
commit
59d680f4e9
195
lib/fb/src/main/cpp/include/lyra/lyra.h
Normal file
195
lib/fb/src/main/cpp/include/lyra/lyra.h
Normal file
@@ -0,0 +1,195 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace facebook {
|
||||
namespace lyra {
|
||||
|
||||
constexpr size_t kDefaultLimit = 64;
|
||||
|
||||
using InstructionPointer = const void*;
|
||||
|
||||
class StackTraceElement {
|
||||
public:
|
||||
StackTraceElement(InstructionPointer absoluteProgramCounter,
|
||||
InstructionPointer libraryBase,
|
||||
InstructionPointer functionAddress,
|
||||
std::string libraryName,
|
||||
std::string functionName)
|
||||
: absoluteProgramCounter_{absoluteProgramCounter},
|
||||
libraryBase_{libraryBase},
|
||||
functionAddress_{functionAddress},
|
||||
libraryName_{std::move(libraryName)},
|
||||
functionName_{std::move(functionName)},
|
||||
hasBuildId_{false},
|
||||
buildId_{}
|
||||
{}
|
||||
|
||||
InstructionPointer libraryBase() const noexcept { return libraryBase_; }
|
||||
|
||||
InstructionPointer functionAddress() const noexcept {
|
||||
return functionAddress_;
|
||||
}
|
||||
|
||||
InstructionPointer absoluteProgramCounter() const noexcept {
|
||||
return absoluteProgramCounter_;
|
||||
}
|
||||
|
||||
const std::string& libraryName() const noexcept { return libraryName_; }
|
||||
|
||||
const std::string& functionName() const noexcept { return functionName_; }
|
||||
|
||||
/**
|
||||
* The offset of the program counter to the base of the library (i.e. the
|
||||
* address that addr2line takes as input>
|
||||
*/
|
||||
std::ptrdiff_t libraryOffset() const noexcept {
|
||||
auto absoluteLibrary = static_cast<const char*>(libraryBase_);
|
||||
auto absoluteabsoluteProgramCounter =
|
||||
static_cast<const char*>(absoluteProgramCounter_);
|
||||
return absoluteabsoluteProgramCounter - absoluteLibrary;
|
||||
}
|
||||
|
||||
/**
|
||||
* The offset within the current function
|
||||
*/
|
||||
int functionOffset() const noexcept {
|
||||
auto absoluteSymbol = static_cast<const char*>(functionAddress_);
|
||||
auto absoluteabsoluteProgramCounter =
|
||||
static_cast<const char*>(absoluteProgramCounter_);
|
||||
return absoluteabsoluteProgramCounter - absoluteSymbol;
|
||||
}
|
||||
|
||||
std::string buildId() const;
|
||||
private:
|
||||
const InstructionPointer absoluteProgramCounter_;
|
||||
const InstructionPointer libraryBase_;
|
||||
const InstructionPointer functionAddress_;
|
||||
const std::string libraryName_;
|
||||
const std::string functionName_;
|
||||
|
||||
mutable bool hasBuildId_;
|
||||
mutable std::string buildId_;
|
||||
};
|
||||
|
||||
/**
|
||||
* If a library identifier function is set, it is passed a libraryName
|
||||
* for the frame, and returns a library build id string, which will be
|
||||
* included in the logged stack trace. The most common use for this
|
||||
* will be correlating stack traces with breakpad identifiers.
|
||||
*/
|
||||
typedef std::string (*LibraryIdentifierFunctionType)(const std::string&);
|
||||
|
||||
void setLibraryIdentifierFunction(LibraryIdentifierFunctionType func);
|
||||
|
||||
/**
|
||||
* Populate the vector with the current stack trace
|
||||
*
|
||||
* Note that this trace needs to be symbolicated to get the library offset even
|
||||
* if it is to be symbolicated off-line.
|
||||
*
|
||||
* Beware of a bug on some platforms, which makes the trace loop until the
|
||||
* buffer is full when it reaches a noexpr function. It seems to be fixed in
|
||||
* newer versions of gcc. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56846
|
||||
*
|
||||
* @param stackTrace The vector that will receive the stack trace. Before
|
||||
* filling the vector it will be cleared. The vector will never grow so the
|
||||
* number of frames captured is limited by the capacity of it.
|
||||
*
|
||||
* @param skip The number of frames to skip before capturing the trace
|
||||
*/
|
||||
void getStackTrace(std::vector<InstructionPointer>& stackTrace, size_t skip = 0);
|
||||
|
||||
/**
|
||||
* Creates a vector and populates it with the current stack trace
|
||||
*
|
||||
* Note that this trace needs to be symbolicated to get the library offset even
|
||||
* if it is to be symbolicated off-line.
|
||||
*
|
||||
* Beware of a bug on some platforms, which makes the trace loop until the
|
||||
* buffer is full when it reaches a noexpr function. It seems to be fixed in
|
||||
* newer versions of gcc. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56846
|
||||
*
|
||||
* @param skip The number of frames to skip before capturing the trace
|
||||
*
|
||||
* @limit The maximum number of frames captured
|
||||
*/
|
||||
inline std::vector<InstructionPointer> getStackTrace(
|
||||
size_t skip = 0,
|
||||
size_t limit = kDefaultLimit) {
|
||||
auto stackTrace = std::vector<InstructionPointer>{};
|
||||
stackTrace.reserve(limit);
|
||||
getStackTrace(stackTrace, skip + 1);
|
||||
return stackTrace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Symbolicates a stack trace into a given vector
|
||||
*
|
||||
* @param symbols The vector to receive the output. The vector is cleared and
|
||||
* enough room to keep the frames are reserved.
|
||||
*
|
||||
* @param stackTrace The input stack trace
|
||||
*/
|
||||
void getStackTraceSymbols(std::vector<StackTraceElement>& symbols,
|
||||
const std::vector<InstructionPointer>& trace);
|
||||
|
||||
/**
|
||||
* Symbolicates a stack trace into a new vector
|
||||
*
|
||||
* @param stackTrace The input stack trace
|
||||
*/
|
||||
inline std::vector<StackTraceElement> getStackTraceSymbols(
|
||||
const std::vector<InstructionPointer>& trace) {
|
||||
auto symbols = std::vector<StackTraceElement>{};
|
||||
getStackTraceSymbols(symbols, trace);
|
||||
return symbols;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Captures and symbolicates a stack trace
|
||||
*
|
||||
* Beware of a bug on some platforms, which makes the trace loop until the
|
||||
* buffer is full when it reaches a noexpr function. It seems to be fixed in
|
||||
* newer versions of gcc. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56846
|
||||
*
|
||||
* @param skip The number of frames before capturing the trace
|
||||
*
|
||||
* @param limit The maximum number of frames captured
|
||||
*/
|
||||
inline std::vector<StackTraceElement> getStackTraceSymbols(
|
||||
size_t skip = 0,
|
||||
size_t limit = kDefaultLimit) {
|
||||
return getStackTraceSymbols(getStackTrace(skip + 1, limit));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formatting a stack trace element
|
||||
*/
|
||||
std::ostream& operator<<(std::ostream& out, const StackTraceElement& elm);
|
||||
|
||||
/**
|
||||
* Formatting a stack trace
|
||||
*/
|
||||
std::ostream& operator<<(std::ostream& out,
|
||||
const std::vector<StackTraceElement>& trace);
|
||||
|
||||
/**
|
||||
* Log stack trace
|
||||
*
|
||||
* Makes it possible to log a trace without using a temporary stream when the
|
||||
* underlying log API is not stream based.
|
||||
*/
|
||||
void logStackTrace(const std::vector<StackTraceElement>& trace);
|
||||
|
||||
}
|
||||
}
|
84
lib/fb/src/main/cpp/include/lyra/lyra_exceptions.h
Normal file
84
lib/fb/src/main/cpp/include/lyra/lyra_exceptions.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <exception>
|
||||
#include <typeinfo>
|
||||
#include <vector>
|
||||
|
||||
#include <lyra/lyra.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace lyra {
|
||||
|
||||
namespace detail {
|
||||
struct ExceptionTraceHolder {
|
||||
ExceptionTraceHolder();
|
||||
// Need some virtual function to make this a polymorphic type.
|
||||
virtual ~ExceptionTraceHolder();
|
||||
ExceptionTraceHolder(const ExceptionTraceHolder&) = delete;
|
||||
ExceptionTraceHolder(ExceptionTraceHolder&&) = default;
|
||||
|
||||
std::vector<InstructionPointer> stackTrace_;
|
||||
};
|
||||
|
||||
template <typename E, bool hasTraceHolder>
|
||||
struct Holder : E, ExceptionTraceHolder {
|
||||
Holder(E&& e) : E{std::forward<E>(e)}, ExceptionTraceHolder{} {}
|
||||
};
|
||||
template <typename E>
|
||||
struct Holder<E, true> : E {
|
||||
Holder(E&& e) : E{std::forward<E>(e)} {}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the stack trace of an exception
|
||||
*/
|
||||
const std::vector<InstructionPointer>& getExceptionTrace(std::exception_ptr ptr);
|
||||
|
||||
/**
|
||||
* Throw an exception and store the stack trace. This works like
|
||||
* std::throw_with_nested in that it will actually throw a type that is
|
||||
* publicly derived from both E and detail::ExceptionTraceHolder.
|
||||
*/
|
||||
template <class E>
|
||||
[[noreturn]] void fbthrow(E&& exception) {
|
||||
throw detail::Holder<E, std::is_base_of<detail::ExceptionTraceHolder, E>::value>{std::forward<E>(exception)};
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that a terminate handler that logs traces is installed.
|
||||
* setLibraryIdentifierFunction should be called first if the stack
|
||||
* trace should log build ids for libraries.
|
||||
*/
|
||||
void ensureRegisteredTerminateHandler();
|
||||
|
||||
/**
|
||||
* Helper to convert an exception to a string
|
||||
*/
|
||||
std::string toString(std::exception_ptr exceptionPointer);
|
||||
|
||||
/**
|
||||
* lyra's cxa_throw will delegate to the original cxa throw. That pointer must
|
||||
* be set before lyra::cxa_throw is called.
|
||||
*
|
||||
* One example use would be to statically compile against something that overrides __cxa_throw.
|
||||
* That would look something like:
|
||||
*
|
||||
* [[noreturn]] void __cxa_throw(void* obj, const std::type_info* type, void (*destructor) (void*)) {
|
||||
* static auto initializer = lyra::original_cxa_throw = lookupOriginalCxaThrow();
|
||||
* lyra::cxa_throw(obj, type, destructor);
|
||||
* }
|
||||
*/
|
||||
[[gnu::noreturn]] extern void (*original_cxa_throw)(void*, const std::type_info*, void (*) (void*));
|
||||
[[noreturn]] void cxa_throw(void* obj, const std::type_info* type, void (*destructor) (void *));
|
||||
|
||||
void enableCxaThrowHookBacktraces(bool enable);
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user