Revert "Implement IsMemoryValid natively on OSX. 250% faster!"
This reverts commit 09d1e4d4b4246e3c738379188e1780522ba70ccf. It is actually much much slower on MacOS 10.11 and 10.12.
This commit is contained in:
parent
74cb06a22f
commit
8dcf1c8b46
@ -26,8 +26,6 @@
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <mach/vm_map.h>
|
||||
#include <mach/mach_host.h>
|
||||
|
||||
#include <CoreFoundation/CFBase.h> // For MAC_OS_X_VERSION_X_X macros
|
||||
|
||||
@ -43,19 +41,6 @@
|
||||
namespace cling {
|
||||
namespace utils {
|
||||
namespace platform {
|
||||
|
||||
bool IsMemoryValid(const void *P) {
|
||||
char Buf;
|
||||
vm_size_t sizeRead = sizeof(Buf);
|
||||
if (::vm_read_overwrite(mach_task_self(), vm_address_t(P), sizeRead,
|
||||
vm_address_t(&Buf), &sizeRead) != KERN_SUCCESS)
|
||||
return false;
|
||||
if (sizeRead != sizeof(Buf))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline namespace osx {
|
||||
|
||||
namespace {
|
||||
|
@ -14,17 +14,18 @@
|
||||
#include "cling/Utils/Paths.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// PATH_MAX
|
||||
#ifdef __APPLE__
|
||||
#include <sys/syslimits.h> // PATH_MAX
|
||||
#include <sys/syslimits.h>
|
||||
#else
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
@ -34,6 +35,61 @@ namespace cling {
|
||||
namespace utils {
|
||||
namespace platform {
|
||||
|
||||
namespace {
|
||||
struct PointerCheck {
|
||||
private:
|
||||
// A simple round-robin cache: what enters first, leaves first.
|
||||
// MRU cache wasn't worth the extra CPU cycles.
|
||||
std::array<const void*, 8> lines;
|
||||
std::atomic<unsigned> mostRecent = {0};
|
||||
int FD;
|
||||
|
||||
// Concurrent writes to the same cache element can result in invalid cache
|
||||
// elements, causing pointer address not being available in the cache even
|
||||
// though they should be, i.e. false cache misses. While can cause a
|
||||
// slow-down, the cost for keeping the cache thread-local or atomic is
|
||||
// much higher (yes, this was measured).
|
||||
void push(const void* P) {
|
||||
unsigned acquiredVal = mostRecent;
|
||||
while(!mostRecent.compare_exchange_weak(acquiredVal,
|
||||
(acquiredVal+1)%lines.size())) {
|
||||
acquiredVal = mostRecent;
|
||||
}
|
||||
lines[acquiredVal] = P;
|
||||
}
|
||||
|
||||
public:
|
||||
PointerCheck() : FD(::open("/dev/random", O_WRONLY)) {
|
||||
if (FD == -1) ::perror("open('/dev/random')");
|
||||
}
|
||||
~PointerCheck() {
|
||||
if (FD != -1) ::close(FD);
|
||||
}
|
||||
|
||||
bool operator () (const void* P) {
|
||||
if (FD == -1)
|
||||
return false;
|
||||
|
||||
if (std::find(lines.begin(), lines.end(), P) != lines.end())
|
||||
return true;
|
||||
|
||||
// There is a POSIX way of finding whether an address
|
||||
// can be accessed for reading.
|
||||
if (::write(FD, P, 1/*byte*/) != 1) {
|
||||
assert(errno == EFAULT && "unexpected write error at address");
|
||||
return false;
|
||||
}
|
||||
push(P);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bool IsMemoryValid(const void *P) {
|
||||
static PointerCheck sPointerCheck;
|
||||
return sPointerCheck(P);
|
||||
}
|
||||
|
||||
std::string GetCwd() {
|
||||
char Buffer[PATH_MAXC];
|
||||
if (::getcwd(Buffer, sizeof(Buffer)))
|
||||
@ -143,73 +199,6 @@ bool GetSystemLibraryPaths(llvm::SmallVectorImpl<std::string>& Paths) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
### FIXME Use OS X IsMemoryValid on all BSD variants:
|
||||
#include <sys/param.h>
|
||||
#if !defined(BSD)
|
||||
<SNIP>
|
||||
#else
|
||||
*/
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
|
||||
namespace {
|
||||
struct PointerCheck {
|
||||
private:
|
||||
// A simple round-robin cache: what enters first, leaves first.
|
||||
// MRU cache wasn't worth the extra CPU cycles.
|
||||
std::array<const void*, 8> lines;
|
||||
std::atomic<unsigned> mostRecent = {0};
|
||||
int FD;
|
||||
|
||||
// Concurrent writes to the same cache element can result in invalid cache
|
||||
// elements, causing pointer address not being available in the cache even
|
||||
// though they should be, i.e. false cache misses. While can cause a
|
||||
// slow-down, the cost for keeping the cache thread-local or atomic is
|
||||
// much higher (yes, this was measured).
|
||||
void push(const void* P) {
|
||||
unsigned acquiredVal = mostRecent;
|
||||
while(!mostRecent.compare_exchange_weak(acquiredVal,
|
||||
(acquiredVal+1)%lines.size())) {
|
||||
acquiredVal = mostRecent;
|
||||
}
|
||||
lines[acquiredVal] = P;
|
||||
}
|
||||
|
||||
public:
|
||||
PointerCheck() : FD(::open("/dev/random", O_WRONLY)) {
|
||||
if (FD == -1) ::perror("open('/dev/random')");
|
||||
}
|
||||
~PointerCheck() {
|
||||
if (FD != -1) ::close(FD);
|
||||
}
|
||||
|
||||
bool operator () (const void* P) {
|
||||
if (FD == -1)
|
||||
return false;
|
||||
|
||||
if (std::find(lines.begin(), lines.end(), P) != lines.end())
|
||||
return true;
|
||||
|
||||
// There is a POSIX way of finding whether an address
|
||||
// can be accessed for reading.
|
||||
if (::write(FD, P, 1/*byte*/) != 1) {
|
||||
assert(errno == EFAULT && "unexpected write error at address");
|
||||
return false;
|
||||
}
|
||||
push(P);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bool IsMemoryValid(const void *P) {
|
||||
static PointerCheck sPointerCheck;
|
||||
return sPointerCheck(P);
|
||||
}
|
||||
|
||||
#endif // !__APPLE__
|
||||
|
||||
} // namespace platform
|
||||
} // namespace utils
|
||||
} // namespace cling
|
||||
|
Loading…
x
Reference in New Issue
Block a user