Backed out efc4b8a23cd7:12e8fc56b5eb (bug 876064) for asm.js test failures

This commit is contained in:
Phil Ringnalda 2013-07-01 23:06:49 -07:00
Родитель 1fddfac45e
Коммит f327c82296
13 изменённых файлов: 87 добавлений и 133 удалений

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

@ -22,7 +22,11 @@ using namespace js;
using namespace js::ion;
BaselineCompiler::BaselineCompiler(JSContext *cx, HandleScript script)
: BaselineCompilerSpecific(cx, script)
: BaselineCompilerSpecific(cx, script),
return_(new HeapLabel())
#ifdef JSGC_GENERATIONAL
, postBarrierSlot_(new HeapLabel())
#endif
{
}
@ -257,7 +261,7 @@ BaselineCompiler::emitPrologue()
bool
BaselineCompiler::emitEpilogue()
{
masm.bind(&return_);
masm.bind(return_);
// Pop SPS frame if necessary
emitSPSPop();
@ -279,7 +283,7 @@ BaselineCompiler::emitEpilogue()
bool
BaselineCompiler::emitOutOfLinePostBarrierSlot()
{
masm.bind(&postBarrierSlot_);
masm.bind(postBarrierSlot_);
Register objReg = R2.scratchReg();
GeneralRegisterSet regs(GeneralRegisterSet::All());
@ -342,7 +346,7 @@ BaselineCompiler::emitDebugPrologue()
masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, &done);
{
masm.loadValue(frame.addressOfReturnValue(), JSReturnOperand);
masm.jump(&return_);
masm.jump(return_);
}
masm.bind(&done);
return true;
@ -1820,7 +1824,7 @@ BaselineCompiler::emit_JSOP_SETALIASEDVAR()
masm.branchPtr(Assembler::Below, objReg, ImmWord(nursery.heapEnd()), &skipBarrier);
masm.bind(&isTenured);
masm.call(&postBarrierSlot_);
masm.call(postBarrierSlot_);
masm.bind(&skipBarrier);
#endif
@ -2485,7 +2489,7 @@ BaselineCompiler::emit_JSOP_DEBUGGER()
masm.branchTest32(Assembler::Zero, ReturnReg, ReturnReg, &done);
{
masm.loadValue(frame.addressOfReturnValue(), JSReturnOperand);
masm.jump(&return_);
masm.jump(return_);
}
masm.bind(&done);
return true;
@ -2518,7 +2522,7 @@ BaselineCompiler::emitReturn()
if (JSOp(*pc) != JSOP_STOP) {
// JSOP_STOP is immediately followed by the return label, so we don't
// need a jump.
masm.jump(&return_);
masm.jump(return_);
}
return true;

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

@ -184,9 +184,9 @@ namespace ion {
class BaselineCompiler : public BaselineCompilerSpecific
{
FixedList<Label> labels_;
NonAssertingLabel return_;
HeapLabel * return_;
#ifdef JSGC_GENERATIONAL
NonAssertingLabel postBarrierSlot_;
HeapLabel * postBarrierSlot_;
#endif
// Native code offset right before the scope chain is initialized.

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

@ -887,7 +887,7 @@ CodeGenerator::visitReturn(LReturn *lir)
#endif
// Don't emit a jump to the return label if this is the last block.
if (current->mir() != *gen->graph().poBegin())
masm.jump(&returnLabel_);
masm.jump(returnLabel_);
return true;
}
@ -6944,7 +6944,7 @@ CodeGenerator::visitOutOfLineParallelAbort(OutOfLineParallelAbort *ool)
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ParallelAbort));
masm.moveValue(MagicValue(JS_ION_ERROR), JSReturnOperand);
masm.jump(&returnLabel_);
masm.jump(returnLabel_);
return true;
}
@ -7004,7 +7004,7 @@ CodeGenerator::visitOutOfLinePropagateParallelAbort(OutOfLinePropagateParallelAb
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, PropagateParallelAbort));
masm.moveValue(MagicValue(JS_ION_ERROR), JSReturnOperand);
masm.jump(&returnLabel_);
masm.jump(returnLabel_);
return true;
}
@ -7097,7 +7097,7 @@ CodeGenerator::visitAsmJSReturn(LAsmJSReturn *lir)
masm.ma_vxfer(d0, r0, r1);
#endif
if (current->mir() != *gen->graph().poBegin())
masm.jump(&returnLabel_);
masm.jump(returnLabel_);
return true;
}
@ -7106,7 +7106,7 @@ CodeGenerator::visitAsmJSVoidReturn(LAsmJSVoidReturn *lir)
{
// Don't emit a jump to the return label if this is the last block.
if (current->mir() != *gen->graph().poBegin())
masm.jump(&returnLabel_);
masm.jump(returnLabel_);
return true;
}

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

