Force 16 byte stack alignment on JNI method invocations on x86
Reviewed By: dcolascione Differential Revision: D2989293 fb-gh-sync-id: 9140ced55ef0b8a73fdc03a6d307af87cd2335ef shipit-source-id: 9140ced55ef0b8a73fdc03a6d307af87cd2335ef
This commit is contained in:
parent
d3f2081d90
commit
5df3eeb723
|
@ -1,15 +0,0 @@
|
||||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __i386__
|
|
||||||
// The Android x86 ABI states that the NDK toolchain assumes 16 byte stack
|
|
||||||
// alignment: http://developer.android.com/ndk/guides/x86.html JSC checks for
|
|
||||||
// stack alignment, and fails with SIGTRAP if it is not. Empirically, the
|
|
||||||
// google android x86 emulator does not provide this alignment, and so JSC
|
|
||||||
// calls may crash. All checked calls go through here, so the attribute here
|
|
||||||
// is added to force alignment and prevent crashes.
|
|
||||||
#define ALIGN_STACK __attribute__((force_align_arg_pointer))
|
|
||||||
#else
|
|
||||||
#define ALIGN_STACK
|
|
||||||
#endif
|
|
|
@ -65,7 +65,6 @@ react_library(
|
||||||
'JSCMemory.h',
|
'JSCMemory.h',
|
||||||
],
|
],
|
||||||
exported_headers = [
|
exported_headers = [
|
||||||
'AlignStack.h',
|
|
||||||
'Bridge.h',
|
'Bridge.h',
|
||||||
'ExecutorToken.h',
|
'ExecutorToken.h',
|
||||||
'ExecutorTokenFactory.h',
|
'ExecutorTokenFactory.h',
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "AlignStack.h"
|
|
||||||
|
|
||||||
namespace facebook {
|
namespace facebook {
|
||||||
namespace react {
|
namespace react {
|
||||||
|
|
||||||
|
@ -18,13 +16,11 @@ struct JsException : std::runtime_error {
|
||||||
using std::runtime_error::runtime_error;
|
using std::runtime_error::runtime_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
ALIGN_STACK
|
|
||||||
inline void throwJSExecutionException(const char* msg) {
|
inline void throwJSExecutionException(const char* msg) {
|
||||||
throw JsException(msg);
|
throw JsException(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
ALIGN_STACK
|
|
||||||
inline void throwJSExecutionException(const char* fmt, Args... args) {
|
inline void throwJSExecutionException(const char* fmt, Args... args) {
|
||||||
int msgSize = snprintf(nullptr, 0, fmt, args...);
|
int msgSize = snprintf(nullptr, 0, fmt, args...);
|
||||||
msgSize = std::min(512, msgSize + 1);
|
msgSize = std::min(512, msgSize + 1);
|
||||||
|
@ -36,16 +32,16 @@ inline void throwJSExecutionException(const char* fmt, Args... args) {
|
||||||
void installGlobalFunction(
|
void installGlobalFunction(
|
||||||
JSGlobalContextRef ctx,
|
JSGlobalContextRef ctx,
|
||||||
const char* name,
|
const char* name,
|
||||||
JSObjectCallAsFunctionCallback callback) ALIGN_STACK;
|
JSObjectCallAsFunctionCallback callback);
|
||||||
|
|
||||||
JSValueRef makeJSCException(
|
JSValueRef makeJSCException(
|
||||||
JSContextRef ctx,
|
JSContextRef ctx,
|
||||||
const char* exception_text) ALIGN_STACK;
|
const char* exception_text);
|
||||||
|
|
||||||
JSValueRef evaluateScript(
|
JSValueRef evaluateScript(
|
||||||
JSContextRef ctx,
|
JSContextRef ctx,
|
||||||
JSStringRef script,
|
JSStringRef script,
|
||||||
JSStringRef sourceURL,
|
JSStringRef sourceURL,
|
||||||
const char* cachePath = nullptr) ALIGN_STACK;
|
const char* cachePath = nullptr);
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
|
@ -14,8 +14,6 @@
|
||||||
|
|
||||||
#include "noncopyable.h"
|
#include "noncopyable.h"
|
||||||
|
|
||||||
#include "AlignStack.h"
|
|
||||||
|
|
||||||
#if WITH_FBJSCEXTENSIONS
|
#if WITH_FBJSCEXTENSIONS
|
||||||
#include <jsc_stringref.h>
|
#include <jsc_stringref.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,15 +26,15 @@ class Context;
|
||||||
|
|
||||||
class String : public noncopyable {
|
class String : public noncopyable {
|
||||||
public:
|
public:
|
||||||
explicit String(const char* utf8) ALIGN_STACK :
|
explicit String(const char* utf8) :
|
||||||
m_string(Adopt, JSStringCreateWithUTF8CString(utf8))
|
m_string(Adopt, JSStringCreateWithUTF8CString(utf8))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
String(String&& other) ALIGN_STACK :
|
String(String&& other) :
|
||||||
m_string(Adopt, other.m_string.leakRef())
|
m_string(Adopt, other.m_string.leakRef())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
String(const String& other) ALIGN_STACK :
|
String(const String& other) :
|
||||||
m_string(other.m_string)
|
m_string(other.m_string)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -45,16 +43,16 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Length in characters
|
// Length in characters
|
||||||
size_t length() const ALIGN_STACK {
|
size_t length() const {
|
||||||
return JSStringGetLength(m_string.get());
|
return JSStringGetLength(m_string.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Length in bytes of a null-terminated utf8 encoded value
|
// Length in bytes of a null-terminated utf8 encoded value
|
||||||
size_t utf8Size() const ALIGN_STACK {
|
size_t utf8Size() const {
|
||||||
return JSStringGetMaximumUTF8CStringSize(m_string.get());
|
return JSStringGetMaximumUTF8CStringSize(m_string.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string str() const ALIGN_STACK {
|
std::string str() const {
|
||||||
size_t reserved = utf8Size();
|
size_t reserved = utf8Size();
|
||||||
char* bytes = new char[reserved];
|
char* bytes = new char[reserved];
|
||||||
size_t length = JSStringGetUTF8CString(m_string.get(), bytes, reserved) - 1;
|
size_t length = JSStringGetUTF8CString(m_string.get(), bytes, reserved) - 1;
|
||||||
|
@ -63,11 +61,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assumes that utf8 is null terminated
|
// Assumes that utf8 is null terminated
|
||||||
bool equals(const char* utf8) ALIGN_STACK {
|
bool equals(const char* utf8) {
|
||||||
return JSStringIsEqualToUTF8CString(m_string.get(), utf8);
|
return JSStringIsEqualToUTF8CString(m_string.get(), utf8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String createExpectingAscii(std::string const &utf8) ALIGN_STACK {
|
static String createExpectingAscii(std::string const &utf8) {
|
||||||
#if WITH_FBJSCEXTENSIONS
|
#if WITH_FBJSCEXTENSIONS
|
||||||
return String(Adopt, JSStringCreateWithUTF8CStringExpectAscii(utf8.c_str(), utf8.size()));
|
return String(Adopt, JSStringCreateWithUTF8CStringExpectAscii(utf8.c_str(), utf8.size()));
|
||||||
#else
|
#else
|
||||||
|
@ -84,11 +82,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit String(JSStringRef string) ALIGN_STACK :
|
explicit String(JSStringRef string) :
|
||||||
m_string(string)
|
m_string(string)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
String(AdoptTag tag, JSStringRef string) ALIGN_STACK :
|
String(AdoptTag tag, JSStringRef string) :
|
||||||
m_string(tag, string)
|
m_string(tag, string)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -110,7 +108,7 @@ public:
|
||||||
other.m_isProtected = false;
|
other.m_isProtected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
~Object() ALIGN_STACK {
|
~Object() {
|
||||||
if (m_isProtected && m_obj) {
|
if (m_isProtected && m_obj) {
|
||||||
JSValueUnprotect(m_context, m_obj);
|
JSValueUnprotect(m_context, m_obj);
|
||||||
}
|
}
|
||||||
|
@ -122,28 +120,28 @@ public:
|
||||||
|
|
||||||
operator Value() const;
|
operator Value() const;
|
||||||
|
|
||||||
bool isFunction() const ALIGN_STACK {
|
bool isFunction() const {
|
||||||
return JSObjectIsFunction(m_context, m_obj);
|
return JSObjectIsFunction(m_context, m_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value callAsFunction(int nArgs, JSValueRef args[]) ALIGN_STACK;
|
Value callAsFunction(int nArgs, JSValueRef args[]);
|
||||||
|
|
||||||
Value getProperty(const String& propName) const ALIGN_STACK;
|
Value getProperty(const String& propName) const;
|
||||||
Value getProperty(const char *propName) const;
|
Value getProperty(const char *propName) const;
|
||||||
Value getPropertyAtIndex(unsigned index) const ALIGN_STACK;
|
Value getPropertyAtIndex(unsigned index) const;
|
||||||
void setProperty(const String& propName, const Value& value) const ALIGN_STACK;
|
void setProperty(const String& propName, const Value& value) const;
|
||||||
void setProperty(const char *propName, const Value& value) const;
|
void setProperty(const char *propName, const Value& value) const;
|
||||||
std::vector<std::string> getPropertyNames() const ALIGN_STACK;
|
std::vector<std::string> getPropertyNames() const;
|
||||||
std::unordered_map<std::string, std::string> toJSONMap() const ALIGN_STACK;
|
std::unordered_map<std::string, std::string> toJSONMap() const;
|
||||||
|
|
||||||
void makeProtected() ALIGN_STACK {
|
void makeProtected() {
|
||||||
if (!m_isProtected && m_obj) {
|
if (!m_isProtected && m_obj) {
|
||||||
JSValueProtect(m_context, m_obj);
|
JSValueProtect(m_context, m_obj);
|
||||||
m_isProtected = true;
|
m_isProtected = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Object getGlobalObject(JSContextRef ctx) ALIGN_STACK {
|
static Object getGlobalObject(JSContextRef ctx) {
|
||||||
auto globalObj = JSContextGetGlobalObject(ctx);
|
auto globalObj = JSContextGetGlobalObject(ctx);
|
||||||
return Object(ctx, globalObj);
|
return Object(ctx, globalObj);
|
||||||
}
|
}
|
||||||
|
@ -151,7 +149,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Creates an instance of the default object class.
|
* Creates an instance of the default object class.
|
||||||
*/
|
*/
|
||||||
static Object create(JSContextRef ctx) ALIGN_STACK;
|
static Object create(JSContextRef ctx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JSContextRef m_context;
|
JSContextRef m_context;
|
||||||
|
@ -168,27 +166,27 @@ public:
|
||||||
return m_value;
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isBoolean() const ALIGN_STACK {
|
bool isBoolean() const {
|
||||||
return JSValueIsBoolean(context(), m_value);
|
return JSValueIsBoolean(context(), m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool asBoolean() const ALIGN_STACK {
|
bool asBoolean() const {
|
||||||
return JSValueToBoolean(context(), m_value);
|
return JSValueToBoolean(context(), m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNumber() const ALIGN_STACK {
|
bool isNumber() const {
|
||||||
return JSValueIsNumber(context(), m_value);
|
return JSValueIsNumber(context(), m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNull() const ALIGN_STACK {
|
bool isNull() const {
|
||||||
return JSValueIsNull(context(), m_value);
|
return JSValueIsNull(context(), m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isUndefined() const ALIGN_STACK {
|
bool isUndefined() const {
|
||||||
return JSValueIsUndefined(context(), m_value);
|
return JSValueIsUndefined(context(), m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
double asNumber() const ALIGN_STACK {
|
double asNumber() const {
|
||||||
if (isNumber()) {
|
if (isNumber()) {
|
||||||
return JSValueToNumber(context(), m_value, nullptr);
|
return JSValueToNumber(context(), m_value, nullptr);
|
||||||
} else {
|
} else {
|
||||||
|
@ -204,22 +202,22 @@ public:
|
||||||
return static_cast<uint32_t>(asNumber());
|
return static_cast<uint32_t>(asNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isObject() const ALIGN_STACK {
|
bool isObject() const {
|
||||||
return JSValueIsObject(context(), m_value);
|
return JSValueIsObject(context(), m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object asObject() ALIGN_STACK;
|
Object asObject();
|
||||||
|
|
||||||
bool isString() const ALIGN_STACK {
|
bool isString() const {
|
||||||
return JSValueIsString(context(), m_value);
|
return JSValueIsString(context(), m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
String toString() ALIGN_STACK {
|
String toString() {
|
||||||
return String::adopt(JSValueToStringCopy(context(), m_value, nullptr));
|
return String::adopt(JSValueToStringCopy(context(), m_value, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string toJSONString(unsigned indent = 0) const ALIGN_STACK;
|
std::string toJSONString(unsigned indent = 0) const;
|
||||||
static Value fromJSON(JSContextRef ctx, const String& json) ALIGN_STACK;
|
static Value fromJSON(JSContextRef ctx, const String& json);
|
||||||
protected:
|
protected:
|
||||||
JSContextRef context() const;
|
JSContextRef context() const;
|
||||||
JSContextRef m_context;
|
JSContextRef m_context;
|
||||||
|
|
Loading…
Reference in New Issue