Skip to content

Commit

Permalink
Merge pull request #14201 from hrydgard/ios-jit-detect
Browse files Browse the repository at this point in the history
Add iOS version detection, turn off JIT on bootup if >= 14.3.
  • Loading branch information
unknownbrackets committed Feb 22, 2021
2 parents 366428b + 21511ac commit 70c7c3e
Show file tree
Hide file tree
Showing 11 changed files with 91 additions and 19 deletions.
2 changes: 2 additions & 0 deletions Common/System/System.h
Expand Up @@ -98,6 +98,8 @@ enum SystemProperty {

SYSPROP_SUPPORTS_PERMISSIONS,
SYSPROP_SUPPORTS_SUSTAINED_PERF_MODE,

SYSPROP_CAN_JIT,
};

std::string System_GetProperty(SystemProperty prop);
Expand Down
2 changes: 2 additions & 0 deletions Qt/QtMain.cpp
Expand Up @@ -225,6 +225,8 @@ bool System_GetPropertyBool(SystemProperty prop) {
#else
return false;
#endif
case SYSPROP_CAN_JIT:
return true;
default:
return false;
}
Expand Down
2 changes: 2 additions & 0 deletions SDL/SDLMain.cpp
Expand Up @@ -387,6 +387,8 @@ bool System_GetPropertyBool(SystemProperty prop) {
#else
return false;
#endif
case SYSPROP_CAN_JIT:
return true;
default:
return false;
}
Expand Down
3 changes: 3 additions & 0 deletions UI/DevScreens.cpp
Expand Up @@ -472,6 +472,9 @@ void SystemInfoScreen::CreateViews() {
int totalThreads = cpu_info.num_cores * cpu_info.logical_cpu_count;
std::string cores = StringFromFormat(si->T("%d (%d per core, %d cores)"), totalThreads, cpu_info.logical_cpu_count, cpu_info.num_cores);
deviceSpecs->Add(new InfoItem(si->T("Threads"), cores));
#endif
#if PPSSPP_PLATFORM(IOS)
deviceSpecs->Add(new InfoItem(si->T("JIT available"), System_GetPropertyBool(SYSPROP_CAN_JIT) ? di->T("Yes") : di->T("No")));
#endif
deviceSpecs->Add(new ItemHeader(si->T("GPU Information")));

Expand Down
6 changes: 6 additions & 0 deletions UI/NativeApp.cpp
Expand Up @@ -694,6 +694,12 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
}
}

if (System_GetPropertyBool(SYSPROP_CAN_JIT) == false && g_Config.iCpuCore == (int)CPUCore::JIT) {
// Just gonna force it to the IR interpreter on startup.
// We don't hide the option, but we make sure it's off on bootup. In case someone wants
// to experiment in future iOS versions or something...
g_Config.iCpuCore = (int)CPUCore::IR_JIT;
}

auto des = GetI18NCategory("DesktopUI");
// Note to translators: do not translate this/add this to PPSSPP-lang's files.
Expand Down
2 changes: 2 additions & 0 deletions UWP/PPSSPP_UWPMain.cpp
Expand Up @@ -439,6 +439,8 @@ bool System_GetPropertyBool(SystemProperty prop) {
#else
return false;
#endif
case SYSPROP_CAN_JIT:
return true;
default:
return false;
}
Expand Down
2 changes: 2 additions & 0 deletions Windows/main.cpp
Expand Up @@ -310,6 +310,8 @@ bool System_GetPropertyBool(SystemProperty prop) {
#else
return false;
#endif
case SYSPROP_CAN_JIT:
return true;
default:
return false;
}
Expand Down
2 changes: 2 additions & 0 deletions android/jni/app-android.cpp
Expand Up @@ -443,6 +443,8 @@ bool System_GetPropertyBool(SystemProperty prop) {
#else
return false;
#endif
case SYSPROP_CAN_JIT:
return true;
default:
return false;
}
Expand Down
9 changes: 8 additions & 1 deletion headless/Headless.cpp
Expand Up @@ -89,7 +89,14 @@ std::string System_GetProperty(SystemProperty prop) { return ""; }
std::vector<std::string> System_GetPropertyStringVec(SystemProperty prop) { return std::vector<std::string>(); }
int System_GetPropertyInt(SystemProperty prop) { return -1; }
float System_GetPropertyFloat(SystemProperty prop) { return -1.0f; }
bool System_GetPropertyBool(SystemProperty prop) { return false; }
bool System_GetPropertyBool(SystemProperty prop) {
switch (prop) {
case SYSPROP_CAN_JIT:
return true;
default:
return false;
}
}

void System_SendMessage(const char *command, const char *parameter) {}
void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function<void(bool, const std::string &)> cb) { cb(false, ""); }
Expand Down
76 changes: 58 additions & 18 deletions ios/main.mm
Expand Up @@ -14,8 +14,10 @@
#import "PPSSPPUIApplication.h"
#import "ViewController.h"

#include "Common/MemoryUtil.h"
#include "Common/System/NativeApp.h"
#include "Common/System/System.h"
#include "Common/StringUtils.h"
#include "Common/Profiler/Profiler.h"