@ -28,7 +28,8 @@ using namespace js::ion;
// shared
CodeGeneratorARM::CodeGeneratorARM(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm)
: CodeGeneratorShared(gen, graph, masm)
: CodeGeneratorShared(gen, graph, masm),
deoptLabel_(NULL)
{
}
@ -45,13 +46,17 @@ CodeGeneratorARM::generatePrologue()
masm.checkStackAlignment();
}
// Allocate returnLabel_ on the heap, so we don't run its destructor and
// assert-not-bound in debug mode on compilation failure.
returnLabel_ = new HeapLabel();
return true;
}
bool
CodeGeneratorARM::generateEpilogue()
{
masm.bind(&returnLabel_);
masm.bind(returnLabel_);
if (gen->compilingAsmJS()) {
// Pop the stack we allocated at the start of the function.
masm.freeStack(frameDepth_);
@ -147,9 +152,9 @@ CodeGeneratorARM::generateOutOfLineCode()
if (!CodeGeneratorShared::generateOutOfLineCode())
return false;
if (deoptLabel_.used()) {
if (deoptLabel_) {
// All non-table-based bailouts will go here.
masm.bind(&deoptLabel_);
masm.bind(deoptLabel_);
// Push the frame size, so the handler can recover the IonScript.
masm.ma_mov(Imm32(frameSize()), lr);
@ -259,10 +264,12 @@ CodeGeneratorARM::bailout(LSnapshot *snapshot)
bool
CodeGeneratorARM::visitOutOfLineBailout(OutOfLineBailout *ool)
{
if (!deoptLabel_)
deoptLabel_ = new HeapLabel();
masm.ma_mov(Imm32(ool->snapshot()->snapshotOffset()), ScratchRegister);
masm.ma_push(ScratchRegister);
masm.ma_push(ScratchRegister);
masm.ma_b(&deoptLabel_);
masm.ma_b(deoptLabel_);
return true;
}

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

@ -24,8 +24,8 @@ class CodeGeneratorARM : public CodeGeneratorShared
protected:
// Label for the common return path.
NonAssertingLabel returnLabel_;
NonAssertingLabel deoptLabel_;
HeapLabel *returnLabel_;
HeapLabel *deoptLabel_;
// ugh. this is not going to be pretty to move over.
// stack slotted variables are not useful on arm.
// it looks like this will need to return one of two types.

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

@ -278,19 +278,11 @@ class Label : public LabelBase
}
};
// Label's destructor asserts that if it has been used it has also been bound.
// In the case long-lived labels, however, failed compilation (e.g. OOM) will
// trigger this failure innocuously. This Label silences the assertion.
class NonAssertingLabel : public Label
// Wrapper around Label, on the heap, to avoid a bogus assert with OOM.
struct HeapLabel
: public TempObject,
public Label
{
public:
~NonAssertingLabel()
{
#ifdef DEBUG
if (used())
bind(0);
#endif
}
};
class RepatchLabel

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

@ -22,7 +22,8 @@ namespace js {
namespace ion {
CodeGeneratorX86Shared::CodeGeneratorX86Shared(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm)
: CodeGeneratorShared(gen, graph, masm)
: CodeGeneratorShared(gen, graph, masm),
deoptLabel_(NULL)
{
}
@ -38,13 +39,17 @@ CodeGeneratorX86Shared::generatePrologue()
// Note that this automatically sets MacroAssembler::framePushed().
masm.reserveStack(frameSize());
// Allocate returnLabel_ on the heap, so we don't run its destructor and
// assert-not-bound in debug mode on compilation failure.
returnLabel_ = new HeapLabel();
return true;
}
bool
CodeGeneratorX86Shared::generateEpilogue()
{
masm.bind(&returnLabel_);
masm.bind(returnLabel_);
// Pop the stack we allocated at the start of the function.
masm.freeStack(frameSize());
@ -223,9 +228,9 @@ CodeGeneratorX86Shared::generateOutOfLineCode()
if (!CodeGeneratorShared::generateOutOfLineCode())
return false;
if (deoptLabel_.used()) {
if (deoptLabel_) {
// All non-table-based bailouts will go here.
masm.bind(&deoptLabel_);
masm.bind(deoptLabel_);
// Push the frame size, so the handler can recover the IonScript.
masm.push(Imm32(frameSize()));
@ -344,8 +349,11 @@ CodeGeneratorX86Shared::bailout(LSnapshot *snapshot)
bool
CodeGeneratorX86Shared::visitOutOfLineBailout(OutOfLineBailout *ool)
{
if (!deoptLabel_)
deoptLabel_ = new HeapLabel();
masm.push(Imm32(ool->snapshot()->snapshotOffset()));
masm.jmp(&deoptLabel_);
masm.jmp(deoptLabel_);
return true;
}

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

@ -30,8 +30,8 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
protected:
// Label for the common return path.
NonAssertingLabel returnLabel_;
NonAssertingLabel deoptLabel_;
HeapLabel *returnLabel_;
HeapLabel *deoptLabel_;
inline Operand ToOperand(const LAllocation &a) {
if (a.isGeneralReg())

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

@ -386,22 +386,27 @@ class MacroAssemblerX86Shared : public Assembler
bind(&done);
}
bool maybeInlineDouble(double d, const FloatRegister &dest) {
uint64_t u = mozilla::BitwiseCast<uint64_t>(d);
bool maybeInlineDouble(uint64_t u, const FloatRegister &dest) {
// This implements parts of "13.4 Generating constants" of
// "2. Optimizing subroutines in assembly language" by Agner Fog,
// generalized to handle any case that can use a pcmpeqw and
// up to two shifts.
// Loading zero with xor is specially optimized in hardware.
if (u == 0) {
xorpd(dest, dest);
return true;
}
// It is also possible to load several common constants using pcmpeqw
// to get all ones and then psllq and psrlq to get zeros at the ends,
// as described in "13.4 Generating constants" of
// "2. Optimizing subroutines in assembly language" by Agner Fog, and as
// previously implemented here. However, with x86 and x64 both using
// constant pool loads for double constants, this is probably only
// worthwhile in cases where a load is likely to be delayed.
int tz = js_bitscan_ctz64(u);
int lz = js_bitscan_clz64(u);
if (u == (~uint64_t(0) << (lz + tz) >> lz)) {
pcmpeqw(dest, dest);
if (tz != 0)
psllq(Imm32(lz + tz), dest);
if (lz != 0)
psrlq(Imm32(lz), dest);
return true;
}
return false;
}

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

@ -8,65 +8,12 @@
#include "ion/BaselineFrame.h"
#include "ion/MoveEmitter.h"
#include "ion/IonFrames.h"
#include "mozilla/Casting.h"
#include "jsscriptinlines.h"
using namespace js;
using namespace js::ion;
void
MacroAssemblerX64::loadConstantDouble(double d, const FloatRegister &dest)
{
if (maybeInlineDouble(d, dest))
return;
if (!doubleMap_.initialized()) {
enoughMemory_ &= doubleMap_.init();
if (!enoughMemory_)
return;
}
size_t doubleIndex;
DoubleMap::AddPtr p = doubleMap_.lookupForAdd(d);
if (p) {
doubleIndex = p->value;
} else {
doubleIndex = doubles_.length();
enoughMemory_ &= doubles_.append(Double(d));
enoughMemory_ &= doubleMap_.add(p, d, doubleIndex);
if (!enoughMemory_)
return;
}
Double &dbl = doubles_[doubleIndex];
JS_ASSERT(!dbl.uses.bound());
// The constants will be stored in a pool appended to the text (see
// finish()), so they will always be a fixed distance from the
// instructions which reference them. This allows the instructions to use
// PC-relative addressing. Use "jump" label support code, because we need
// the same PC-relative address patching that jumps use.
JmpSrc j = masm.movsd_ripr(dest.code());
JmpSrc prev = JmpSrc(dbl.uses.use(j.offset()));
masm.setNextJump(j, prev);
}
void
MacroAssemblerX64::finish()
{
JS_STATIC_ASSERT(CodeAlignment >= sizeof(double));
if (!doubles_.empty())
masm.align(sizeof(double));
for (size_t i = 0; i < doubles_.length(); i++) {
Double &dbl = doubles_[i];
bind(&dbl.uses);
masm.doubleConstant(dbl.value);
}
MacroAssemblerX86Shared::finish();
}
void
MacroAssemblerX64::setupABICall(uint32_t args)
{

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

@ -45,16 +45,6 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
bool dynamicAlignment_;
bool enoughMemory_;
struct Double {
double value;
NonAssertingLabel uses;
Double(double value) : value(value) {}
};
Vector<Double, 0, IonAllocPolicy> doubles_;
typedef HashMap<double, size_t, DefaultHasher<double>, IonAllocPolicy> DoubleMap;
DoubleMap doubleMap_;
void setupABICall(uint32_t arg);
protected:
@ -81,10 +71,6 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
{
}
// The buffer is about to be linked, make sure any constant pools or excess
// bookkeeping has been flushed to the instruction stream.
void finish();
bool oom() const {
return MacroAssemblerX86Shared::oom() || !enoughMemory_;
}
@ -952,7 +938,17 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
cvtsi2sd(operand.valueReg(), dest);
}
void loadConstantDouble(double d, const FloatRegister &dest);
void loadConstantDouble(double d, const FloatRegister &dest) {
union DoublePun {
uint64_t u;
double d;
} pun;
pun.d = d;
if (!maybeInlineDouble(pun.u, dest)) {
mov(ImmWord(pun.u), ScratchReg);
movqsd(ScratchReg, dest);
}
}
void loadStaticDouble(const double *dp, const FloatRegister &dest) {
loadConstantDouble(*dp, dest);
}

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

@ -8,7 +8,6 @@
#include "ion/BaselineFrame.h"
#include "ion/MoveEmitter.h"
#include "ion/IonFrames.h"
#include "mozilla/Casting.h"
#include "jsscriptinlines.h"
@ -18,7 +17,12 @@ using namespace js::ion;
void
MacroAssemblerX86::loadConstantDouble(double d, const FloatRegister &dest)
{
if (maybeInlineDouble(d, dest))
union DoublePun {
uint64_t u;
double d;
} dpun;
dpun.d = d;
if (maybeInlineDouble(dpun.u, dest))
return;
if (!doubleMap_.initialized()) {
@ -38,21 +42,10 @@ MacroAssemblerX86::loadConstantDouble(double d, const FloatRegister &dest)
return;
}
Double &dbl = doubles_[doubleIndex];
JS_ASSERT(!dbl.uses.bound());
masm.movsd_mr(reinterpret_cast<const void *>(dbl.uses.prev()), dest.code());
masm.movsd_mr(reinterpret_cast<void *>(dbl.uses.prev()), dest.code());
dbl.uses.setPrev(masm.size());
}
void
MacroAssemblerX86::loadStaticDouble(const double *dp, const FloatRegister &dest) {
if (maybeInlineDouble(*dp, dest))
return;
// x86 can just load from any old immediate address.
movsd(dp, dest);
}
void
MacroAssemblerX86::finish()
{

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

@ -793,7 +793,9 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
}
void loadConstantDouble(double d, const FloatRegister &dest);
void loadStaticDouble(const double *dp, const FloatRegister &dest);
void loadStaticDouble(const double *dp, const FloatRegister &dest) {
movsd(dp, dest);
}
void branchTruncateDouble(const FloatRegister &src, const Register &dest, Label *fail) {
const uint32_t IndefiniteIntegerValue = 0x80000000;