Bug 1050254 - OdinMonkey: Place NaN in the global data and load from here to free the NANReg. r=luke

This commit is contained in:
Douglas Crosher 2014-08-13 01:12:00 +10:00
Родитель e3681d9600
Коммит 489904c774
9 изменённых файлов: 39 добавлений и 19 удалений

Просмотреть файл

@ -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