#define CS_OPS_STATUS 0 /* return status */
Expand Down Expand Up @@ -52,11 +54,14 @@ kern_return_t catch_exception_raise(mach_port_t exception_port,
static float g_safeInsetTop = 0.0;
static float g_safeInsetBottom = 0.0;

static bool g_jitAvailable = false;
static int g_iosVersionMajor;
static int g_iosVersionMinor;

std::string System_GetProperty(SystemProperty prop) {
switch (prop) {
case SYSPROP_NAME:
return "iOS:";
return StringFromFormat("iOS %d.%d", g_iosVersionMajor, g_iosVersionMinor);
case SYSPROP_LANGREGION:
return "en_US";
default:
Expand All @@ -78,6 +83,8 @@ int System_GetPropertyInt(SystemProperty prop) {
return 44100;
case SYSPROP_DEVICE_TYPE:
return DEVICE_TYPE_MOBILE;
case SYSPROP_SYSTEMVERSION:
return g_iosVersionMajor;
default:
return -1;
}
Expand Down Expand Up @@ -110,6 +117,9 @@ bool System_GetPropertyBool(SystemProperty prop) {
#else
return false;
#endif
case SYSPROP_CAN_JIT:
return g_jitAvailable;

default:
return false;
}
Expand Down Expand Up @@ -200,28 +210,58 @@ void Vibrate(int mode) {

int main(int argc, char *argv[])
{
// Hacky hacks to try to enable JIT by pretending to be a debugger.
csops = reinterpret_cast<decltype(csops)>(dlsym(dlopen(nullptr, RTLD_LAZY), "csops"));
exc_server = reinterpret_cast<decltype(exc_server)>(dlsym(dlopen(NULL, RTLD_LAZY), "exc_server"));
ptrace = reinterpret_cast<decltype(ptrace)>(dlsym(dlopen(NULL, RTLD_LAZY), "ptrace"));
// see https://github.com/hrydgard/ppsspp/issues/11905
if (!cs_debugged()) {
pid_t pid = fork();
if (pid == 0) {
ptrace(PT_TRACE_ME, 0, nullptr, 0);
exit(0);
} else if (pid < 0) {
perror("Unable to fork");

ptrace(PT_TRACE_ME, 0, nullptr, 0);
ptrace(PT_SIGEXC, 0, nullptr, 0);

mach_port_t port = MACH_PORT_NULL;
mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
task_set_exception_ports(mach_task_self(), EXC_MASK_SOFTWARE, port, EXCEPTION_DEFAULT, THREAD_STATE_NONE);
pthread_t thread;
pthread_create(&thread, nullptr, exception_handler, reinterpret_cast<void *>(&port));

// Tried checking for JIT support here with AllocateExecutableMemory and ProtectMemoryPages,
// but it just succeeds, and then fails when you try to execute from it.

// So, we'll just resort to a version check.

std::string version = [[UIDevice currentDevice].systemVersion UTF8String];
if (2 != sscanf(version.c_str(), "%d.%d", &g_iosVersionMajor, &g_iosVersionMinor)) {
// Just set it to 14.0 if the parsing fails for whatever reason.
g_iosVersionMajor = 14;
g_iosVersionMinor = 0;
}

if (g_iosVersionMajor > 14 || (g_iosVersionMajor == 14 && g_iosVersionMinor >= 3)) {
g_jitAvailable = false;
} else {
g_jitAvailable = true;
}

bool debuggerAttached = cs_debugged();

if (!debuggerAttached) {
// Try to fool iOS into thinking a debugger is attached.
// This doesn't work in iOS 14.4 anymore so don't even try there.
if (!(g_iosVersionMajor == 14 && g_iosVersionMinor == 4)) {
pid_t pid = fork();
if (pid == 0) {
printf("Forked a ptrace call");
ptrace(PT_TRACE_ME, 0, nullptr, 0);
exit(0);
} else if (pid < 0) {
perror("Unable to fork");

ptrace(PT_TRACE_ME, 0, nullptr, 0);
ptrace(PT_SIGEXC, 0, nullptr, 0);

mach_port_t port = MACH_PORT_NULL;
mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
task_set_exception_ports(mach_task_self(), EXC_MASK_SOFTWARE, port, EXCEPTION_DEFAULT, THREAD_STATE_NONE);
pthread_t thread;
pthread_create(&thread, nullptr, exception_handler, reinterpret_cast<void *>(&port));
}
}
} else {
// Debugger is attached - we can actually JIT. Override the version detect.
g_jitAvailable = true;
}

PROFILE_INIT();
Expand Down
4 changes: 4 additions & 0 deletions unittest/UnitTest.cpp
Expand Up @@ -69,6 +69,10 @@ float System_GetPropertyFloat(SystemProperty prop) {
return -1;
}
bool System_GetPropertyBool(SystemProperty prop) {
switch (prop) {
case SYSPROP_CAN_JIT:
return true;
}
return false;
}

Expand Down

0 comments on commit 70c7c3e

Please sign in to comment.