mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 959597 part 3 - Add ARM simulator for JIT code. r=nbp
This commit is contained in:
parent
c0d09abad1
commit
f289f537ef
@ -34,7 +34,7 @@
|
||||
|
||||
#include "assembler/assembler/MacroAssemblerARM.h"
|
||||
|
||||
#if WTF_OS_LINUX || WTF_OS_ANDROID
|
||||
#if (WTF_OS_LINUX || WTF_OS_ANDROID) && !defined(JS_ARM_SIMULATOR)
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
@ -56,6 +56,9 @@ namespace JSC {
|
||||
|
||||
static bool isVFPPresent()
|
||||
{
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
return true;
|
||||
#else
|
||||
#if WTF_OS_LINUX
|
||||
int fd = open("/proc/self/auxv", O_RDONLY);
|
||||
if (fd > 0) {
|
||||
@ -85,8 +88,8 @@ static bool isVFPPresent()
|
||||
if (strstr(buf, "vfp"))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
#endif // JS_ARM_SIMULATOR
|
||||
}
|
||||
|
||||
const bool MacroAssemblerARM::s_isVFPPresent = isVFPPresent();
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "jsalloc.h"
|
||||
|
||||
#include "assembler/wtf/Platform.h"
|
||||
#include "jit/arm/Simulator-arm.h"
|
||||
#include "js/HashTable.h"
|
||||
#include "js/Vector.h"
|
||||
|
||||
@ -396,6 +397,11 @@ public:
|
||||
static void cacheFlush(void*, size_t)
|
||||
{
|
||||
}
|
||||
#elif defined(JS_ARM_SIMULATOR)
|
||||
static void cacheFlush(void *code, size_t size)
|
||||
{
|
||||
js::jit::Simulator::FlushICache(code, size);
|
||||
}
|
||||
#elif WTF_CPU_MIPS
|
||||
static void cacheFlush(void* code, size_t size)
|
||||
{
|
||||
|
@ -366,6 +366,13 @@
|
||||
|
||||
#endif /* ARM */
|
||||
|
||||
#if defined(JS_ARM_SIMULATOR)
|
||||
# undef WTF_CPU_X86
|
||||
# undef WTF_CPU_X64
|
||||
# define WTF_CPU_ARM_TRADITIONAL 1
|
||||
# define WTF_CPU_ARM 1
|
||||
#endif
|
||||
|
||||
#if WTF_CPU_ARM || WTF_CPU_MIPS
|
||||
#define WTF_CPU_NEEDS_ALIGNED_ACCESS 1
|
||||
#endif
|
||||
|
@ -278,10 +278,14 @@ MarkRangeConservativelyAndSkipIon(JSTracer *trc, JSRuntime *rt, const uintptr_t
|
||||
{
|
||||
const uintptr_t *i = begin;
|
||||
|
||||
#if JS_STACK_GROWTH_DIRECTION < 0 && defined(JS_ION)
|
||||
#if JS_STACK_GROWTH_DIRECTION < 0 && defined(JS_ION) && !defined(JS_ARM_SIMULATOR)
|
||||
// Walk only regions in between JIT activations. Note that non-volatile
|
||||
// registers are spilled to the stack before the entry frame, ensuring
|
||||
// that the conservative scanner will still see them.
|
||||
//
|
||||
// If the ARM simulator is enabled, JIT activations are not on the native
|
||||
// stack but on the simulator stack, so we don't have to skip JIT regions
|
||||
// in this case.
|
||||
for (jit::JitActivationIterator iter(rt); !iter.done(); ++iter) {
|
||||
uintptr_t *jitMin, *jitEnd;
|
||||
iter.jitStackRange(jitMin, jitEnd);
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "jit/AsmJSModule.h"
|
||||
#include "jit/Ion.h"
|
||||
#include "jit/JitCommon.h"
|
||||
#ifdef JS_ION_PERF
|
||||
# include "jit/PerfSpewer.h"
|
||||
#endif
|
||||
@ -397,7 +398,8 @@ CallAsmJS(JSContext *cx, unsigned argc, Value *vp)
|
||||
JitActivation jitActivation(cx, /* firstFrameIsConstructing = */ false, /* active */ false);
|
||||
|
||||
// Call the per-exported-function trampoline created by GenerateEntry.
|
||||
if (!module.entryTrampoline(func)(coercedArgs.begin(), module.globalData()))
|
||||
AsmJSModule::CodePtr enter = module.entryTrampoline(func);
|
||||
if (!CALL_GENERATED_ASMJS(enter, coercedArgs.begin(), module.globalData()))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -183,10 +183,10 @@ InvokeFromAsmJS_ToNumber(JSContext *cx, int32_t exitIndex, int32_t argc, Value *
|
||||
#if defined(JS_CODEGEN_ARM)
|
||||
extern "C" {
|
||||
|
||||
extern int
|
||||
extern int64_t
|
||||
__aeabi_idivmod(int, int);
|
||||
|
||||
extern int
|
||||
extern int64_t
|
||||
__aeabi_uidivmod(int, int);
|
||||
|
||||
}
|
||||
@ -199,6 +199,15 @@ FuncCast(F *pf)
|
||||
return JS_FUNC_TO_DATA_PTR(void *, pf);
|
||||
}
|
||||
|
||||
static void *
|
||||
RedirectCall(void *fun, ABIFunctionType type)
|
||||
{
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
fun = Simulator::RedirectNativeFunction(fun, type);
|
||||
#endif
|
||||
return fun;
|
||||
}
|
||||
|
||||
static void *
|
||||
AddressOf(AsmJSImmKind kind, ExclusiveContext *cx)
|
||||
{
|
||||
@ -206,79 +215,79 @@ AddressOf(AsmJSImmKind kind, ExclusiveContext *cx)
|
||||
case AsmJSImm_Runtime:
|
||||
return cx->runtimeAddressForJit();
|
||||
case AsmJSImm_StackLimit:
|
||||
return cx->stackLimitAddress(StackForUntrustedScript);
|
||||
return cx->stackLimitAddressForJitCode(StackForUntrustedScript);
|
||||
case AsmJSImm_ReportOverRecursed:
|
||||
return FuncCast<void (JSContext*)>(js_ReportOverRecursed);
|
||||
return RedirectCall(FuncCast<void (JSContext*)>(js_ReportOverRecursed), Args_General1);
|
||||
case AsmJSImm_HandleExecutionInterrupt:
|
||||
return FuncCast(js_HandleExecutionInterrupt);
|
||||
return RedirectCall(FuncCast(js_HandleExecutionInterrupt), Args_General1);
|
||||
case AsmJSImm_InvokeFromAsmJS_Ignore:
|
||||
return FuncCast(InvokeFromAsmJS_Ignore);
|
||||
return RedirectCall(FuncCast(InvokeFromAsmJS_Ignore), Args_General4);
|
||||
case AsmJSImm_InvokeFromAsmJS_ToInt32:
|
||||
return FuncCast(InvokeFromAsmJS_ToInt32);
|
||||
return RedirectCall(FuncCast(InvokeFromAsmJS_ToInt32), Args_General4);
|
||||
case AsmJSImm_InvokeFromAsmJS_ToNumber:
|
||||
return FuncCast(InvokeFromAsmJS_ToNumber);
|
||||
return RedirectCall(FuncCast(InvokeFromAsmJS_ToNumber), Args_General4);
|
||||
case AsmJSImm_CoerceInPlace_ToInt32:
|
||||
return FuncCast(CoerceInPlace_ToInt32);
|
||||
return RedirectCall(FuncCast(CoerceInPlace_ToInt32), Args_General2);
|
||||
case AsmJSImm_CoerceInPlace_ToNumber:
|
||||
return FuncCast(CoerceInPlace_ToNumber);
|
||||
return RedirectCall(FuncCast(CoerceInPlace_ToNumber), Args_General2);
|
||||
case AsmJSImm_ToInt32:
|
||||
return FuncCast<int32_t (double)>(js::ToInt32);
|
||||
return RedirectCall(FuncCast<int32_t (double)>(js::ToInt32), Args_Int_Double);
|
||||
case AsmJSImm_EnableActivationFromAsmJS:
|
||||
return FuncCast(EnableActivationFromAsmJS);
|
||||
return RedirectCall(FuncCast(EnableActivationFromAsmJS), Args_General1);
|
||||
case AsmJSImm_DisableActivationFromAsmJS:
|
||||
return FuncCast(DisableActivationFromAsmJS);
|
||||
return RedirectCall(FuncCast(DisableActivationFromAsmJS), Args_General1);
|
||||
#if defined(JS_CODEGEN_ARM)
|
||||
case AsmJSImm_aeabi_idivmod:
|
||||
return FuncCast(__aeabi_idivmod);
|
||||
return RedirectCall(FuncCast(__aeabi_idivmod), Args_General2);
|
||||
case AsmJSImm_aeabi_uidivmod:
|
||||
return FuncCast(__aeabi_uidivmod);
|
||||
return RedirectCall(FuncCast(__aeabi_uidivmod), Args_General2);
|
||||
#endif
|
||||
case AsmJSImm_ModD:
|
||||
return FuncCast(NumberMod);
|
||||
return RedirectCall(FuncCast(NumberMod), Args_Double_DoubleDouble);
|
||||
case AsmJSImm_SinD:
|
||||
return FuncCast<double (double)>(sin);
|
||||
return RedirectCall(FuncCast<double (double)>(sin), Args_Double_Double);
|
||||
case AsmJSImm_SinF:
|
||||
return FuncCast<float (float)>(sinf);
|
||||
return RedirectCall(FuncCast<float (float)>(sinf), Args_Float32_Float32);
|
||||
case AsmJSImm_CosD:
|
||||
return FuncCast<double (double)>(cos);
|
||||
return RedirectCall(FuncCast<double (double)>(cos), Args_Double_Double);
|
||||
case AsmJSImm_CosF:
|
||||
return FuncCast<float (float)>(cosf);
|
||||
return RedirectCall(FuncCast<float (float)>(cosf), Args_Float32_Float32);
|
||||
case AsmJSImm_TanD:
|
||||
return FuncCast<double (double)>(tan);
|
||||
return RedirectCall(FuncCast<double (double)>(tan), Args_Double_Double);
|
||||
case AsmJSImm_TanF:
|
||||
return FuncCast<float (float)>(tanf);
|
||||
return RedirectCall(FuncCast<float (float)>(tanf), Args_Float32_Float32);
|
||||
case AsmJSImm_ASinD:
|
||||
return FuncCast<double (double)>(asin);
|
||||
return RedirectCall(FuncCast<double (double)>(asin), Args_Double_Double);
|
||||
case AsmJSImm_ASinF:
|
||||
return FuncCast<float (float)>(asinf);
|
||||
return RedirectCall(FuncCast<float (float)>(asinf), Args_Float32_Float32);
|
||||
case AsmJSImm_ACosD:
|
||||
return FuncCast<double (double)>(acos);
|
||||
return RedirectCall(FuncCast<double (double)>(acos), Args_Double_Double);
|
||||
case AsmJSImm_ACosF:
|
||||
return FuncCast<float (float)>(acosf);
|
||||
return RedirectCall(FuncCast<float (float)>(acosf), Args_Float32_Float32);
|
||||
case AsmJSImm_ATanD:
|
||||
return FuncCast<double (double)>(atan);
|
||||
return RedirectCall(FuncCast<double (double)>(atan), Args_Double_Double);
|
||||
case AsmJSImm_ATanF:
|
||||
return FuncCast<float (float)>(atanf);
|
||||
return RedirectCall(FuncCast<float (float)>(atanf), Args_Float32_Float32);
|
||||
case AsmJSImm_CeilD:
|
||||
return FuncCast<double (double)>(ceil);
|
||||
return RedirectCall(FuncCast<double (double)>(ceil), Args_Double_Double);
|
||||
case AsmJSImm_CeilF:
|
||||
return FuncCast<float (float)>(ceilf);
|
||||
return RedirectCall(FuncCast<float (float)>(ceilf), Args_Float32_Float32);
|
||||
case AsmJSImm_FloorD:
|
||||
return FuncCast<double (double)>(floor);
|
||||
return RedirectCall(FuncCast<double (double)>(floor), Args_Double_Double);
|
||||
case AsmJSImm_FloorF:
|
||||
return FuncCast<float (float)>(floorf);
|
||||
return RedirectCall(FuncCast<float (float)>(floorf), Args_Float32_Float32);
|
||||
case AsmJSImm_ExpD:
|
||||
return FuncCast<double (double)>(exp);
|
||||
return RedirectCall(FuncCast<double (double)>(exp), Args_Double_Double);
|
||||
case AsmJSImm_ExpF:
|
||||
return FuncCast<float (float)>(expf);
|
||||
return RedirectCall(FuncCast<float (float)>(expf), Args_Float32_Float32);
|
||||
case AsmJSImm_LogD:
|
||||
return FuncCast<double (double)>(log);
|
||||
return RedirectCall(FuncCast<double (double)>(log), Args_Double_Double);
|
||||
case AsmJSImm_LogF:
|
||||
return FuncCast<float (float)>(logf);
|
||||
return RedirectCall(FuncCast<float (float)>(logf), Args_Float32_Float32);
|
||||
case AsmJSImm_PowD:
|
||||
return FuncCast(ecmaPow);
|
||||
return RedirectCall(FuncCast(ecmaPow), Args_Double_DoubleDouble);
|
||||
case AsmJSImm_ATan2D:
|
||||
return FuncCast(ecmaAtan2);
|
||||
return RedirectCall(FuncCast(ecmaAtan2), Args_Double_DoubleDouble);
|
||||
case AsmJSImm_Invalid:
|
||||
break;
|
||||
}
|
||||
|
@ -332,6 +332,29 @@ static bool IsSignalHandlingBroken() { return false; }
|
||||
# define PC_sig(p) R15_sig(p)
|
||||
#endif
|
||||
|
||||
static bool
|
||||
HandleSimulatorInterrupt(JSRuntime *rt, AsmJSActivation *activation, void *faultingAddress)
|
||||
{
|
||||
// If the ARM simulator is enabled, the pc is in the simulator C++ code and
|
||||
// not in the generated code, so we check the simulator's pc manually. Also
|
||||
// note that we can't simply use simulator->set_pc() here because the
|
||||
// simulator could be in the middle of an instruction. On ARM, the signal
|
||||
// handlers are currently only used for Odin code, see bug 964258.
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
const AsmJSModule &module = activation->module();
|
||||
if (module.containsPC((void *)rt->mainThread.simulator()->get_pc()) &&
|
||||
module.containsPC(faultingAddress))
|
||||
{
|
||||
activation->setResumePC(nullptr);
|
||||
int32_t nextpc = int32_t(module.operationCallbackExit());
|
||||
rt->mainThread.simulator()->set_resume_pc(nextpc);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !defined(XP_MACOSX)
|
||||
static uint8_t **
|
||||
ContextToPC(CONTEXT *context)
|
||||
@ -621,6 +644,11 @@ HandleMachException(JSRuntime *rt, const ExceptionRequest &request)
|
||||
return false;
|
||||
|
||||
const AsmJSModule &module = activation->module();
|
||||
if (HandleSimulatorInterrupt(rt, activation, faultingAddress)) {
|
||||
mprotect(module.codeBase(), module.functionBytes(), PROT_EXEC);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!module.containsPC(pc))
|
||||
return false;
|
||||
|
||||
@ -863,6 +891,11 @@ HandleSignal(int signum, siginfo_t *info, void *ctx)
|
||||
return false;
|
||||
|
||||
const AsmJSModule &module = activation->module();
|
||||
if (HandleSimulatorInterrupt(rt, activation, faultingAddress)) {
|
||||
mprotect(module.codeBase(), module.functionBytes(), PROT_EXEC);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!module.containsPC(pc))
|
||||
return false;
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "jit/arm/Simulator-arm.h"
|
||||
#include "jit/BaselineIC.h"
|
||||
#include "jit/BaselineJIT.h"
|
||||
#include "jit/CompileInfo.h"
|
||||
@ -1336,7 +1337,12 @@ jit::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, IonBailoutIt
|
||||
// Do stack check.
|
||||
bool overRecursed = false;
|
||||
uint8_t *newsp = info->incomingStack - (info->copyStackTop - info->copyStackBottom);
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
if (Simulator::Current()->overRecursed(uintptr_t(newsp)))
|
||||
overRecursed = true;
|
||||
#else
|
||||
JS_CHECK_RECURSION_WITH_SP_DONT_REPORT(cx, newsp, overRecursed = true);
|
||||
#endif
|
||||
if (overRecursed) {
|
||||
IonSpew(IonSpew_BaselineBailouts, " Overrecursion check failed!");
|
||||
return BAILOUT_RETURN_OVERRECURSED;
|
||||
|
@ -8722,7 +8722,15 @@ ICCall_Native::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
masm.passABIArg(scratch);
|
||||
masm.passABIArg(argcReg);
|
||||
masm.passABIArg(vpReg);
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
// The simulator requires VM calls to be redirected to a special swi
|
||||
// instruction to handle them, so we store the redirected pointer in the
|
||||
// stub and use that instead of the original one.
|
||||
masm.callWithABI(Address(BaselineStubReg, ICCall_Native::offsetOfNative()));
|
||||
#else
|
||||
masm.callWithABI(Address(callee, JSFunction::offsetOfNativeOrScript()));
|
||||
#endif
|
||||
|
||||
// Test for failure.
|
||||
masm.branchIfFalseBool(ReturnReg, masm.exceptionLabel());
|
||||
@ -9832,7 +9840,15 @@ ICCall_Native::ICCall_Native(JitCode *stubCode, ICStub *firstMonitorStub,
|
||||
callee_(callee),
|
||||
templateObject_(templateObject),
|
||||
pcOffset_(pcOffset)
|
||||
{ }
|
||||
{
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
// The simulator requires VM calls to be redirected to a special swi
|
||||
// instruction to handle them. To make this work, we store the redirected
|
||||
// pointer in the stub.
|
||||
native_ = Simulator::RedirectNativeFunction(JS_FUNC_TO_DATA_PTR(void *, callee->native()),
|
||||
Args_General3);
|
||||
#endif
|
||||
}
|
||||
|
||||
ICGetPropCallDOMProxyNativeStub::ICGetPropCallDOMProxyNativeStub(Kind kind, JitCode *stubCode,
|
||||
ICStub *firstMonitorStub,
|
||||
|
@ -5414,6 +5414,10 @@ class ICCall_Native : public ICMonitoredStub
|
||||
HeapPtrObject templateObject_;
|
||||
uint32_t pcOffset_;
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
void *native_;
|
||||
#endif
|
||||
|
||||
ICCall_Native(JitCode *stubCode, ICStub *firstMonitorStub,
|
||||
HandleFunction callee, HandleObject templateObject,
|
||||
uint32_t pcOffset);
|
||||
@ -5443,6 +5447,12 @@ class ICCall_Native : public ICMonitoredStub
|
||||
return offsetof(ICCall_Native, pcOffset_);
|
||||
}
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
static size_t offsetOfNative() {
|
||||
return offsetof(ICCall_Native, native_);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICCallStubCompiler {
|
||||
protected:
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "jit/BaselineIC.h"
|
||||
#include "jit/CompileInfo.h"
|
||||
#include "jit/IonSpewer.h"
|
||||
#include "jit/JitCommon.h"
|
||||
#include "vm/Interpreter.h"
|
||||
|
||||
#include "jsgcinlines.h"
|
||||
@ -118,8 +119,8 @@ EnterBaseline(JSContext *cx, EnterJitData &data)
|
||||
JS_ASSERT_IF(data.osrFrame, !IsJSDEnabled(cx));
|
||||
|
||||
// Single transition point from Interpreter to Baseline.
|
||||
enter(data.jitcode, data.maxArgc, data.maxArgv, data.osrFrame, data.calleeToken,
|
||||
data.scopeChain, data.osrNumStackValues, data.result.address());
|
||||
CALL_GENERATED_CODE(enter, data.jitcode, data.maxArgc, data.maxArgv, data.osrFrame, data.calleeToken,
|
||||
data.scopeChain.get(), data.osrNumStackValues, data.result.address());
|
||||
|
||||
if (data.osrFrame)
|
||||
data.osrFrame->clearRunningInJit();
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "jit/IonBuilder.h"
|
||||
#include "jit/IonOptimizationLevels.h"
|
||||
#include "jit/IonSpewer.h"
|
||||
#include "jit/JitCommon.h"
|
||||
#include "jit/JitCompartment.h"
|
||||
#include "jit/LICM.h"
|
||||
#include "jit/LinearScan.h"
|
||||
@ -2231,9 +2232,8 @@ EnterIon(JSContext *cx, EnterJitData &data)
|
||||
JSAutoResolveFlags rf(cx, RESOLVE_INFER);
|
||||
AutoFlushInhibitor afi(cx->runtime()->jitRuntime());
|
||||
|
||||
// Single transition point from Interpreter to Baseline.
|
||||
enter(data.jitcode, data.maxArgc, data.maxArgv, /* osrFrame = */nullptr, data.calleeToken,
|
||||
/* scopeChain = */ nullptr, 0, data.result.address());
|
||||
CALL_GENERATED_CODE(enter, data.jitcode, data.maxArgc, data.maxArgv, /* osrFrame = */nullptr, data.calleeToken,
|
||||
/* scopeChain = */ nullptr, 0, data.result.address());
|
||||
}
|
||||
|
||||
JS_ASSERT(!cx->runtime()->hasIonReturnOverride());
|
||||
@ -2342,8 +2342,9 @@ jit::FastInvoke(JSContext *cx, HandleFunction fun, CallArgs &args)
|
||||
JS_ASSERT(args.length() >= fun->nargs());
|
||||
|
||||
JSAutoResolveFlags rf(cx, RESOLVE_INFER);
|
||||
enter(jitcode, args.length() + 1, args.array() - 1, nullptr, calleeToken,
|
||||
/* scopeChain = */ nullptr, 0, result.address());
|
||||
|
||||
CALL_GENERATED_CODE(enter, jitcode, args.length() + 1, args.array() - 1, /* osrFrame = */nullptr,
|
||||
calleeToken, /* scopeChain = */ nullptr, 0, result.address());
|
||||
|
||||
JS_ASSERT(!cx->runtime()->hasIonReturnOverride());
|
||||
|
||||
|
@ -244,6 +244,64 @@ IsNullOrUndefined(MIRType type)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
enum {
|
||||
ArgType_General = 0x1,
|
||||
ArgType_Double = 0x2,
|
||||
ArgType_Float32 = 0x3,
|
||||
|
||||
RetType_Shift = 0x0,
|
||||
ArgType_Shift = 0x2,
|
||||
ArgType_Mask = 0x3
|
||||
};
|
||||
|
||||
enum ABIFunctionType
|
||||
{
|
||||
// VM functions that take 0-9 non-double arguments
|
||||
// and return a non-double value.
|
||||
Args_General0 = ArgType_General << RetType_Shift,
|
||||
Args_General1 = Args_General0 | (ArgType_General << (ArgType_Shift * 1)),
|
||||
Args_General2 = Args_General1 | (ArgType_General << (ArgType_Shift * 2)),
|
||||
Args_General3 = Args_General2 | (ArgType_General << (ArgType_Shift * 3)),
|
||||
Args_General4 = Args_General3 | (ArgType_General << (ArgType_Shift * 4)),
|
||||
Args_General5 = Args_General4 | (ArgType_General << (ArgType_Shift * 5)),
|
||||
Args_General6 = Args_General5 | (ArgType_General << (ArgType_Shift * 6)),
|
||||
Args_General7 = Args_General6 | (ArgType_General << (ArgType_Shift * 7)),
|
||||
Args_General8 = Args_General7 | (ArgType_General << (ArgType_Shift * 8)),
|
||||
|
||||
// double f()
|
||||
Args_Double_None = ArgType_Double << RetType_Shift,
|
||||
|
||||
// int f(double)
|
||||
Args_Int_Double = Args_General0 | (ArgType_Double << ArgType_Shift),
|
||||
|
||||
// float f(float)
|
||||
Args_Float32_Float32 = (ArgType_Float32 << RetType_Shift) | (ArgType_Float32 << ArgType_Shift),
|
||||
|
||||
// double f(double)
|
||||
Args_Double_Double = Args_Double_None | (ArgType_Double << ArgType_Shift),
|
||||
|
||||
// double f(int)
|
||||
Args_Double_Int = Args_Double_None | (ArgType_General << ArgType_Shift),
|
||||
|
||||
// double f(double, int)
|
||||
Args_Double_DoubleInt = Args_Double_None |
|
||||
(ArgType_General << (ArgType_Shift * 1)) |
|
||||
(ArgType_Double << (ArgType_Shift * 2)),
|
||||
|
||||
// double f(double, double)
|
||||
Args_Double_DoubleDouble = Args_Double_Double | (ArgType_Double << (ArgType_Shift * 2)),
|
||||
|
||||
// double f(int, double)
|
||||
Args_Double_IntDouble = Args_Double_None |
|
||||
(ArgType_Double << (ArgType_Shift * 1)) |
|
||||
(ArgType_General << (ArgType_Shift * 2)),
|
||||
|
||||
// int f(int, double)
|
||||
Args_Int_IntDouble = Args_General0 |
|
||||
(ArgType_Double << (ArgType_Shift * 1)) |
|
||||
(ArgType_General << (ArgType_Shift * 2))
|
||||
};
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
|
46
js/src/jit/JitCommon.h
Normal file
46
js/src/jit/JitCommon.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef jit_JitCommon_h
|
||||
#define jit_JitCommon_h
|
||||
|
||||
// Various macros used by all JITs, including YARR.
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
#include "jit/arm/Simulator-arm.h"
|
||||
|
||||
// Call into cross-jitted code by following the ABI of the simulated architecture.
|
||||
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \
|
||||
(js::jit::Simulator::Current()->call( \
|
||||
JS_FUNC_TO_DATA_PTR(uint8_t *, entry), 8, p0, p1, p2, p3, p4, p5, p6, p7) & 0xffffffff)
|
||||
|
||||
#define CALL_GENERATED_YARR_CODE3(entry, p0, p1, p2) \
|
||||
js::jit::Simulator::Current()->call(JS_FUNC_TO_DATA_PTR(uint8_t *, entry), 3, p0, p1, p2)
|
||||
|
||||
#define CALL_GENERATED_YARR_CODE4(entry, p0, p1, p2, p3) \
|
||||
js::jit::Simulator::Current()->call(JS_FUNC_TO_DATA_PTR(uint8_t *, entry), 4, p0, p1, p2, p3)
|
||||
|
||||
#define CALL_GENERATED_ASMJS(entry, p0, p1) \
|
||||
(Simulator::Current()->call(JS_FUNC_TO_DATA_PTR(uint8_t *, entry), 2, p0, p1) & 0xffffffff)
|
||||
|
||||
#else
|
||||
|
||||
// Call into jitted code by following the ABI of the native architecture.
|
||||
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \
|
||||
entry(p0, p1, p2, p3, p4, p5, p6, p7)
|
||||
|
||||
#define CALL_GENERATED_YARR_CODE3(entry, p0, p1, p2) \
|
||||
entry(p0, p1, p2)
|
||||
|
||||
#define CALL_GENERATED_YARR_CODE4(entry, p0, p1, p2, p3) \
|
||||
entry(p0, p1, p2, p3)
|
||||
|
||||
#define CALL_GENERATED_ASMJS(entry, p0, p1) \
|
||||
entry(p0, p1)
|
||||
|
||||
#endif
|
||||
|
||||
#endif // jit_JitCommon_h
|
@ -7,6 +7,7 @@
|
||||
#include "jit/ParallelFunctions.h"
|
||||
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "jit/arm/Simulator-arm.h"
|
||||
#include "vm/ArrayObject.h"
|
||||
|
||||
#include "jsgcinlines.h"
|
||||
@ -190,6 +191,13 @@ jit::CheckOverRecursedPar(ForkJoinSlice *slice)
|
||||
// limit, but we do still call into this routine if the interrupt
|
||||
// flag is set, so we still need to double check.
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
if (Simulator::Current()->overRecursed()) {
|
||||
slice->bailoutRecord->setCause(ParallelBailoutOverRecursed);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
uintptr_t realStackLimit;
|
||||
if (slice->isMainThread())
|
||||
realStackLimit = GetNativeStackLimit(slice);
|
||||
|
@ -31,6 +31,11 @@ struct Register {
|
||||
Register r = { (Registers::Code)i };
|
||||
return r;
|
||||
}
|
||||
static Register FromName(const char *name) {
|
||||
Registers::Code code = Registers::FromName(name);
|
||||
Register r = { code };
|
||||
return r;
|
||||
}
|
||||
Code code() const {
|
||||
JS_ASSERT((uint32_t)code_ < Registers::Total);
|
||||
return code_;
|
||||
@ -60,6 +65,11 @@ struct FloatRegister {
|
||||
FloatRegister r = { (FloatRegisters::Code)i };
|
||||
return r;
|
||||
}
|
||||
static FloatRegister FromName(const char *name) {
|
||||
FloatRegisters::Code code = FloatRegisters::FromName(name);
|
||||
FloatRegister r = { code };
|
||||
return r;
|
||||
}
|
||||
Code code() const {
|
||||
JS_ASSERT((uint32_t)code_ < FloatRegisters::Total);
|
||||
return code_;
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "jit/arm/Simulator-arm.h"
|
||||
#include "jit/BaselineIC.h"
|
||||
#include "jit/IonFrames.h"
|
||||
#include "jit/JitCompartment.h"
|
||||
@ -119,7 +120,11 @@ CheckOverRecursed(JSContext *cx)
|
||||
// has not yet been set to 1. That's okay; it will be set to 1 very shortly,
|
||||
// and in the interim we might just fire a few useless calls to
|
||||
// CheckOverRecursed.
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, 0, return false);
|
||||
#else
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
#endif
|
||||
|
||||
if (cx->runtime()->interrupt)
|
||||
return InterruptCheck(cx);
|
||||
@ -148,7 +153,12 @@ CheckOverRecursedWithExtra(JSContext *cx, BaselineFrame *frame,
|
||||
uint8_t spDummy;
|
||||
uint8_t *checkSp = (&spDummy) - extra;
|
||||
if (earlyCheck) {
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
(void)checkSp;
|
||||
JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, extra, frame->setOverRecursed());
|
||||
#else
|
||||
JS_CHECK_RECURSION_WITH_SP(cx, checkSp, frame->setOverRecursed());
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -157,7 +167,11 @@ CheckOverRecursedWithExtra(JSContext *cx, BaselineFrame *frame,
|
||||
if (frame->overRecursed())
|
||||
return false;
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, extra, return false);
|
||||
#else
|
||||
JS_CHECK_RECURSION_WITH_SP(cx, checkSp, return false);
|
||||
#endif
|
||||
|
||||
if (cx->runtime()->interrupt)
|
||||
return InterruptCheck(cx);
|
||||
|
@ -6,13 +6,16 @@
|
||||
|
||||
#include "jit/arm/Architecture-arm.h"
|
||||
|
||||
#ifndef JS_ARM_SIMULATOR
|
||||
#include <elf.h>
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "jit/arm/Assembler-arm.h"
|
||||
|
||||
#if !(defined(ANDROID) || defined(MOZ_B2G))
|
||||
#if !(defined(ANDROID) || defined(MOZ_B2G)) && !defined(JS_ARM_SIMULATOR)
|
||||
#define HWCAP_ARMv7 (1 << 29)
|
||||
#include <asm/hwcap.h>
|
||||
#else
|
||||
@ -36,6 +39,12 @@ uint32_t GetARMFlags()
|
||||
if (isSet)
|
||||
return flags;
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
isSet = true;
|
||||
flags = HWCAP_ARMv7 | HWCAP_VFP | HWCAP_VFPv4 | HWCAP_NEON;
|
||||
return flags;
|
||||
#else
|
||||
|
||||
#if WTF_OS_LINUX
|
||||
int fd = open("/proc/self/auxv", O_RDONLY);
|
||||
if (fd > 0) {
|
||||
@ -105,6 +114,7 @@ uint32_t GetARMFlags()
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
#endif // JS_ARM_SIMULATOR
|
||||
}
|
||||
|
||||
bool hasMOVWT()
|
||||
@ -138,6 +148,37 @@ bool hasIDIV()
|
||||
#endif
|
||||
}
|
||||
|
||||
Registers::Code
|
||||
Registers::FromName(const char *name)
|
||||
{
|
||||
// Check for some register aliases first.
|
||||
if (strcmp(name, "ip") == 0)
|
||||
return ip;
|
||||
if (strcmp(name, "r13") == 0)
|
||||
return r13;
|
||||
if (strcmp(name, "lr") == 0)
|
||||
return lr;
|
||||
if (strcmp(name, "r15") == 0)
|
||||
return r15;
|
||||
|
||||
for (size_t i = 0; i < Total; i++) {
|
||||
if (strcmp(GetName(i), name) == 0)
|
||||
return Code(i);
|
||||
}
|
||||
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
FloatRegisters::Code
|
||||
FloatRegisters::FromName(const char *name)
|
||||
{
|
||||
for (size_t i = 0; i < Total; i++) {
|
||||
if (strcmp(GetName(i), name) == 0)
|
||||
return Code(i);
|
||||
}
|
||||
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "js/Utility.h"
|
||||
|
||||
// gcc appears to use __ARM_PCS_VFP to denote that the target is a hard-float target.
|
||||
#ifdef __ARM_PCS_VFP
|
||||
#define JS_CODEGEN_ARM_HARDFP
|
||||
@ -75,6 +77,12 @@ class Registers
|
||||
"r8", "r9", "r10", "r11", "r12", "sp", "r14", "pc"};
|
||||
return Names[code];
|
||||
}
|
||||
static const char *GetName(uint32_t i) {
|
||||
MOZ_ASSERT(i < Total);
|
||||
return GetName(Code(i));
|
||||
}
|
||||
|
||||
static Code FromName(const char *name);
|
||||
|
||||
static const Code StackPointer = sp;
|
||||
static const Code Invalid = invalid_reg;
|
||||
@ -180,6 +188,12 @@ class FloatRegisters
|
||||
"d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15"};
|
||||
return Names[code];
|
||||
}
|
||||
static const char *GetName(uint32_t i) {
|
||||
JS_ASSERT(i < Total);
|
||||
return GetName(Code(i));
|
||||
}
|
||||
|
||||
static Code FromName(const char *name);
|
||||
|
||||
static const Code Invalid = invalid_freg;
|
||||
|
||||
|
@ -1021,15 +1021,6 @@ class Imm16
|
||||
}
|
||||
};
|
||||
|
||||
// FP Instructions use a different set of registers,
|
||||
// with a different encoding, so this calls for a different class.
|
||||
// which will be implemented later
|
||||
// IIRC, this has been subsumed by vfpreg.
|
||||
class FloatOp
|
||||
{
|
||||
uint32_t data;
|
||||
};
|
||||
|
||||
/* I would preffer that these do not exist, since there are essentially
|
||||
* no instructions that would ever take more than one of these, however,
|
||||
* the MIR wants to only have one type of arguments to functions, so bugger.
|
||||
|
@ -71,7 +71,7 @@ ICCompare_Double::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
// ICBinaryArith_Int32
|
||||
|
||||
extern "C" {
|
||||
extern int __aeabi_idivmod(int,int);
|
||||
extern int64_t __aeabi_idivmod(int,int);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -609,8 +609,8 @@ CodeGeneratorARM::visitDivI(LDivI *ins)
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
extern int __aeabi_idivmod(int,int);
|
||||
extern int __aeabi_uidivmod(int,int);
|
||||
extern int64_t __aeabi_idivmod(int,int);
|
||||
extern int64_t __aeabi_uidivmod(int,int);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -204,6 +204,7 @@ typedef CodeGeneratorARM CodeGeneratorSpecific;
|
||||
// An out-of-line bailout thunk.
|
||||
class OutOfLineBailout : public OutOfLineCodeBase<CodeGeneratorARM>
|
||||
{
|
||||
protected: // Silence Clang warning.
|
||||
LSnapshot *snapshot_;
|
||||
uint32_t frameSize_;
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
|
||||
#include "jit/arm/Simulator-arm.h"
|
||||
#include "jit/Bailouts.h"
|
||||
#include "jit/BaselineFrame.h"
|
||||
#include "jit/MoveEmitter.h"
|
||||
@ -3479,6 +3480,7 @@ MacroAssemblerARMCompat::setupABICall(uint32_t args)
|
||||
inCall_ = true;
|
||||
args_ = args;
|
||||
passedArgs_ = 0;
|
||||
passedArgTypes_ = 0;
|
||||
#ifdef JS_CODEGEN_ARM_HARDFP
|
||||
usedIntSlots_ = 0;
|
||||
usedFloatSlots_ = 0;
|
||||
@ -3512,6 +3514,7 @@ MacroAssemblerARMCompat::setupUnalignedABICall(uint32_t args, const Register &sc
|
||||
ma_and(Imm32(~(StackAlignment - 1)), sp, sp);
|
||||
ma_push(scratch);
|
||||
}
|
||||
|
||||
#ifdef JS_CODEGEN_ARM_HARDFP
|
||||
void
|
||||
MacroAssemblerARMCompat::passABIArg(const MoveOperand &from, MoveOp::Type type)
|
||||
@ -3537,6 +3540,10 @@ MacroAssemblerARMCompat::passABIArg(const MoveOperand &from, MoveOp::Type type)
|
||||
to = MoveOperand(sp, disp);
|
||||
}
|
||||
usedFloatSlots_++;
|
||||
if (type == MoveOp::FLOAT32)
|
||||
passedArgTypes_ = (passedArgTypes_ << ArgType_Shift) | ArgType_Float32;
|
||||
else
|
||||
passedArgTypes_ = (passedArgTypes_ << ArgType_Shift) | ArgType_Double;
|
||||
break;
|
||||
}
|
||||
case MoveOp::GENERAL: {
|
||||
@ -3552,6 +3559,7 @@ MacroAssemblerARMCompat::passABIArg(const MoveOperand &from, MoveOp::Type type)
|
||||
to = MoveOperand(sp, disp);
|
||||
}
|
||||
usedIntSlots_++;
|
||||
passedArgTypes_ = (passedArgTypes_ << ArgType_Shift) | ArgType_General;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -3575,9 +3583,13 @@ MacroAssemblerARMCompat::passABIArg(const MoveOperand &from, MoveOp::Type type)
|
||||
// boundary, even if it is in a register!
|
||||
usedSlots_ = (usedSlots_ + 1) & ~1;
|
||||
increment = 2;
|
||||
passedArgTypes_ = (passedArgTypes_ << ArgType_Shift) | ArgType_Double;
|
||||
break;
|
||||
case MoveOp::FLOAT32:
|
||||
passedArgTypes_ = (passedArgTypes_ << ArgType_Shift) | ArgType_Float32;
|
||||
break;
|
||||
case MoveOp::GENERAL:
|
||||
passedArgTypes_ = (passedArgTypes_ << ArgType_Shift) | ArgType_General;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("Unexpected argument type");
|
||||
@ -3723,9 +3735,53 @@ MacroAssemblerARMCompat::callWithABIPost(uint32_t stackAdjust, MoveOp::Type resu
|
||||
inCall_ = false;
|
||||
}
|
||||
|
||||
#if defined(DEBUG) && defined(JS_ARM_SIMULATOR)
|
||||
static void
|
||||
AssertValidABIFunctionType(uint32_t passedArgTypes)
|
||||
{
|
||||
switch (passedArgTypes) {
|
||||
case Args_General0:
|
||||
case Args_General1:
|
||||
case Args_General2:
|
||||
case Args_General3:
|
||||
case Args_General4:
|
||||
case Args_General5:
|
||||
case Args_General6:
|
||||
case Args_General7:
|
||||
case Args_General8:
|
||||
case Args_Double_None:
|
||||
case Args_Int_Double:
|
||||
case Args_Float32_Float32:
|
||||
case Args_Double_Double:
|
||||
case Args_Double_Int:
|
||||
case Args_Double_DoubleInt:
|
||||
case Args_Double_DoubleDouble:
|
||||
case Args_Double_IntDouble:
|
||||
case Args_Int_IntDouble:
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("Unexpected type");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
MacroAssemblerARMCompat::callWithABI(void *fun, MoveOp::Type result)
|
||||
{
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
MOZ_ASSERT(passedArgs_ <= 15);
|
||||
passedArgTypes_ <<= ArgType_Shift;
|
||||
switch (result) {
|
||||
case MoveOp::GENERAL: passedArgTypes_ |= ArgType_General; break;
|
||||
case MoveOp::DOUBLE: passedArgTypes_ |= ArgType_Double; break;
|
||||
case MoveOp::FLOAT32: passedArgTypes_ |= ArgType_Float32; break;
|
||||
default: MOZ_ASSUME_UNREACHABLE("Invalid return type");
|
||||
}
|
||||
AssertValidABIFunctionType(passedArgTypes_);
|
||||
ABIFunctionType type = ABIFunctionType(passedArgTypes_);
|
||||
fun = Simulator::RedirectNativeFunction(fun, type);
|
||||
#endif
|
||||
|
||||
uint32_t stackAdjust;
|
||||
callWithABIPre(&stackAdjust);
|
||||
ma_call(ImmPtr(fun));
|
||||
|
@ -443,6 +443,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
|
||||
// The actual number of arguments that were passed, used to assert that
|
||||
// the initial number of arguments declared was correct.
|
||||
uint32_t passedArgs_;
|
||||
uint32_t passedArgTypes_;
|
||||
|
||||
#ifdef JS_CODEGEN_ARM_HARDFP
|
||||
uint32_t usedIntSlots_;
|
||||
|
4040
js/src/jit/arm/Simulator-arm.cpp
Normal file
4040
js/src/jit/arm/Simulator-arm.cpp
Normal file
File diff suppressed because it is too large
Load Diff
364
js/src/jit/arm/Simulator-arm.h
Normal file
364
js/src/jit/arm/Simulator-arm.h
Normal file
@ -0,0 +1,364 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef jit_arm_Simulator_arm_h
|
||||
#define jit_arm_Simulator_arm_h
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
|
||||
#include "jit/IonTypes.h"
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
class SimulatorRuntime;
|
||||
SimulatorRuntime *CreateSimulatorRuntime();
|
||||
void DestroySimulatorRuntime(SimulatorRuntime *srt);
|
||||
|
||||
// VFP rounding modes. See ARM DDI 0406B Page A2-29.
|
||||
enum VFPRoundingMode {
|
||||
SimRN = 0 << 22, // Round to Nearest.
|
||||
SimRP = 1 << 22, // Round towards Plus Infinity.
|
||||
SimRM = 2 << 22, // Round towards Minus Infinity.
|
||||
SimRZ = 3 << 22, // Round towards zero.
|
||||
|
||||
// Aliases.
|
||||
kRoundToNearest = SimRN,
|
||||
kRoundToPlusInf = SimRP,
|
||||
kRoundToMinusInf = SimRM,
|
||||
kRoundToZero = SimRZ
|
||||
};
|
||||
|
||||
const uint32_t kVFPRoundingModeMask = 3 << 22;
|
||||
|
||||
typedef int32_t Instr;
|
||||
class SimInstruction;
|
||||
|
||||
class Simulator
|
||||
{
|
||||
friend class Redirection;
|
||||
|
||||
public:
|
||||
friend class ArmDebugger;
|
||||
enum Register {
|
||||
no_reg = -1,
|
||||
r0 = 0, r1, r2, r3, r4, r5, r6, r7,
|
||||
r8, r9, r10, r11, r12, r13, r14, r15,
|
||||
num_registers,
|
||||
sp = 13,
|
||||
lr = 14,
|
||||
pc = 15,
|
||||
s0 = 0, s1, s2, s3, s4, s5, s6, s7,
|
||||
s8, s9, s10, s11, s12, s13, s14, s15,
|
||||
s16, s17, s18, s19, s20, s21, s22, s23,
|
||||
s24, s25, s26, s27, s28, s29, s30, s31,
|
||||
num_s_registers = 32,
|
||||
d0 = 0, d1, d2, d3, d4, d5, d6, d7,
|
||||
d8, d9, d10, d11, d12, d13, d14, d15,
|
||||
d16, d17, d18, d19, d20, d21, d22, d23,
|
||||
d24, d25, d26, d27, d28, d29, d30, d31,
|
||||
num_d_registers = 32,
|
||||
q0 = 0, q1, q2, q3, q4, q5, q6, q7,
|
||||
q8, q9, q10, q11, q12, q13, q14, q15,
|
||||
num_q_registers = 16
|
||||
};
|
||||
|
||||
explicit Simulator(SimulatorRuntime *srt);
|
||||
~Simulator();
|
||||
|
||||
// The currently executing Simulator instance. Potentially there can be one
|
||||
// for each native thread.
|
||||
static Simulator *Current();
|
||||
|
||||
static inline uintptr_t StackLimit() {
|
||||
return Simulator::Current()->stackLimit();
|
||||
}
|
||||
|
||||
// Accessors for register state. Reading the pc value adheres to the ARM
|
||||
// architecture specification and is off by a 8 from the currently executing
|
||||
// instruction.
|
||||
void set_register(int reg, int32_t value);
|
||||
int32_t get_register(int reg) const;
|
||||
double get_double_from_register_pair(int reg);
|
||||
void set_register_pair_from_double(int reg, double* value);
|
||||
void set_dw_register(int dreg, const int* dbl);
|
||||
|
||||
// Support for VFP.
|
||||
void get_d_register(int dreg, uint64_t* value);
|
||||
void set_d_register(int dreg, const uint64_t* value);
|
||||
void get_d_register(int dreg, uint32_t* value);
|
||||
void set_d_register(int dreg, const uint32_t* value);
|
||||
void get_q_register(int qreg, uint64_t* value);
|
||||
void set_q_register(int qreg, const uint64_t* value);
|
||||
void get_q_register(int qreg, uint32_t* value);
|
||||
void set_q_register(int qreg, const uint32_t* value);
|
||||
void set_s_register(int reg, unsigned int value);
|
||||
unsigned int get_s_register(int reg) const;
|
||||
|
||||
void set_d_register_from_double(int dreg, const double& dbl) {
|
||||
setVFPRegister<double, 2>(dreg, dbl);
|
||||
}
|
||||
double get_double_from_d_register(int dreg) {
|
||||
return getFromVFPRegister<double, 2>(dreg);
|
||||
}
|
||||
void set_s_register_from_float(int sreg, const float flt) {
|
||||
setVFPRegister<float, 1>(sreg, flt);
|
||||
}
|
||||
float get_float_from_s_register(int sreg) {
|
||||
return getFromVFPRegister<float, 1>(sreg);
|
||||
}
|
||||
void set_s_register_from_sinteger(int sreg, const int sint) {
|
||||
setVFPRegister<int, 1>(sreg, sint);
|
||||
}
|
||||
int get_sinteger_from_s_register(int sreg) {
|
||||
return getFromVFPRegister<int, 1>(sreg);
|
||||
}
|
||||
|
||||
// Special case of set_register and get_register to access the raw PC value.
|
||||
void set_pc(int32_t value);
|
||||
int32_t get_pc() const;
|
||||
|
||||
void set_resume_pc(int32_t value) {
|
||||
resume_pc_ = value;
|
||||
}
|
||||
|
||||
uintptr_t stackLimit() const;
|
||||
bool overRecursed(uintptr_t newsp = 0) const;
|
||||
bool overRecursedWithExtra(uint32_t extra) const;
|
||||
|
||||
// Executes ARM instructions until the PC reaches end_sim_pc.
|
||||
void execute();
|
||||
|
||||
// Sets up the simulator state and grabs the result on return.
|
||||
int64_t call(uint8_t* entry, int argument_count, ...);
|
||||
|
||||
// Debugger input.
|
||||
void setLastDebuggerInput(char *input);
|
||||
char *lastDebuggerInput() { return lastDebuggerInput_; }
|
||||
|
||||
// Returns true if pc register contains one of the 'special_values' defined
|
||||
// below (bad_lr, end_sim_pc).
|
||||
bool has_bad_pc() const;
|
||||
|
||||
// EABI variant for double arguments in use.
|
||||
bool use_eabi_hardfloat() {
|
||||
#if USE_EABI_HARDFLOAT
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
enum special_values {
|
||||
// Known bad pc value to ensure that the simulator does not execute
|
||||
// without being properly setup.
|
||||
bad_lr = -1,
|
||||
// A pc value used to signal the simulator to stop execution. Generally
|
||||
// the lr is set to this value on transition from native C code to
|
||||
// simulated execution, so that the simulator can "return" to the native
|
||||
// C code.
|
||||
end_sim_pc = -2
|
||||
};
|
||||
|
||||
// Checks if the current instruction should be executed based on its
|
||||
// condition bits.
|
||||
inline bool conditionallyExecute(SimInstruction* instr);
|
||||
|
||||
// Helper functions to set the conditional flags in the architecture state.
|
||||
void setNZFlags(int32_t val);
|
||||
void setCFlag(bool val);
|
||||
void setVFlag(bool val);
|
||||
bool carryFrom(int32_t left, int32_t right, int32_t carry = 0);
|
||||
bool borrowFrom(int32_t left, int32_t right);
|
||||
bool overflowFrom(int32_t alu_out, int32_t left, int32_t right, bool addition);
|
||||
|
||||
inline int getCarry() { return c_flag_ ? 1 : 0; };
|
||||
|
||||
// Support for VFP.
|
||||
void compute_FPSCR_Flags(double val1, double val2);
|
||||
void copy_FPSCR_to_APSR();
|
||||
inline double canonicalizeNaN(double value);
|
||||
|
||||
// Helper functions to decode common "addressing" modes
|
||||
int32_t getShiftRm(SimInstruction *instr, bool* carry_out);
|
||||
int32_t getImm(SimInstruction *instr, bool* carry_out);
|
||||
int32_t processPU(SimInstruction *instr, int num_regs, int operand_size,
|
||||
intptr_t *start_address, intptr_t *end_address);
|
||||
void handleRList(SimInstruction *instr, bool load);
|
||||
void handleVList(SimInstruction *inst);
|
||||
void softwareInterrupt(SimInstruction *instr);
|
||||
|
||||
// Stop helper functions.
|
||||
inline bool isStopInstruction(SimInstruction *instr);
|
||||
inline bool isWatchedStop(uint32_t bkpt_code);
|
||||
inline bool isEnabledStop(uint32_t bkpt_code);
|
||||
inline void enableStop(uint32_t bkpt_code);
|
||||
inline void disableStop(uint32_t bkpt_code);
|
||||
inline void increaseStopCounter(uint32_t bkpt_code);
|
||||
void printStopInfo(uint32_t code);
|
||||
|
||||
// Read and write memory.
|
||||
inline uint8_t readBU(int32_t addr);
|
||||
inline int8_t readB(int32_t addr);
|
||||
inline void writeB(int32_t addr, uint8_t value);
|
||||
inline void writeB(int32_t addr, int8_t value);
|
||||
|
||||
inline uint16_t readHU(int32_t addr, SimInstruction *instr);
|
||||
inline int16_t readH(int32_t addr, SimInstruction *instr);
|
||||
// Note: Overloaded on the sign of the value.
|
||||
inline void writeH(int32_t addr, uint16_t value, SimInstruction *instr);
|
||||
inline void writeH(int32_t addr, int16_t value, SimInstruction *instr);
|
||||
|
||||
inline int readW(int32_t addr, SimInstruction *instr);
|
||||
inline void writeW(int32_t addr, int value, SimInstruction *instr);
|
||||
|
||||
int32_t *readDW(int32_t addr);
|
||||
void writeDW(int32_t addr, int32_t value1, int32_t value2);
|
||||
|
||||
// Executing is handled based on the instruction type.
|
||||
// Both type 0 and type 1 rolled into one.
|
||||
void decodeType01(SimInstruction *instr);
|
||||
void decodeType2(SimInstruction *instr);
|
||||
void decodeType3(SimInstruction *instr);
|
||||
void decodeType4(SimInstruction *instr);
|
||||
void decodeType5(SimInstruction *instr);
|
||||
void decodeType6(SimInstruction *instr);
|
||||
void decodeType7(SimInstruction *instr);
|
||||
|
||||
// Support for VFP.
|
||||
void decodeTypeVFP(SimInstruction *instr);
|
||||
void decodeType6CoprocessorIns(SimInstruction *instr);
|
||||
void decodeSpecialCondition(SimInstruction *instr);
|
||||
|
||||
void decodeVMOVBetweenCoreAndSinglePrecisionRegisters(SimInstruction *instr);
|
||||
void decodeVCMP(SimInstruction *instr);
|
||||
void decodeVCVTBetweenDoubleAndSingle(SimInstruction *instr);
|
||||
void decodeVCVTBetweenFloatingPointAndInteger(SimInstruction *instr);
|
||||
|
||||
// Executes one instruction.
|
||||
void instructionDecode(SimInstruction *instr);
|
||||
|
||||
public:
|
||||
static bool ICacheCheckingEnabled;
|
||||
static void FlushICache(void *start, size_t size);
|
||||
|
||||
// Runtime call support.
|
||||
static void *RedirectNativeFunction(void *nativeFunction, ABIFunctionType type);
|
||||
|
||||
private:
|
||||
// Handle arguments and return value for runtime FP functions.
|
||||
void getFpArgs(double *x, double *y, int32_t *z);
|
||||
void setCallResultDouble(double result);
|
||||
void setCallResultFloat(float result);
|
||||
void setCallResult(int64_t res);
|
||||
|
||||
template<class ReturnType, int register_size>
|
||||
ReturnType getFromVFPRegister(int reg_index);
|
||||
|
||||
template<class InputType, int register_size>
|
||||
void setVFPRegister(int reg_index, const InputType& value);
|
||||
|
||||
void callInternal(uint8_t* entry);
|
||||
|
||||
// Architecture state.
|
||||
// Saturating instructions require a Q flag to indicate saturation.
|
||||
// There is currently no way to read the CPSR directly, and thus read the Q
|
||||
// flag, so this is left unimplemented.
|
||||
int32_t registers_[16];
|
||||
bool n_flag_;
|
||||
bool z_flag_;
|
||||
bool c_flag_;
|
||||
bool v_flag_;
|
||||
|
||||
// VFP architecture state.
|
||||
uint32_t vfp_registers_[num_d_registers * 2];
|
||||
bool n_flag_FPSCR_;
|
||||
bool z_flag_FPSCR_;
|
||||
bool c_flag_FPSCR_;
|
||||
bool v_flag_FPSCR_;
|
||||
|
||||
// VFP rounding mode. See ARM DDI 0406B Page A2-29.
|
||||
VFPRoundingMode FPSCR_rounding_mode_;
|
||||
bool FPSCR_default_NaN_mode_;
|
||||
|
||||
// VFP FP exception flags architecture state.
|
||||
bool inv_op_vfp_flag_;
|
||||
bool div_zero_vfp_flag_;
|
||||
bool overflow_vfp_flag_;
|
||||
bool underflow_vfp_flag_;
|
||||
bool inexact_vfp_flag_;
|
||||
|
||||
// Simulator support.
|
||||
char *stack_;
|
||||
bool pc_modified_;
|
||||
int icount_;
|
||||
|
||||
int32_t resume_pc_;
|
||||
|
||||
// Debugger input.
|
||||
char *lastDebuggerInput_;
|
||||
|
||||
// Registered breakpoints.
|
||||
SimInstruction *break_pc_;
|
||||
Instr break_instr_;
|
||||
|
||||
SimulatorRuntime *srt_;
|
||||
|
||||
// A stop is watched if its code is less than kNumOfWatchedStops.
|
||||
// Only watched stops support enabling/disabling and the counter feature.
|
||||
static const uint32_t kNumOfWatchedStops = 256;
|
||||
|
||||
// Breakpoint is disabled if bit 31 is set.
|
||||
static const uint32_t kStopDisabledBit = 1 << 31;
|
||||
|
||||
// A stop is enabled, meaning the simulator will stop when meeting the
|
||||
// instruction, if bit 31 of watched_stops_[code].count is unset.
|
||||
// The value watched_stops_[code].count & ~(1 << 31) indicates how many times
|
||||
// the breakpoint was hit or gone through.
|
||||
struct StopCountAndDesc {
|
||||
uint32_t count;
|
||||
char *desc;
|
||||
};
|
||||
StopCountAndDesc watched_stops_[kNumOfWatchedStops];
|
||||
};
|
||||
|
||||
#define JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, extra, onerror) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (cx->mainThread().simulator()->overRecursedWithExtra(extra)) { \
|
||||
js_ReportOverRecursed(cx); \
|
||||
onerror; \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
#endif /* JS_ARM_SIMULATOR */
|
||||
|
||||
#endif /* jit_arm_Simulator_arm_h */
|
@ -235,7 +235,7 @@ static int getId() {
|
||||
return NULL_ID;
|
||||
}
|
||||
#endif
|
||||
static void spewEntry(uint8_t *ptr, int length) {
|
||||
static inline void spewEntry(uint8_t *ptr, int length) {
|
||||
#if IS_LITTLE_ENDIAN
|
||||
for (int idx = 0; idx < length; idx++) {
|
||||
IonSpewCont(IonSpew_Pools, "%02x", ptr[length - idx - 1]);
|
||||
|
@ -36,6 +36,14 @@ class Registers {
|
||||
return Names[code];
|
||||
}
|
||||
|
||||
static Code FromName(const char *name) {
|
||||
for (size_t i = 0; i < Total; i++) {
|
||||
if (strcmp(GetName(Code(i)), name) == 0)
|
||||
return Code(i);
|
||||
}
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
static const Code StackPointer = JSC::X86Registers::esp;
|
||||
static const Code Invalid = JSC::X86Registers::invalid_reg;
|
||||
|
||||
@ -116,6 +124,14 @@ class FloatRegisters {
|
||||
return Names[code];
|
||||
}
|
||||
|
||||
static Code FromName(const char *name) {
|
||||
for (size_t i = 0; i < Total; i++) {
|
||||
if (strcmp(GetName(Code(i)), name) == 0)
|
||||
return Code(i);
|
||||
}
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
static const Code Invalid = JSC::X86Registers::invalid_xmm;
|
||||
|
||||
static const uint32_t Total = 16;
|
||||
|
@ -43,6 +43,14 @@ class Registers {
|
||||
return Names[code];
|
||||
}
|
||||
|
||||
static Code FromName(const char *name) {
|
||||
for (size_t i = 0; i < Total; i++) {
|
||||
if (strcmp(GetName(Code(i)), name) == 0)
|
||||
return Code(i);
|
||||
}
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
static const Code StackPointer = JSC::X86Registers::esp;
|
||||
static const Code Invalid = JSC::X86Registers::invalid_reg;
|
||||
|
||||
@ -105,6 +113,14 @@ class FloatRegisters {
|
||||
return Names[code];
|
||||
}
|
||||
|
||||
static Code FromName(const char *name) {
|
||||
for (size_t i = 0; i < Total; i++) {
|
||||
if (strcmp(GetName(Code(i)), name) == 0)
|
||||
return Code(i);
|
||||
}
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
static const Code Invalid = JSC::X86Registers::invalid_xmm;
|
||||
|
||||
static const uint32_t Total = 8;
|
||||
|
@ -62,6 +62,7 @@
|
||||
#include "frontend/Parser.h" // for JS_BufferIsCompileableUnit
|
||||
#include "gc/Marking.h"
|
||||
#include "jit/AsmJSLink.h"
|
||||
#include "jit/JitCommon.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/SliceBudget.h"
|
||||
#include "js/StructuredClone.h"
|
||||
@ -2179,8 +2180,12 @@ js::RecomputeStackLimit(JSRuntime *rt, StackKind kind)
|
||||
#ifdef JS_ION
|
||||
if (kind == StackForUntrustedScript) {
|
||||
JSRuntime::AutoLockForOperationCallback lock(rt);
|
||||
if (rt->mainThread.ionStackLimit != uintptr_t(-1))
|
||||
if (rt->mainThread.ionStackLimit != uintptr_t(-1)) {
|
||||
rt->mainThread.ionStackLimit = rt->mainThread.nativeStackLimit[kind];
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
rt->mainThread.ionStackLimit = jit::Simulator::StackLimit();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -1291,6 +1291,15 @@ JSContext::mark(JSTracer *trc)
|
||||
MarkValueRoot(trc, &iterValue, "iterValue");
|
||||
}
|
||||
|
||||
void *
|
||||
ThreadSafeContext::stackLimitAddressForJitCode(StackKind kind)
|
||||
{
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
return runtime_->mainThread.addressOfSimulatorStackLimit();
|
||||
#endif
|
||||
return stackLimitAddress(kind);
|
||||
}
|
||||
|
||||
JSVersion
|
||||
JSContext::findVersion() const
|
||||
{
|
||||
|
@ -287,6 +287,7 @@ struct ThreadSafeContext : ContextFriendFields,
|
||||
size_t workerThreadCount() { return runtime_->workerThreadCount(); }
|
||||
void *runtimeAddressForJit() { return runtime_; }
|
||||
void *stackLimitAddress(StackKind kind) { return &runtime_->mainThread.nativeStackLimit[kind]; }
|
||||
void *stackLimitAddressForJitCode(StackKind kind);
|
||||
size_t gcSystemPageSize() { return runtime_->gcSystemPageSize; }
|
||||
bool signalHandlersInstalled() const { return runtime_->signalHandlersInstalled(); }
|
||||
bool jitSupportsFloatingPoint() const { return runtime_->jitSupportsFloatingPoint; }
|
||||
|
@ -1300,8 +1300,8 @@ class ParallelIonInvoke
|
||||
|
||||
bool invoke(PerThreadData *perThread) {
|
||||
RootedValue result(perThread);
|
||||
enter_(jitcode_, argc_ + 1, argv_ + 1, nullptr, calleeToken_, nullptr, 0,
|
||||
result.address());
|
||||
CALL_GENERATED_CODE(enter_, jitcode_, argc_ + 1, argv_ + 1, nullptr, calleeToken_,
|
||||
nullptr, 0, result.address());
|
||||
return !result.isMagic();
|
||||
}
|
||||
};
|
||||
@ -1443,6 +1443,10 @@ ForkJoinShared::executeFromWorker(uint16_t sliceId, uint32_t workerId, uintptr_t
|
||||
}
|
||||
TlsPerThreadData.set(&thisThread);
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
stackLimit = Simulator::StackLimit();
|
||||
#endif
|
||||
|
||||
// Don't use setIonStackLimit() because that acquires the ionStackLimitLock, and the
|
||||
// lock has not been initialized in these cases.
|
||||
thisThread.ionStackLimit = stackLimit;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#if defined(JS_ION)
|
||||
# include "assembler/assembler/MacroAssembler.h"
|
||||
#endif
|
||||
#include "jit/arm/Simulator-arm.h"
|
||||
#include "jit/AsmJSSignalHandlers.h"
|
||||
#include "jit/JitCompartment.h"
|
||||
#include "jit/PcScriptCache.h"
|
||||
@ -73,6 +74,10 @@ PerThreadData::PerThreadData(JSRuntime *runtime)
|
||||
ionStackLimit(0),
|
||||
activation_(nullptr),
|
||||
asmJSActivationStack_(nullptr),
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
simulator_(nullptr),
|
||||
simulatorStackLimit_(0),
|
||||
#endif
|
||||
dtoaState(nullptr),
|
||||
suppressGC(0),
|
||||
#ifdef DEBUG
|
||||
@ -88,6 +93,10 @@ PerThreadData::~PerThreadData()
|
||||
|
||||
if (isInList())
|
||||
removeFromThreadList();
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
js_delete(simulator_);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
@ -255,6 +264,9 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
|
||||
gcFinalizeCallback(nullptr),
|
||||
gcMallocBytes(0),
|
||||
gcMallocGCTriggered(false),
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
simulatorRuntime_(nullptr),
|
||||
#endif
|
||||
scriptAndCountsVector(nullptr),
|
||||
NaNValue(DoubleNaNValue()),
|
||||
negativeInfinityValue(DoubleValue(NegativeInfinity())),
|
||||
@ -428,6 +440,12 @@ JSRuntime::init(uint32_t maxbytes)
|
||||
if (!evalCache.init())
|
||||
return false;
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
simulatorRuntime_ = js::jit::CreateSimulatorRuntime();
|
||||
if (!simulatorRuntime_)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
nativeStackBase = GetNativeStackBase();
|
||||
|
||||
jitSupportsFloatingPoint = JitSupportsFloatingPoint();
|
||||
@ -558,6 +576,10 @@ JSRuntime::~JSRuntime()
|
||||
gcNursery.disable();
|
||||
#endif
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
js::jit::DestroySimulatorRuntime(simulatorRuntime_);
|
||||
#endif
|
||||
|
||||
DebugOnly<size_t> oldCount = liveRuntimesCount--;
|
||||
JS_ASSERT(oldCount > 0);
|
||||
|
||||
@ -581,6 +603,17 @@ NewObjectCache::clearNurseryObjects(JSRuntime *rt)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JSRuntime::resetIonStackLimit()
|
||||
{
|
||||
AutoLockForOperationCallback lock(this);
|
||||
mainThread.setIonStackLimit(mainThread.nativeStackLimit[js::StackForUntrustedScript]);
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
mainThread.setIonStackLimit(js::jit::Simulator::StackLimit());
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
JSRuntime::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes *rtSizes)
|
||||
{
|
||||
|
@ -89,6 +89,8 @@ namespace jit {
|
||||
class JitRuntime;
|
||||
class JitActivation;
|
||||
struct PcScriptCache;
|
||||
class Simulator;
|
||||
class SimulatorRuntime;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -546,6 +548,11 @@ class PerThreadData : public PerThreadDataFriendFields,
|
||||
/* See AsmJSActivation comment. Protected by rt->operationCallbackLock. */
|
||||
js::AsmJSActivation *asmJSActivationStack_;
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
js::jit::Simulator *simulator_;
|
||||
uintptr_t simulatorStackLimit_;
|
||||
#endif
|
||||
|
||||
public:
|
||||
js::Activation *const *addressOfActivation() const {
|
||||
return &activation_;
|
||||
@ -600,6 +607,13 @@ class PerThreadData : public PerThreadDataFriendFields,
|
||||
inline bool exclusiveThreadsPresent();
|
||||
inline void addActiveCompilation();
|
||||
inline void removeActiveCompilation();
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
js::jit::Simulator *simulator() const;
|
||||
void setSimulator(js::jit::Simulator *sim);
|
||||
js::jit::SimulatorRuntime *simulatorRuntime() const;
|
||||
uintptr_t *addressOfSimulatorStackLimit();
|
||||
#endif
|
||||
};
|
||||
|
||||
template<class Client>
|
||||
@ -1336,6 +1350,10 @@ struct JSRuntime : public JS::shadow::Runtime,
|
||||
*/
|
||||
mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> gcMallocGCTriggered;
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
js::jit::SimulatorRuntime *simulatorRuntime_;
|
||||
#endif
|
||||
|
||||
public:
|
||||
void setNeedsBarrier(bool needs) {
|
||||
needsBarrier_ = needs;
|
||||
@ -1353,6 +1371,11 @@ struct JSRuntime : public JS::shadow::Runtime,
|
||||
{}
|
||||
};
|
||||
|
||||
#ifdef JS_ARM_SIMULATOR
|
||||
js::jit::SimulatorRuntime *simulatorRuntime() const;
|
||||
void setSimulatorRuntime(js::jit::SimulatorRuntime *srt);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The trace operations to trace embedding-specific GC roots. One is for
|
||||
* tracing through black roots and the other is for tracing through gray
|
||||
@ -1651,10 +1674,7 @@ struct JSRuntime : public JS::shadow::Runtime,
|
||||
|
||||
// Used to reset stack limit after a signaled interrupt (i.e. ionStackLimit_ = -1)
|
||||
// has been noticed by Ion/Baseline.
|
||||
void resetIonStackLimit() {
|
||||
AutoLockForOperationCallback lock(this);
|
||||
mainThread.setIonStackLimit(mainThread.nativeStackLimit[js::StackForUntrustedScript]);
|
||||
}
|
||||
void resetIonStackLimit();
|
||||
|
||||
// Cache for jit::GetPcScript().
|
||||
js::jit::PcScriptCache *ionPcScriptCache;
|
||||
|
@ -47,6 +47,8 @@
|
||||
#include "TraceLogging.h"
|
||||
#endif
|
||||
|
||||
#include "jit/JitCommon.h"
|
||||
|
||||
namespace JSC {
|
||||
|
||||
class JSGlobalData;
|
||||
@ -131,7 +133,7 @@ public:
|
||||
#endif
|
||||
|
||||
YarrJITCode16 fn = JS_FUNC_TO_DATA_PTR(YarrJITCode16, m_ref16.code().executableAddress());
|
||||
return MatchResult(fn(input, start, length, output));
|
||||
return MatchResult(CALL_GENERATED_YARR_CODE4(fn, input, start, length, output));
|
||||
}
|
||||
|
||||
MatchResult execute(const UChar* input, unsigned start, unsigned length)
|
||||
@ -145,7 +147,7 @@ public:
|
||||
#endif
|
||||
|
||||
YarrJITCodeMatchOnly16 fn = JS_FUNC_TO_DATA_PTR(YarrJITCodeMatchOnly16, m_matchOnly16.code().executableAddress());
|
||||
return MatchResult(fn(input, start, length));
|
||||
return MatchResult(CALL_GENERATED_YARR_CODE3(fn, input, start, length));
|
||||
}
|
||||
|
||||
#if ENABLE_REGEXP_TRACING
|
||||
|
Loading…
Reference in New Issue
Block a user