зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1027885 - OdinMonkey: avoid passing JSContext to C++ functions that can instead use innermostAsmJSActivation (r=dougc)
This commit is contained in:
Родитель
af44b6bf3d
Коммит
3414c83d98
|
@ -5880,12 +5880,6 @@ LoadAsmJSActivationIntoRegister(MacroAssembler &masm, Register reg)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
LoadJSContextFromActivation(MacroAssembler &masm, Register activation, Register dest)
|
||||
{
|
||||
masm.loadPtr(Address(activation, AsmJSActivation::offsetOfContext()), dest);
|
||||
}
|
||||
|
||||
static void
|
||||
AssertStackAlignment(MacroAssembler &masm)
|
||||
{
|
||||
|
@ -6070,102 +6064,6 @@ GenerateEntry(ModuleCompiler &m, const AsmJSModule::ExportedFunction &exportedFu
|
|||
return true;
|
||||
}
|
||||
|
||||
// This function and InvokeFromAsmJS* functions all return int32_t rather than
|
||||
// bool to prevent the compiler from optimizing bits higher than what's
|
||||
// actually needed for a bool (as the result is tested in asm.js generated code
|
||||
// which the compiler isn't aware of).
|
||||
static inline int32_t
|
||||
TryEnablingIon(JSContext *cx, AsmJSModule &module, HandleFunction fun, uint32_t exitIndex,
|
||||
int32_t argc, Value *argv)
|
||||
{
|
||||
if (!fun->hasScript())
|
||||
return true;
|
||||
|
||||
// Test if the function is Ion compiled
|
||||
JSScript *script = fun->nonLazyScript();
|
||||
if (!script->hasIonScript())
|
||||
return true;
|
||||
|
||||
// Currently we can't rectify arguments. Therefore disabling if argc is too low.
|
||||
if (fun->nargs() > size_t(argc))
|
||||
return true;
|
||||
|
||||
// Normally the types should corresond, since we just ran with those types,
|
||||
// but there are reports this is asserting. Therefore doing it as a check, instead of DEBUG only.
|
||||
if (!types::TypeScript::ThisTypes(script)->hasType(types::Type::UndefinedType()))
|
||||
return true;
|
||||
for(uint32_t i = 0; i < fun->nargs(); i++) {
|
||||
types::StackTypeSet *typeset = types::TypeScript::ArgTypes(script, i);
|
||||
types::Type type = types::Type::DoubleType();
|
||||
if (!argv[i].isDouble())
|
||||
type = types::Type::PrimitiveType(argv[i].extractNonDoubleType());
|
||||
if (!typeset->hasType(type))
|
||||
return true;
|
||||
}
|
||||
|
||||
// Enable
|
||||
IonScript *ionScript = script->ionScript();
|
||||
if (!ionScript->addDependentAsmJSModule(cx, DependentAsmJSModuleExit(&module, exitIndex)))
|
||||
return false;
|
||||
|
||||
module.exitIndexToGlobalDatum(exitIndex).exit = module.ionExitTrampoline(module.exit(exitIndex));
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
// See comment above TryEnablingIon.
|
||||
int32_t
|
||||
InvokeFromAsmJS(JSContext *cx, int32_t exitIndex, int32_t argc, Value *argv,
|
||||
MutableHandleValue rval)
|
||||
{
|
||||
AsmJSModule &module = cx->mainThread().asmJSActivationStackFromOwnerThread()->module();
|
||||
|
||||
RootedFunction fun(cx, module.exitIndexToGlobalDatum(exitIndex).fun);
|
||||
RootedValue fval(cx, ObjectValue(*fun));
|
||||
if (!Invoke(cx, UndefinedValue(), fval, argc, argv, rval))
|
||||
return false;
|
||||
|
||||
return TryEnablingIon(cx, module, fun, exitIndex, argc, argv);
|
||||
}
|
||||
|
||||
int32_t
|
||||
InvokeFromAsmJS_Ignore(JSContext *cx, int32_t exitIndex, int32_t argc, Value *argv)
|
||||
{
|
||||
RootedValue rval(cx);
|
||||
return InvokeFromAsmJS(cx, exitIndex, argc, argv, &rval);
|
||||
}
|
||||
|
||||
int32_t
|
||||
InvokeFromAsmJS_ToInt32(JSContext *cx, int32_t exitIndex, int32_t argc, Value *argv)
|
||||
{
|
||||
RootedValue rval(cx);
|
||||
if (!InvokeFromAsmJS(cx, exitIndex, argc, argv, &rval))
|
||||
return false;
|
||||
|
||||
int32_t i32;
|
||||
if (!ToInt32(cx, rval, &i32))
|
||||
return false;
|
||||
argv[0] = Int32Value(i32);
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t
|
||||
InvokeFromAsmJS_ToNumber(JSContext *cx, int32_t exitIndex, int32_t argc, Value *argv)
|
||||
{
|
||||
RootedValue rval(cx);
|
||||
if (!InvokeFromAsmJS(cx, exitIndex, argc, argv, &rval))
|
||||
return false;
|
||||
|
||||
double dbl;
|
||||
if (!ToNumber(cx, rval, &dbl))
|
||||
return false;
|
||||
argv[0] = DoubleValue(dbl);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
static void
|
||||
FillArgumentArray(ModuleCompiler &m, const VarTypeVector &argTypes,
|
||||
unsigned offsetToArgs, unsigned offsetToCallerStackArgs,
|
||||
|
@ -6226,8 +6124,7 @@ GenerateFFIInterpreterExit(ModuleCompiler &m, const ModuleCompiler::ExitDescript
|
|||
LoadAsmJSActivationIntoRegister(masm, activation);
|
||||
masm.storePtr(StackPointer, Address(activation, AsmJSActivation::offsetOfExitFP()));
|
||||
|
||||
MIRType typeArray[] = { MIRType_Pointer, // cx
|
||||
MIRType_Pointer, // exitDatum
|
||||
MIRType typeArray[] = { MIRType_Pointer, // exitDatum
|
||||
MIRType_Int32, // argc
|
||||
MIRType_Pointer }; // argv
|
||||
MIRTypeVector invokeArgTypes(m.cx());
|
||||
|
@ -6235,9 +6132,9 @@ GenerateFFIInterpreterExit(ModuleCompiler &m, const ModuleCompiler::ExitDescript
|
|||
|
||||
// At the point of the call, the stack layout shall be (sp grows to the left):
|
||||
// | stack args | padding | Value argv[] | padding | retaddr | caller stack args |
|
||||
// The padding between stack args and argv ensures that sp is aligned. The
|
||||
// padding between argv and retaddr ensures that argv is aligned.
|
||||
unsigned offsetToArgv = AlignBytes(StackArgBytes(invokeArgTypes), StackAlignment);
|
||||
// The padding between stack args and argv ensures that argv is aligned. The
|
||||
// padding between argv and retaddr ensures that sp is aligned.
|
||||
unsigned offsetToArgv = AlignBytes(StackArgBytes(invokeArgTypes), sizeof(double));
|
||||
unsigned argvBytes = Max<size_t>(1, exit.sig().args().length()) * sizeof(Value);
|
||||
unsigned stackDec = StackDecrementForCall(masm, offsetToArgv + argvBytes);
|
||||
masm.reserveStack(stackDec);
|
||||
|
@ -6250,23 +6147,14 @@ GenerateFFIInterpreterExit(ModuleCompiler &m, const ModuleCompiler::ExitDescript
|
|||
// Prepare the arguments for the call to InvokeFromAsmJS_*.
|
||||
ABIArgMIRTypeIter i(invokeArgTypes);
|
||||
|
||||
// argument 0: cx
|
||||
if (i->kind() == ABIArg::GPR) {
|
||||
LoadJSContextFromActivation(masm, activation, i->gpr());
|
||||
} else {
|
||||
LoadJSContextFromActivation(masm, activation, scratch);
|
||||
masm.storePtr(scratch, Address(StackPointer, i->offsetFromArgBase()));
|
||||
}
|
||||
i++;
|
||||
|
||||
// argument 1: exitIndex
|
||||
// argument 0: exitIndex
|
||||
if (i->kind() == ABIArg::GPR)
|
||||
masm.mov(ImmWord(exitIndex), i->gpr());
|
||||
else
|
||||
masm.store32(Imm32(exitIndex), Address(StackPointer, i->offsetFromArgBase()));
|
||||
i++;
|
||||
|
||||
// argument 2: argc
|
||||
// argument 1: argc
|
||||
unsigned argc = exit.sig().args().length();
|
||||
if (i->kind() == ABIArg::GPR)
|
||||
masm.mov(ImmWord(argc), i->gpr());
|
||||
|
@ -6274,7 +6162,7 @@ GenerateFFIInterpreterExit(ModuleCompiler &m, const ModuleCompiler::ExitDescript
|
|||
masm.store32(Imm32(argc), Address(StackPointer, i->offsetFromArgBase()));
|
||||
i++;
|
||||
|
||||
// argument 3: argv
|
||||
// argument 2: argv
|
||||
Address argv(StackPointer, offsetToArgv);
|
||||
if (i->kind() == ABIArg::GPR) {
|
||||
masm.computeEffectiveAddress(argv, i->gpr());
|
||||
|
@ -6371,25 +6259,26 @@ GenerateFFIIonExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit
|
|||
|
||||
// Ion calls use the following stack layout (sp grows to the left):
|
||||
// | return address | descriptor | callee | argc | this | arg1 | arg2 | ...
|
||||
unsigned offsetToArgs = MaybeRetAddr;
|
||||
unsigned argBytes = 3 * sizeof(size_t) + (1 + exit.sig().args().length()) * sizeof(Value);
|
||||
unsigned totalIonBytes = offsetToArgs + argBytes + savedRegBytes;
|
||||
unsigned offsetToIonArgs = MaybeRetAddr;
|
||||
unsigned ionArgBytes = 3 * sizeof(size_t) + (1 + exit.sig().args().length()) * sizeof(Value);
|
||||
unsigned totalIonBytes = offsetToIonArgs + ionArgBytes + savedRegBytes;
|
||||
unsigned ionFrameSize = StackDecrementForCall(masm, totalIonBytes);
|
||||
|
||||
// Coercion calls use the following stack layout (sp grows to the left):
|
||||
// | stack args | Value argv[1] | ...
|
||||
// | stack args | padding | Value argv[1] | ...
|
||||
// The padding between args and argv ensures that argv is aligned.
|
||||
MIRTypeVector coerceArgTypes(m.cx());
|
||||
coerceArgTypes.infallibleAppend(MIRType_Pointer); // cx
|
||||
coerceArgTypes.infallibleAppend(MIRType_Pointer); // argv
|
||||
unsigned bytesAfterArgs = sizeof(Value) + savedRegBytes;
|
||||
unsigned coerceFrameSize = StackDecrementForCall(masm, coerceArgTypes, bytesAfterArgs);
|
||||
unsigned offsetToCoerceArgv = AlignBytes(StackArgBytes(coerceArgTypes), sizeof(double));
|
||||
unsigned totalCoerceBytes = offsetToCoerceArgv + sizeof(Value) + savedRegBytes;
|
||||
unsigned coerceFrameSize = StackDecrementForCall(masm, totalCoerceBytes);
|
||||
|
||||
// Allocate a frame large enough for both of the above calls.
|
||||
unsigned framePushed = Max(ionFrameSize, coerceFrameSize);
|
||||
masm.reserveStack(framePushed);
|
||||
|
||||
// 1. Descriptor
|
||||
size_t argOffset = offsetToArgs;
|
||||
size_t argOffset = offsetToIonArgs;
|
||||
uint32_t descriptor = MakeFrameDescriptor(framePushed, JitFrame_Entry);
|
||||
masm.storePtr(ImmWord(uintptr_t(descriptor)), Address(StackPointer, argOffset));
|
||||
argOffset += sizeof(size_t);
|
||||
|
@ -6430,7 +6319,7 @@ GenerateFFIIonExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit
|
|||
unsigned offsetToCallerStackArgs = framePushed + AsmJSFrameSize;
|
||||
FillArgumentArray(m, exit.sig().args(), argOffset, offsetToCallerStackArgs, scratch);
|
||||
argOffset += exit.sig().args().length() * sizeof(Value);
|
||||
JS_ASSERT(argOffset == offsetToArgs + argBytes);
|
||||
JS_ASSERT(argOffset == offsetToIonArgs + ionArgBytes);
|
||||
|
||||
// 6. Store asm.js pinned registers
|
||||
#if defined(JS_CODEGEN_X64)
|
||||
|
@ -6556,24 +6445,11 @@ GenerateFFIIonExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit
|
|||
masm.setFramePushed(framePushed);
|
||||
|
||||
// Store return value into argv[0]
|
||||
unsigned offsetToArgv = StackArgBytes(coerceArgTypes);
|
||||
JS_ASSERT(offsetToArgv % sizeof(Value) == 0);
|
||||
masm.storeValue(JSReturnOperand, Address(StackPointer, offsetToArgv));
|
||||
masm.storeValue(JSReturnOperand, Address(StackPointer, offsetToCoerceArgv));
|
||||
|
||||
// argument 0: argv
|
||||
ABIArgMIRTypeIter i(coerceArgTypes);
|
||||
|
||||
// argument 0: cx
|
||||
LoadAsmJSActivationIntoRegister(masm, scratch);
|
||||
if (i->kind() == ABIArg::GPR) {
|
||||
LoadJSContextFromActivation(masm, scratch, i->gpr());
|
||||
} else {
|
||||
LoadJSContextFromActivation(masm, scratch, scratch);
|
||||
masm.storePtr(scratch, Address(StackPointer, i->offsetFromArgBase()));
|
||||
}
|
||||
i++;
|
||||
|
||||
// argument 1: argv
|
||||
Address argv(StackPointer, offsetToArgv);
|
||||
Address argv(StackPointer, offsetToCoerceArgv);
|
||||
if (i->kind() == ABIArg::GPR) {
|
||||
masm.computeEffectiveAddress(argv, i->gpr());
|
||||
} else {
|
||||
|
@ -6589,12 +6465,12 @@ GenerateFFIIonExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit
|
|||
case RetType::Signed:
|
||||
masm.call(AsmJSImmPtr(AsmJSImm_CoerceInPlace_ToInt32));
|
||||
masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, throwLabel);
|
||||
masm.unboxInt32(Address(StackPointer, offsetToArgv), ReturnReg);
|
||||
masm.unboxInt32(Address(StackPointer, offsetToCoerceArgv), ReturnReg);
|
||||
break;
|
||||
case RetType::Double:
|
||||
masm.call(AsmJSImmPtr(AsmJSImm_CoerceInPlace_ToNumber));
|
||||
masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, throwLabel);
|
||||
masm.loadDouble(Address(StackPointer, offsetToArgv), ReturnDoubleReg);
|
||||
masm.loadDouble(Address(StackPointer, offsetToCoerceArgv), ReturnDoubleReg);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("Unsupported convert type");
|
||||
|
@ -6629,7 +6505,7 @@ GenerateStackOverflowExit(ModuleCompiler &m, Label *throwLabel)
|
|||
masm.align(CodeAlignment);
|
||||
masm.bind(&m.stackOverflowLabel());
|
||||
|
||||
// The stack-overflow is checked before bumping the stack.
|
||||
// For the benefit of AssertStackAlignment.
|
||||
masm.setFramePushed(0);
|
||||
|
||||
// Store the frame pointer in AsmJSActivation::exitFP for stack unwinding.
|
||||
|
@ -6637,24 +6513,8 @@ GenerateStackOverflowExit(ModuleCompiler &m, Label *throwLabel)
|
|||
LoadAsmJSActivationIntoRegister(masm, activation);
|
||||
masm.storePtr(StackPointer, Address(activation, AsmJSActivation::offsetOfExitFP()));
|
||||
|
||||
MIRTypeVector argTypes(m.cx());
|
||||
argTypes.infallibleAppend(MIRType_Pointer); // cx
|
||||
|
||||
unsigned stackDec = StackDecrementForCall(masm, argTypes);
|
||||
masm.reserveStack(stackDec);
|
||||
|
||||
ABIArgMIRTypeIter i(argTypes);
|
||||
|
||||
// argument 0: cx
|
||||
if (i->kind() == ABIArg::GPR) {
|
||||
LoadJSContextFromActivation(masm, activation, i->gpr());
|
||||
} else {
|
||||
LoadJSContextFromActivation(masm, activation, activation);
|
||||
masm.storePtr(activation, Address(StackPointer, i->offsetFromArgBase()));
|
||||
}
|
||||
i++;
|
||||
|
||||
JS_ASSERT(i.done());
|
||||
// Even without arguments, various platforms require stack adjustment.
|
||||
masm.reserveStack(ComputeByteAlignment(AsmJSFrameSize + ShadowStackSpace, StackAlignment));
|
||||
|
||||
AssertStackAlignment(masm);
|
||||
masm.call(AsmJSImmPtr(AsmJSImm_ReportOverRecursed));
|
||||
|
@ -6697,34 +6557,23 @@ GenerateAsyncInterruptExit(ModuleCompiler &m, Label *throwLabel)
|
|||
masm.setFramePushed(0); // set to zero so we can use masm.framePushed() below
|
||||
masm.PushRegsInMask(AllRegsExceptSP); // save all GP/FP registers (except SP)
|
||||
|
||||
Register activation = ABIArgGenerator::NonArgReturnVolatileReg0;
|
||||
Register scratch = ABIArgGenerator::NonArgReturnVolatileReg1;
|
||||
Register scratch = ABIArgGenerator::NonArgReturnVolatileReg0;
|
||||
|
||||
// Store resumePC into the reserved space.
|
||||
LoadAsmJSActivationIntoRegister(masm, activation);
|
||||
masm.loadPtr(Address(activation, AsmJSActivation::offsetOfResumePC()), scratch);
|
||||
LoadAsmJSActivationIntoRegister(masm, scratch);
|
||||
masm.loadPtr(Address(scratch, AsmJSActivation::offsetOfResumePC()), scratch);
|
||||
masm.storePtr(scratch, Address(StackPointer, masm.framePushed() + sizeof(void*)));
|
||||
|
||||
// We know that StackPointer is word-aligned, but not necessarily
|
||||
// stack-aligned, so we need to align it dynamically.
|
||||
masm.mov(StackPointer, ABIArgGenerator::NonVolatileReg);
|
||||
#if defined(JS_CODEGEN_X86)
|
||||
// Ensure that at least one slot is pushed for passing 'cx' below.
|
||||
masm.push(Imm32(0));
|
||||
#endif
|
||||
masm.andPtr(Imm32(~(StackAlignment - 1)), StackPointer);
|
||||
if (ShadowStackSpace)
|
||||
masm.subPtr(Imm32(ShadowStackSpace), StackPointer);
|
||||
|
||||
// argument 0: cx
|
||||
#if defined(JS_CODEGEN_X86)
|
||||
LoadJSContextFromActivation(masm, activation, scratch);
|
||||
masm.storePtr(scratch, Address(StackPointer, 0));
|
||||
#elif defined(JS_CODEGEN_X64)
|
||||
LoadJSContextFromActivation(masm, activation, IntArgReg0);
|
||||
#endif
|
||||
|
||||
AssertStackAlignment(masm);
|
||||
masm.call(AsmJSImmPtr(AsmJSImm_HandleExecutionInterrupt));
|
||||
|
||||
masm.branchIfFalseBool(ReturnReg, throwLabel);
|
||||
|
||||
// Restore the StackPointer to it's position before the call.
|
||||
|
@ -6752,9 +6601,6 @@ GenerateAsyncInterruptExit(ModuleCompiler &m, Label *throwLabel)
|
|||
masm.loadPtr(Address(IntArgReg0, AsmJSActivation::offsetOfResumePC()), IntArgReg1);
|
||||
masm.storePtr(IntArgReg1, Address(s0, masm.framePushed()));
|
||||
|
||||
// argument 0: cx
|
||||
masm.loadPtr(Address(IntArgReg0, AsmJSActivation::offsetOfContext()), IntArgReg0);
|
||||
|
||||
// MIPS ABI requires rewserving stack for registes $a0 to $a3.
|
||||
masm.subPtr(Imm32(4 * sizeof(intptr_t)), StackPointer);
|
||||
|
||||
|
@ -6791,9 +6637,6 @@ GenerateAsyncInterruptExit(ModuleCompiler &m, Label *throwLabel)
|
|||
masm.loadPtr(Address(IntArgReg0, AsmJSActivation::offsetOfResumePC()), IntArgReg1);
|
||||
masm.storePtr(IntArgReg1, Address(r6, 14 * sizeof(uint32_t*)));
|
||||
|
||||
// argument 0: cx
|
||||
masm.loadPtr(Address(IntArgReg0, AsmJSActivation::offsetOfContext()), IntArgReg0);
|
||||
|
||||
masm.PushRegsInMask(RegisterSet(GeneralRegisterSet(0), FloatRegisterSet(FloatRegisters::AllDoubleMask))); // save all FP registers
|
||||
masm.call(AsmJSImm_HandleExecutionInterrupt);
|
||||
masm.branchIfFalseBool(ReturnReg, throwLabel);
|
||||
|
@ -6842,9 +6685,6 @@ GenerateSyncInterruptExit(ModuleCompiler &m, Label *throwLabel)
|
|||
masm.align(CodeAlignment);
|
||||
masm.bind(&m.syncInterruptLabel());
|
||||
|
||||
MIRTypeVector argTypes(m.cx());
|
||||
argTypes.infallibleAppend(MIRType_Pointer); // cx
|
||||
|
||||
// See AsmJSFrameSize comment in Assembler-shared.h.
|
||||
#if defined(JS_CODEGEN_ARM)
|
||||
masm.push(lr);
|
||||
|
@ -6859,22 +6699,9 @@ GenerateSyncInterruptExit(ModuleCompiler &m, Label *throwLabel)
|
|||
|
||||
masm.PushRegsInMask(VolatileRegs);
|
||||
|
||||
unsigned stackDec = StackDecrementForCall(masm, argTypes);
|
||||
unsigned stackDec = StackDecrementForCall(masm, ShadowStackSpace);
|
||||
masm.reserveStack(stackDec);
|
||||
|
||||
ABIArgMIRTypeIter i(argTypes);
|
||||
|
||||
// argument 0: cx
|
||||
if (i->kind() == ABIArg::GPR) {
|
||||
LoadJSContextFromActivation(masm, activation, i->gpr());
|
||||
} else {
|
||||
LoadJSContextFromActivation(masm, activation, activation);
|
||||
masm.storePtr(activation, Address(StackPointer, i->offsetFromArgBase()));
|
||||
}
|
||||
i++;
|
||||
|
||||
JS_ASSERT(i.done());
|
||||
|
||||
AssertStackAlignment(masm);
|
||||
masm.call(AsmJSImmPtr(AsmJSImm_HandleExecutionInterrupt));
|
||||
masm.branchIfFalseBool(ReturnReg, throwLabel);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "jsobjinlines.h"
|
||||
|
||||
#include "frontend/ParseNode-inl.h"
|
||||
#include "vm/Stack-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace jit;
|
||||
|
@ -448,9 +449,25 @@ AsmJSModule::setAutoFlushICacheRange()
|
|||
AutoFlushICache::setRange(uintptr_t(code_), pod.codeBytes_);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
CoerceInPlace_ToInt32(JSContext *cx, MutableHandleValue val)
|
||||
static void
|
||||
AsmJSReportOverRecursed()
|
||||
{
|
||||
JSContext *cx = PerThreadData::innermostAsmJSActivation()->cx();
|
||||
js_ReportOverRecursed(cx);
|
||||
}
|
||||
|
||||
static void
|
||||
AsmJSHandleExecutionInterrupt()
|
||||
{
|
||||
JSContext *cx = PerThreadData::innermostAsmJSActivation()->cx();
|
||||
HandleExecutionInterrupt(cx);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
CoerceInPlace_ToInt32(MutableHandleValue val)
|
||||
{
|
||||
JSContext *cx = PerThreadData::innermostAsmJSActivation()->cx();
|
||||
|
||||
int32_t i32;
|
||||
if (!ToInt32(cx, val, &i32))
|
||||
return false;
|
||||
|
@ -460,8 +477,10 @@ CoerceInPlace_ToInt32(JSContext *cx, MutableHandleValue val)
|
|||
}
|
||||
|
||||
static int32_t
|
||||
CoerceInPlace_ToNumber(JSContext *cx, MutableHandleValue val)
|
||||
CoerceInPlace_ToNumber(MutableHandleValue val)
|
||||
{
|
||||
JSContext *cx = PerThreadData::innermostAsmJSActivation()->cx();
|
||||
|
||||
double dbl;
|
||||
if (!ToNumber(cx, val, &dbl))
|
||||
return false;
|
||||
|
@ -470,19 +489,109 @@ CoerceInPlace_ToNumber(JSContext *cx, MutableHandleValue val)
|
|||
return true;
|
||||
}
|
||||
|
||||
namespace js {
|
||||
static bool
|
||||
TryEnablingIon(JSContext *cx, AsmJSModule &module, HandleFunction fun, uint32_t exitIndex,
|
||||
int32_t argc, Value *argv)
|
||||
{
|
||||
if (!fun->hasScript())
|
||||
return true;
|
||||
|
||||
// Defined in AsmJS.cpp:
|
||||
// Test if the function is Ion compiled
|
||||
JSScript *script = fun->nonLazyScript();
|
||||
if (!script->hasIonScript())
|
||||
return true;
|
||||
|
||||
int32_t
|
||||
InvokeFromAsmJS_Ignore(JSContext *cx, int32_t exitIndex, int32_t argc, Value *argv);
|
||||
// Currently we can't rectify arguments. Therefore disabling if argc is too low.
|
||||
if (fun->nargs() > size_t(argc))
|
||||
return true;
|
||||
|
||||
int32_t
|
||||
InvokeFromAsmJS_ToInt32(JSContext *cx, int32_t exitIndex, int32_t argc, Value *argv);
|
||||
// Normally the types should corresond, since we just ran with those types,
|
||||
// but there are reports this is asserting. Therefore doing it as a check, instead of DEBUG only.
|
||||
if (!types::TypeScript::ThisTypes(script)->hasType(types::Type::UndefinedType()))
|
||||
return true;
|
||||
for(uint32_t i = 0; i < fun->nargs(); i++) {
|
||||
types::StackTypeSet *typeset = types::TypeScript::ArgTypes(script, i);
|
||||
types::Type type = types::Type::DoubleType();
|
||||
if (!argv[i].isDouble())
|
||||
type = types::Type::PrimitiveType(argv[i].extractNonDoubleType());
|
||||
if (!typeset->hasType(type))
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t
|
||||
InvokeFromAsmJS_ToNumber(JSContext *cx, int32_t exitIndex, int32_t argc, Value *argv);
|
||||
// Enable
|
||||
IonScript *ionScript = script->ionScript();
|
||||
if (!ionScript->addDependentAsmJSModule(cx, DependentAsmJSModuleExit(&module, exitIndex)))
|
||||
return false;
|
||||
|
||||
module.exitIndexToGlobalDatum(exitIndex).exit = module.ionExitTrampoline(module.exit(exitIndex));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
InvokeFromAsmJS(AsmJSActivation *activation, int32_t exitIndex, int32_t argc, Value *argv,
|
||||
MutableHandleValue rval)
|
||||
{
|
||||
JSContext *cx = activation->cx();
|
||||
AsmJSModule &module = activation->module();
|
||||
|
||||
RootedFunction fun(cx, module.exitIndexToGlobalDatum(exitIndex).fun);
|
||||
RootedValue fval(cx, ObjectValue(*fun));
|
||||
if (!Invoke(cx, UndefinedValue(), fval, argc, argv, rval))
|
||||
return false;
|
||||
|
||||
return TryEnablingIon(cx, module, fun, exitIndex, argc, argv);
|
||||
}
|
||||
|
||||
// Use an int32_t return type instead of bool since bool does not have a
|
||||
// specified width and the caller is assuming a word-sized return.
|
||||
static int32_t
|
||||
InvokeFromAsmJS_Ignore(int32_t exitIndex, int32_t argc, Value *argv)
|
||||
{
|
||||
AsmJSActivation *activation = PerThreadData::innermostAsmJSActivation();
|
||||
JSContext *cx = activation->cx();
|
||||
|
||||
RootedValue rval(cx);
|
||||
return InvokeFromAsmJS(activation, exitIndex, argc, argv, &rval);
|
||||
}
|
||||
|
||||
// Use an int32_t return type instead of bool since bool does not have a
|
||||
// specified width and the caller is assuming a word-sized return.
|
||||
static int32_t
|
||||
InvokeFromAsmJS_ToInt32(int32_t exitIndex, int32_t argc, Value *argv)
|
||||
{
|
||||
AsmJSActivation *activation = PerThreadData::innermostAsmJSActivation();
|
||||
JSContext *cx = activation->cx();
|
||||
|
||||
RootedValue rval(cx);
|
||||
if (!InvokeFromAsmJS(activation, exitIndex, argc, argv, &rval))
|
||||
return false;
|
||||
|
||||
int32_t i32;
|
||||
if (!ToInt32(cx, rval, &i32))
|
||||
return false;
|
||||
|
||||
argv[0] = Int32Value(i32);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Use an int32_t return type instead of bool since bool does not have a
|
||||
// specified width and the caller is assuming a word-sized return.
|
||||
static int32_t
|
||||
InvokeFromAsmJS_ToNumber(int32_t exitIndex, int32_t argc, Value *argv)
|
||||
{
|
||||
AsmJSActivation *activation = PerThreadData::innermostAsmJSActivation();
|
||||
JSContext *cx = activation->cx();
|
||||
|
||||
RootedValue rval(cx);
|
||||
if (!InvokeFromAsmJS(activation, exitIndex, argc, argv, &rval))
|
||||
return false;
|
||||
|
||||
double dbl;
|
||||
if (!ToNumber(cx, rval, &dbl))
|
||||
return false;
|
||||
|
||||
argv[0] = DoubleValue(dbl);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(JS_CODEGEN_ARM)
|
||||
|
@ -524,19 +633,19 @@ AddressOf(AsmJSImmKind kind, ExclusiveContext *cx)
|
|||
case AsmJSImm_StackLimit:
|
||||
return cx->stackLimitAddressForJitCode(StackForUntrustedScript);
|
||||
case AsmJSImm_ReportOverRecursed:
|
||||
return RedirectCall(FuncCast<void (JSContext*)>(js_ReportOverRecursed), Args_General1);
|
||||
return RedirectCall(FuncCast(AsmJSReportOverRecursed), Args_General0);
|
||||
case AsmJSImm_HandleExecutionInterrupt:
|
||||
return RedirectCall(FuncCast(js::HandleExecutionInterrupt), Args_General1);
|
||||
return RedirectCall(FuncCast(AsmJSHandleExecutionInterrupt), Args_General0);
|
||||
case AsmJSImm_InvokeFromAsmJS_Ignore:
|
||||
return RedirectCall(FuncCast(InvokeFromAsmJS_Ignore), Args_General4);
|
||||
return RedirectCall(FuncCast(InvokeFromAsmJS_Ignore), Args_General3);
|
||||
case AsmJSImm_InvokeFromAsmJS_ToInt32:
|
||||
return RedirectCall(FuncCast(InvokeFromAsmJS_ToInt32), Args_General4);
|
||||
return RedirectCall(FuncCast(InvokeFromAsmJS_ToInt32), Args_General3);
|
||||
case AsmJSImm_InvokeFromAsmJS_ToNumber:
|
||||
return RedirectCall(FuncCast(InvokeFromAsmJS_ToNumber), Args_General4);
|
||||
return RedirectCall(FuncCast(InvokeFromAsmJS_ToNumber), Args_General3);
|
||||
case AsmJSImm_CoerceInPlace_ToInt32:
|
||||
return RedirectCall(FuncCast(CoerceInPlace_ToInt32), Args_General2);
|
||||
return RedirectCall(FuncCast(CoerceInPlace_ToInt32), Args_General1);
|
||||
case AsmJSImm_CoerceInPlace_ToNumber:
|
||||
return RedirectCall(FuncCast(CoerceInPlace_ToNumber), Args_General2);
|
||||
return RedirectCall(FuncCast(CoerceInPlace_ToNumber), Args_General1);
|
||||
case AsmJSImm_ToInt32:
|
||||
return RedirectCall(FuncCast<int32_t (double)>(js::ToInt32), Args_Int_Double);
|
||||
#if defined(JS_CODEGEN_ARM)
|
||||
|
|
|
@ -150,16 +150,6 @@ using mozilla::DebugOnly;
|
|||
// thread/stack as the victim (Unix and Windows), we can use TLS to find any
|
||||
// currently executing asm.js code.
|
||||
#if !defined(XP_MACOSX)
|
||||
static AsmJSActivation *
|
||||
InnermostAsmJSActivation()
|
||||
{
|
||||
PerThreadData *threadData = TlsPerThreadData.get();
|
||||
if (!threadData)
|
||||
return nullptr;
|
||||
|
||||
return threadData->asmJSActivationStackFromOwnerThread();
|
||||
}
|
||||
|
||||
static JSRuntime *
|
||||
RuntimeForCurrentThread()
|
||||
{
|
||||
|
@ -451,7 +441,7 @@ HandleException(PEXCEPTION_POINTERS exception)
|
|||
if (rt->jitRuntime() && rt->jitRuntime()->handleAccessViolation(rt, faultingAddress))
|
||||
return true;
|
||||
|
||||
AsmJSActivation *activation = InnermostAsmJSActivation();
|
||||
AsmJSActivation *activation = PerThreadData::innermostAsmJSActivation();
|
||||
if (!activation)
|
||||
return false;
|
||||
|
||||
|
@ -648,7 +638,7 @@ HandleMachException(JSRuntime *rt, const ExceptionRequest &request)
|
|||
if (rt->jitRuntime() && rt->jitRuntime()->handleAccessViolation(rt, faultingAddress))
|
||||
return true;
|
||||
|
||||
AsmJSActivation *activation = rt->mainThread.asmJSActivationStackFromAnyThread();
|
||||
AsmJSActivation *activation = rt->mainThread.asmJSActivationStack();
|
||||
if (!activation)
|
||||
return false;
|
||||
|
||||
|
@ -898,7 +888,7 @@ HandleSignal(int signum, siginfo_t *info, void *ctx)
|
|||
if (rt->jitRuntime() && rt->jitRuntime()->handleAccessViolation(rt, faultingAddress))
|
||||
return true;
|
||||
|
||||
AsmJSActivation *activation = InnermostAsmJSActivation();
|
||||
AsmJSActivation *activation = PerThreadData::innermostAsmJSActivation();
|
||||
if (!activation)
|
||||
return false;
|
||||
|
||||
|
@ -1048,7 +1038,7 @@ js::RequestInterruptForAsmJSCode(JSRuntime *rt, int interruptModeRaw)
|
|||
return;
|
||||
}
|
||||
|
||||
AsmJSActivation *activation = rt->mainThread.asmJSActivationStackFromAnyThread();
|
||||
AsmJSActivation *activation = rt->mainThread.asmJSActivationStack();
|
||||
if (!activation)
|
||||
return;
|
||||
|
||||
|
|
|
@ -4065,7 +4065,6 @@ Simulator::execute()
|
|||
// Get the PC to simulate. Cannot use the accessor here as we need the raw
|
||||
// PC value and not the one used as input to arithmetic instructions.
|
||||
int program_counter = get_pc();
|
||||
AsmJSActivation *activation = TlsPerThreadData.get()->asmJSActivationStackFromOwnerThread();
|
||||
|
||||
while (program_counter != end_sim_pc) {
|
||||
if (EnableStopSimAt && (icount_ == Simulator::StopSimAt)) {
|
||||
|
@ -4080,7 +4079,7 @@ Simulator::execute()
|
|||
int32_t rpc = resume_pc_;
|
||||
if (MOZ_UNLIKELY(rpc != 0)) {
|
||||
// AsmJS signal handler ran and we have to adjust the pc.
|
||||
activation->setResumePC((void *)get_pc());
|
||||
PerThreadData::innermostAsmJSActivation()->setResumePC((void *)get_pc());
|
||||
set_pc(rpc);
|
||||
resume_pc_ = 0;
|
||||
}
|
||||
|
|
|
@ -3310,7 +3310,7 @@ Simulator::execute()
|
|||
// Get the PC to simulate. Cannot use the accessor here as we need the
|
||||
// raw PC value and not the one used as input to arithmetic instructions.
|
||||
int program_counter = get_pc();
|
||||
AsmJSActivation *activation = TlsPerThreadData.get()->asmJSActivationStackFromOwnerThread();
|
||||
AsmJSActivation *activation = TlsPerThreadData.get()->asmJSActivationStack();
|
||||
|
||||
while (program_counter != end_sim_pc) {
|
||||
if (enableStopSimAt && (icount_ == Simulator::StopSimAt)) {
|
||||
|
|
|
@ -548,7 +548,7 @@ ArrayBufferObject::canNeuterAsmJSArrayBuffer(JSContext *cx, ArrayBufferObject &b
|
|||
{
|
||||
JS_ASSERT(!buffer.isSharedArrayBuffer());
|
||||
#ifdef JS_ION
|
||||
AsmJSActivation *act = cx->mainThread().asmJSActivationStackFromOwnerThread();
|
||||
AsmJSActivation *act = cx->mainThread().asmJSActivationStack();
|
||||
for (; act; act = act->prevAsmJS()) {
|
||||
if (act->module().maybeHeapBufferObject() == &buffer)
|
||||
break;
|
||||
|
|
|
@ -591,11 +591,12 @@ class PerThreadData : public PerThreadDataFriendFields
|
|||
return offsetof(PerThreadData, activation_);
|
||||
}
|
||||
|
||||
js::AsmJSActivation *asmJSActivationStackFromAnyThread() const {
|
||||
js::AsmJSActivation *asmJSActivationStack() const {
|
||||
return asmJSActivationStack_;
|
||||
}
|
||||
js::AsmJSActivation *asmJSActivationStackFromOwnerThread() const {
|
||||
return asmJSActivationStack_;
|
||||
static js::AsmJSActivation *innermostAsmJSActivation() {
|
||||
PerThreadData *ptd = TlsPerThreadData.get();
|
||||
return ptd ? ptd->asmJSActivationStack_ : nullptr;
|
||||
}
|
||||
|
||||
js::Activation *activation() const {
|
||||
|
|
Загрузка…
Ссылка в новой задаче