зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1050254 - OdinMonkey: Place NaN in the global data and load from here to free the NANReg. r=luke
This commit is contained in:
Родитель
e3681d9600
Коммит
489904c774
|
@ -342,6 +342,8 @@ DynamicallyLinkModule(JSContext *cx, CallArgs args, AsmJSModule &module)
|
||||||
for (unsigned i = 0; i < module.numExits(); i++)
|
for (unsigned i = 0; i < module.numExits(); i++)
|
||||||
module.exitIndexToGlobalDatum(i).fun = &ffis[module.exit(i).ffiIndex()]->as<JSFunction>();
|
module.exitIndexToGlobalDatum(i).fun = &ffis[module.exit(i).ffiIndex()]->as<JSFunction>();
|
||||||
|
|
||||||
|
module.initGlobalNaN();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,12 +33,15 @@
|
||||||
# include "jit/PerfSpewer.h"
|
# include "jit/PerfSpewer.h"
|
||||||
#endif
|
#endif
|
||||||
#include "jit/RegisterSets.h"
|
#include "jit/RegisterSets.h"
|
||||||
|
#include "jit/shared/Assembler-shared.h"
|
||||||
#include "vm/TypedArrayObject.h"
|
#include "vm/TypedArrayObject.h"
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
namespace frontend { class TokenStream; }
|
namespace frontend { class TokenStream; }
|
||||||
|
|
||||||
|
using JS::GenericNaN;
|
||||||
|
|
||||||
// These EcmaScript-defined coercions form the basis of the asm.js type system.
|
// These EcmaScript-defined coercions form the basis of the asm.js type system.
|
||||||
enum AsmJSCoercion
|
enum AsmJSCoercion
|
||||||
{
|
{
|
||||||
|
@ -1042,8 +1045,10 @@ class AsmJSModule
|
||||||
// are laid out in this order:
|
// are laid out in this order:
|
||||||
// 0. a pointer to the current AsmJSActivation
|
// 0. a pointer to the current AsmJSActivation
|
||||||
// 1. a pointer to the heap that was linked to the module
|
// 1. a pointer to the heap that was linked to the module
|
||||||
// 2. global variable state (elements are sizeof(uint64_t))
|
// 2. the double float constant NaN.
|
||||||
// 3. interleaved function-pointer tables and exits. These are allocated
|
// 3. the float32 constant NaN, padded to sizeof(double).
|
||||||
|
// 4. global variable state (elements are sizeof(uint64_t))
|
||||||
|
// 5. interleaved function-pointer tables and exits. These are allocated
|
||||||
// while type checking function bodies (as exits and uses of
|
// while type checking function bodies (as exits and uses of
|
||||||
// function-pointer tables are encountered).
|
// function-pointer tables are encountered).
|
||||||
size_t offsetOfGlobalData() const {
|
size_t offsetOfGlobalData() const {
|
||||||
|
@ -1057,6 +1062,8 @@ class AsmJSModule
|
||||||
size_t globalDataBytes() const {
|
size_t globalDataBytes() const {
|
||||||
return sizeof(void*) +
|
return sizeof(void*) +
|
||||||
sizeof(void*) +
|
sizeof(void*) +
|
||||||
|
sizeof(double) +
|
||||||
|
sizeof(double) +
|
||||||
pod.numGlobalVars_ * sizeof(uint64_t) +
|
pod.numGlobalVars_ * sizeof(uint64_t) +
|
||||||
pod.funcPtrTableAndExitBytes_;
|
pod.funcPtrTableAndExitBytes_;
|
||||||
}
|
}
|
||||||
|
@ -1077,9 +1084,26 @@ class AsmJSModule
|
||||||
JS_ASSERT(isFinished());
|
JS_ASSERT(isFinished());
|
||||||
return *(uint8_t**)(globalData() + heapGlobalDataOffset());
|
return *(uint8_t**)(globalData() + heapGlobalDataOffset());
|
||||||
}
|
}
|
||||||
|
static unsigned nan64GlobalDataOffset() {
|
||||||
|
static_assert(jit::AsmJSNaN64GlobalDataOffset % sizeof(double) == 0,
|
||||||
|
"Global data NaN should be aligned");
|
||||||
|
return heapGlobalDataOffset() + sizeof(void*);
|
||||||
|
}
|
||||||
|
static unsigned nan32GlobalDataOffset() {
|
||||||
|
static_assert(jit::AsmJSNaN32GlobalDataOffset % sizeof(double) == 0,
|
||||||
|
"Global data NaN should be aligned");
|
||||||
|
return nan64GlobalDataOffset() + sizeof(double);
|
||||||
|
}
|
||||||
|
void initGlobalNaN() {
|
||||||
|
MOZ_ASSERT(jit::AsmJSNaN64GlobalDataOffset == nan64GlobalDataOffset());
|
||||||
|
MOZ_ASSERT(jit::AsmJSNaN32GlobalDataOffset == nan32GlobalDataOffset());
|
||||||
|
*(double *)(globalData() + nan64GlobalDataOffset()) = GenericNaN();
|
||||||
|
*(float *)(globalData() + nan32GlobalDataOffset()) = GenericNaN();
|
||||||
|
}
|
||||||
unsigned globalVariableOffset() const {
|
unsigned globalVariableOffset() const {
|
||||||
static_assert((2 * sizeof(void*)) % sizeof(double) == 0, "Global data should be aligned");
|
static_assert((2 * sizeof(void*) + 2 * sizeof(double)) % sizeof(double) == 0,
|
||||||
return 2 * sizeof(void*);
|
"Global data should be aligned");
|
||||||
|
return 2 * sizeof(void*) + 2 * sizeof(double);
|
||||||
}
|
}
|
||||||
unsigned globalVarIndexToGlobalDataOffset(unsigned i) const {
|
unsigned globalVarIndexToGlobalDataOffset(unsigned i) const {
|
||||||
JS_ASSERT(isFinishedWithModulePrologue());
|
JS_ASSERT(isFinishedWithModulePrologue());
|
||||||
|
|
|
@ -5985,11 +5985,9 @@ GenerateEntry(ModuleCompiler &m, unsigned exportIndex)
|
||||||
JS_ASSERT(masm.framePushed() == FramePushedAfterSave);
|
JS_ASSERT(masm.framePushed() == FramePushedAfterSave);
|
||||||
|
|
||||||
// ARM and MIPS have a globally-pinned GlobalReg (x64 uses RIP-relative
|
// ARM and MIPS have a globally-pinned GlobalReg (x64 uses RIP-relative
|
||||||
// addressing, x86 uses immediates in effective addresses) and NaN register
|
// addressing, x86 uses immediates in effective addresses).
|
||||||
// (used as part of the out-of-bounds handling in heap loads/stores).
|
|
||||||
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
|
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
|
||||||
masm.movePtr(IntArgReg1, GlobalReg);
|
masm.movePtr(IntArgReg1, GlobalReg);
|
||||||
masm.loadConstantDouble(GenericNaN(), NANReg);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ARM, MIPS and x64 have a globally-pinned HeapReg (x86 uses immediates in
|
// ARM, MIPS and x64 have a globally-pinned HeapReg (x86 uses immediates in
|
||||||
|
|
|
@ -319,8 +319,6 @@ class RegisterAllocator
|
||||||
#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
|
#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
|
||||||
allRegisters_.take(AnyRegister(HeapReg));
|
allRegisters_.take(AnyRegister(HeapReg));
|
||||||
allRegisters_.take(AnyRegister(GlobalReg));
|
allRegisters_.take(AnyRegister(GlobalReg));
|
||||||
// Need to remove both NANReg, and its aliases.
|
|
||||||
allRegisters_.takeAllAliasedUnchecked(AnyRegister(NANReg));
|
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if (FramePointer != InvalidReg && mir->instrumentedProfiling())
|
if (FramePointer != InvalidReg && mir->instrumentedProfiling())
|
||||||
|
|
|
@ -102,8 +102,6 @@ static MOZ_CONSTEXPR_VAR FloatRegister ScratchSimdReg = InvalidFloatReg;
|
||||||
static MOZ_CONSTEXPR_VAR FloatRegister ScratchUIntReg = { FloatRegisters::d15, VFPRegister::UInt };
|
static MOZ_CONSTEXPR_VAR FloatRegister ScratchUIntReg = { FloatRegisters::d15, VFPRegister::UInt };
|
||||||
static MOZ_CONSTEXPR_VAR FloatRegister ScratchIntReg = { FloatRegisters::d15, VFPRegister::Int };
|
static MOZ_CONSTEXPR_VAR FloatRegister ScratchIntReg = { FloatRegisters::d15, VFPRegister::Int };
|
||||||
|
|
||||||
static MOZ_CONSTEXPR_VAR FloatRegister NANReg = { FloatRegisters::d14, VFPRegister::Double };
|
|
||||||
|
|
||||||
// Registers used in the GenerateFFIIonExit Enable Activation block.
|
// Registers used in the GenerateFFIIonExit Enable Activation block.
|
||||||
static MOZ_CONSTEXPR_VAR Register AsmJSIonExitRegCallee = r4;
|
static MOZ_CONSTEXPR_VAR Register AsmJSIonExitRegCallee = r4;
|
||||||
static MOZ_CONSTEXPR_VAR Register AsmJSIonExitRegE0 = r0;
|
static MOZ_CONSTEXPR_VAR Register AsmJSIonExitRegE0 = r0;
|
||||||
|
|
|
@ -1835,10 +1835,10 @@ CodeGeneratorARM::visitAsmJSLoadHeap(LAsmJSLoadHeap *ins)
|
||||||
FloatRegister dst = ToFloatRegister(ins->output());
|
FloatRegister dst = ToFloatRegister(ins->output());
|
||||||
VFPRegister vd(dst);
|
VFPRegister vd(dst);
|
||||||
if (size == 32) {
|
if (size == 32) {
|
||||||
masm.convertDoubleToFloat32(NANReg, dst, Assembler::AboveOrEqual);
|
masm.ma_vldr(Operand(GlobalReg, AsmJSNaN32GlobalDataOffset), vd.singleOverlay(), Assembler::AboveOrEqual);
|
||||||
masm.ma_vldr(vd.singleOverlay(), HeapReg, ptrReg, 0, Assembler::Below);
|
masm.ma_vldr(vd.singleOverlay(), HeapReg, ptrReg, 0, Assembler::Below);
|
||||||
} else {
|
} else {
|
||||||
masm.ma_vmov(NANReg, dst, Assembler::AboveOrEqual);
|
masm.ma_vldr(Operand(GlobalReg, AsmJSNaN64GlobalDataOffset), vd, Assembler::AboveOrEqual);
|
||||||
masm.ma_vldr(vd, HeapReg, ptrReg, 0, Assembler::Below);
|
masm.ma_vldr(vd, HeapReg, ptrReg, 0, Assembler::Below);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -116,8 +116,6 @@ static MOZ_CONSTEXPR_VAR FloatRegister ReturnFloatReg = { FloatRegisters::f0 };
|
||||||
static MOZ_CONSTEXPR_VAR FloatRegister ScratchFloatReg = { FloatRegisters::f18 };
|
static MOZ_CONSTEXPR_VAR FloatRegister ScratchFloatReg = { FloatRegisters::f18 };
|
||||||
static MOZ_CONSTEXPR_VAR FloatRegister SecondScratchFloatReg = { FloatRegisters::f16 };
|
static MOZ_CONSTEXPR_VAR FloatRegister SecondScratchFloatReg = { FloatRegisters::f16 };
|
||||||
|
|
||||||
static MOZ_CONSTEXPR_VAR FloatRegister NANReg = { FloatRegisters::f30 };
|
|
||||||
|
|
||||||
// Registers used in the GenerateFFIIonExit Enable Activation block.
|
// Registers used in the GenerateFFIIonExit Enable Activation block.
|
||||||
static MOZ_CONSTEXPR_VAR Register AsmJSIonExitRegCallee = t0;
|
static MOZ_CONSTEXPR_VAR Register AsmJSIonExitRegCallee = t0;
|
||||||
static MOZ_CONSTEXPR_VAR Register AsmJSIonExitRegE0 = a0;
|
static MOZ_CONSTEXPR_VAR Register AsmJSIonExitRegE0 = a0;
|
||||||
|
|
|
@ -1954,9 +1954,9 @@ CodeGeneratorMIPS::visitAsmJSLoadHeap(LAsmJSLoadHeap *ins)
|
||||||
// Offset is out of range. Load default values.
|
// Offset is out of range. Load default values.
|
||||||
if (isFloat) {
|
if (isFloat) {
|
||||||
if (size == 32)
|
if (size == 32)
|
||||||
masm.convertDoubleToFloat32(NANReg, ToFloatRegister(out));
|
masm.loadFloat32(Address(GlobalReg, AsmJSNaN32GlobalDataOffset), ToFloatRegister(out));
|
||||||
else
|
else
|
||||||
masm.moveDouble(NANReg, ToFloatRegister(out));
|
masm.loadDouble(Address(GlobalReg, AsmJSNaN64GlobalDataOffset), ToFloatRegister(out));
|
||||||
} else {
|
} else {
|
||||||
masm.move32(Imm32(0), ToRegister(out));
|
masm.move32(Imm32(0), ToRegister(out));
|
||||||
}
|
}
|
||||||
|
|
|
@ -659,9 +659,11 @@ struct AsmJSFrame
|
||||||
static_assert(sizeof(AsmJSFrame) == 2 * sizeof(void*), "?!");
|
static_assert(sizeof(AsmJSFrame) == 2 * sizeof(void*), "?!");
|
||||||
static const uint32_t AsmJSFrameBytesAfterReturnAddress = sizeof(void*);
|
static const uint32_t AsmJSFrameBytesAfterReturnAddress = sizeof(void*);
|
||||||
|
|
||||||
// A hoisting of AsmJSModule::activationGlobalDataOffset that avoids #including
|
// A hoisting of constants that would otherwise require #including AsmJSModule.h
|
||||||
// AsmJSModule everywhere.
|
// everywhere. Values are asserted in AsmJSModule.h.
|
||||||
static const unsigned AsmJSActivationGlobalDataOffset = 0;
|
static const unsigned AsmJSActivationGlobalDataOffset = 0;
|
||||||
|
static const unsigned AsmJSNaN64GlobalDataOffset = 2 * sizeof(void*);
|
||||||
|
static const unsigned AsmJSNaN32GlobalDataOffset = 2 * sizeof(void*) + sizeof(double);
|
||||||
|
|
||||||
// Summarizes a heap access made by asm.js code that needs to be patched later
|
// Summarizes a heap access made by asm.js code that needs to be patched later
|
||||||
// and/or looked up by the asm.js signal handlers. Different architectures need
|
// and/or looked up by the asm.js signal handlers. Different architectures need
|
||||||
|
|
Загрузка…
Ссылка в новой задаче