mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 05:45:37 +00:00
Bug 588021: Port GETPROP PIC for ARM. (r=dmandelin)
This commit is contained in:
parent
9e386e7eeb
commit
8dc586ec63
@ -2913,6 +2913,7 @@ i?86-*)
|
||||
ENABLE_METHODJIT=1
|
||||
ENABLE_MONOIC=1
|
||||
ENABLE_POLYIC=1
|
||||
ENABLE_POLYIC_GETPROP=1
|
||||
AC_DEFINE(JS_CPU_X86)
|
||||
AC_DEFINE(JS_NUNBOX32)
|
||||
;;
|
||||
@ -2922,6 +2923,7 @@ x86_64*-*)
|
||||
ENABLE_METHODJIT=1
|
||||
ENABLE_MONOIC=1
|
||||
ENABLE_POLYIC=1
|
||||
ENABLE_POLYIC_GETPROP=1
|
||||
AC_DEFINE(JS_CPU_X64)
|
||||
AC_DEFINE(JS_PUNBOX64)
|
||||
;;
|
||||
@ -2930,6 +2932,8 @@ arm*-*)
|
||||
NANOJIT_ARCH=ARM
|
||||
ENABLE_METHODJIT=1
|
||||
ENABLE_MONOIC=1
|
||||
ENABLE_POLYIC=1
|
||||
ENABLE_POLYIC_GETPROP=1
|
||||
AC_DEFINE(JS_CPU_ARM)
|
||||
AC_DEFINE(JS_NUNBOX32)
|
||||
;;
|
||||
@ -2975,6 +2979,26 @@ if test "$ENABLE_POLYIC"; then
|
||||
AC_DEFINE(JS_POLYIC)
|
||||
fi
|
||||
|
||||
if test "$ENABLE_POLYIC_GETPROP"; then
|
||||
AC_DEFINE(JS_POLYIC_GETPROP)
|
||||
fi
|
||||
|
||||
if test "$ENABLE_POLYIC_SETPROP"; then
|
||||
AC_DEFINE(JS_POLYIC_SETPROP)
|
||||
fi
|
||||
|
||||
if test "$ENABLE_POLYIC_NAME"; then
|
||||
AC_DEFINE(JS_POLYIC_SETPROP)
|
||||
fi
|
||||
|
||||
if test "$ENABLE_POLYIC_BIND"; then
|
||||
AC_DEFINE(JS_POLYIC_SETPROP)
|
||||
fi
|
||||
|
||||
if test "$ENABLE_POLYIC_ELEM"; then
|
||||
AC_DEFINE(JS_POLYIC_ELEM)
|
||||
fi
|
||||
|
||||
if test "$ENABLE_METHODJIT_SPEW"; then
|
||||
AC_DEFINE(JS_METHODJIT_SPEW)
|
||||
fi
|
||||
|
@ -69,10 +69,16 @@ struct MacroAssemblerTypedefs {
|
||||
typedef JSC::FunctionPtr FunctionPtr;
|
||||
typedef JSC::RepatchBuffer RepatchBuffer;
|
||||
typedef JSC::CodeLocationLabel CodeLocationLabel;
|
||||
typedef JSC::CodeLocationDataLabel32 CodeLocationDataLabel32;
|
||||
typedef JSC::CodeLocationJump CodeLocationJump;
|
||||
typedef JSC::CodeLocationCall CodeLocationCall;
|
||||
typedef JSC::CodeLocationInstruction CodeLocationInstruction;
|
||||
typedef JSC::ReturnAddressPtr ReturnAddressPtr;
|
||||
typedef JSC::MacroAssemblerCodePtr MacroAssemblerCodePtr;
|
||||
typedef JSC::JITCode JITCode;
|
||||
#if defined JS_CPU_ARM
|
||||
typedef JSC::ARMWord ARMWord;
|
||||
#endif
|
||||
};
|
||||
|
||||
class BaseCompiler : public MacroAssemblerTypedefs
|
||||
@ -195,19 +201,22 @@ class LinkerHelper : public JSC::LinkBuffer
|
||||
* up front to prevent this from happening.
|
||||
*/
|
||||
#ifdef JS_CPU_ARM
|
||||
template <size_t reservedSpace>
|
||||
class AutoReserveICSpace {
|
||||
typedef Assembler::Label Label;
|
||||
static const size_t reservedSpace = 68;
|
||||
|
||||
Assembler &masm;
|
||||
#ifdef DEBUG
|
||||
Label startLabel;
|
||||
bool didCheck;
|
||||
#endif
|
||||
|
||||
public:
|
||||
AutoReserveICSpace(Assembler &masm) : masm(masm) {
|
||||
masm.ensureSpace(reservedSpace);
|
||||
#ifdef DEBUG
|
||||
didCheck = false;
|
||||
|
||||
startLabel = masm.label();
|
||||
|
||||
/* Assert that the constant pool is not flushed until we reach a safe point. */
|
||||
@ -217,8 +226,13 @@ class AutoReserveICSpace {
|
||||
#endif
|
||||
}
|
||||
|
||||
~AutoReserveICSpace() {
|
||||
/* Allow manual IC space checks so that non-patchable code at the end of an IC section can be
|
||||
* free to use constant pools. */
|
||||
void check() {
|
||||
#ifdef DEBUG
|
||||
JS_ASSERT(!didCheck);
|
||||
didCheck = true;
|
||||
|
||||
Label endLabel = masm.label();
|
||||
int spaceUsed = masm.differenceBetween(startLabel, endLabel);
|
||||
|
||||
@ -233,12 +247,33 @@ class AutoReserveICSpace {
|
||||
|
||||
/* Allow the pool to be flushed. */
|
||||
masm.allowPoolFlush(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
~AutoReserveICSpace() {
|
||||
#ifdef DEBUG
|
||||
/* Automatically check the IC space if we didn't already do it manually. */
|
||||
if (!didCheck) {
|
||||
check();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
# define RESERVE_IC_SPACE(__masm) AutoReserveICSpace arics(__masm)
|
||||
|
||||
# define RESERVE_IC_SPACE(__masm) AutoReserveICSpace<80> arics(__masm)
|
||||
|
||||
/* The OOL path can need a lot of space because we save and restore a lot of registers. The actual
|
||||
* sequene varies. However, dumping the literal pool before an OOL block is probably a good idea
|
||||
* anyway, as we branch directly to the start of the block from the fast path. */
|
||||
# define RESERVE_OOL_SPACE(__masm) AutoReserveICSpace<256> arics_ool(__masm)
|
||||
|
||||
/* Allow the OOL patch to be checked before object destruction. Often, non-patchable epilogues or
|
||||
* rejoining sequences are emitted, and it isn't necessary to protect these from literal pools. */
|
||||
# define CHECK_OOL_SPACE() arics_ool.check()
|
||||
#else
|
||||
# define RESERVE_IC_SPACE(__masm) /* Nothing. */
|
||||
# define RESERVE_IC_SPACE(__masm) /* Do nothing. */
|
||||
# define RESERVE_OOL_SPACE(__masm) /* Do nothing. */
|
||||
# define CHECK_OOL_SPACE() /* Do nothing. */
|
||||
#endif
|
||||
|
||||
} /* namespace js */
|
||||
|
@ -2969,7 +2969,9 @@ mjit::Compiler::passICAddress(BaseICInfo *ic)
|
||||
{
|
||||
ic->paramAddr = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined JS_POLYIC_GETPROP
|
||||
bool
|
||||
mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache)
|
||||
{
|
||||
@ -2995,10 +2997,12 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache)
|
||||
shapeReg = frame.allocReg();
|
||||
}
|
||||
|
||||
RESERVE_IC_SPACE(masm);
|
||||
|
||||
PICGenInfo pic(ic::PICInfo::GET, JSOp(*PC), usePropCache);
|
||||
|
||||
/* Guard that the type is an object. */
|
||||
Jump typeCheck;
|
||||
Label typeCheck;
|
||||
if (doTypeCheck && !top->isTypeKnown()) {
|
||||
RegisterID reg = frame.tempRegForType(top);
|
||||
pic.typeReg = reg;
|
||||
@ -3006,10 +3010,8 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache)
|
||||
/* Start the hot path where it's easy to patch it. */
|
||||
pic.fastPathStart = masm.label();
|
||||
Jump j = masm.testObject(Assembler::NotEqual, reg);
|
||||
|
||||
/* GETPROP_INLINE_TYPE_GUARD is used to patch the jmp, not cmp. */
|
||||
typeCheck = masm.label();
|
||||
RETURN_IF_OOM(false);
|
||||
JS_ASSERT(masm.differenceBetween(pic.fastPathStart, masm.label()) == GETPROP_INLINE_TYPE_GUARD);
|
||||
|
||||
pic.typeCheck = stubcc.linkExit(j, Uses(1));
|
||||
pic.hasTypeCheck = true;
|
||||
@ -3035,52 +3037,43 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache)
|
||||
Jump j = masm.branch32WithPatch(Assembler::NotEqual, shapeReg,
|
||||
Imm32(int32(JSObjectMap::INVALID_SHAPE)),
|
||||
inlineShapeLabel);
|
||||
DBGLABEL(dbgInlineShapeJump);
|
||||
Label inlineShapeJump = masm.label();
|
||||
|
||||
RESERVE_OOL_SPACE(stubcc.masm);
|
||||
pic.slowPathStart = stubcc.linkExit(j, Uses(1));
|
||||
|
||||
stubcc.leave();
|
||||
passICAddress(&pic);
|
||||
pic.slowPathCall = OOL_STUBCALL(ic::GetProp);
|
||||
CHECK_OOL_SPACE();
|
||||
|
||||
/* Load dslots. */
|
||||
Label dslotsLoadLabel = masm.label();
|
||||
masm.loadPtr(Address(objReg, offsetof(JSObject, slots)), objReg);
|
||||
/* Load the base slot address. */
|
||||
Label dslotsLoadLabel = masm.loadPtrWithPatchToLEA(Address(objReg, offsetof(JSObject, slots)),
|
||||
objReg);
|
||||
|
||||
/* Copy the slot value to the expression stack. */
|
||||
Address slot(objReg, 1 << 24);
|
||||
frame.pop();
|
||||
|
||||
#if defined JS_NUNBOX32
|
||||
masm.loadTypeTag(slot, shapeReg);
|
||||
Label typeLoad = masm.label();
|
||||
|
||||
masm.loadPayload(slot, objReg);
|
||||
Label dataLoad = masm.label();
|
||||
#elif defined JS_PUNBOX64
|
||||
Label inlineValueLoadLabel = masm.loadValueAsComponents(slot, shapeReg, objReg);
|
||||
#endif
|
||||
Label fastValueLoad = masm.loadValueWithAddressOffsetPatch(slot, shapeReg, objReg);
|
||||
pic.fastPathRejoin = masm.label();
|
||||
|
||||
RETURN_IF_OOM(false);
|
||||
|
||||
/* Initialize op labels. */
|
||||
GetPropLabels &labels = pic.getPropLabels();
|
||||
labels.setDslotsLoadOffset(masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel));
|
||||
labels.setInlineShapeOffset(masm.differenceBetween(pic.shapeGuard, inlineShapeLabel));
|
||||
labels.setDslotsLoad(masm, pic.fastPathRejoin, dslotsLoadLabel);
|
||||
labels.setInlineShapeData(masm, pic.shapeGuard, inlineShapeLabel);
|
||||
|
||||
#if defined JS_NUNBOX32
|
||||
labels.setTypeLoad(masm.differenceBetween(pic.fastPathRejoin, typeLoad));
|
||||
labels.setDataLoad(masm.differenceBetween(pic.fastPathRejoin, dataLoad));
|
||||
|
||||
JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP);
|
||||
#elif defined JS_PUNBOX64
|
||||
labels.setValueLoad(masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel));
|
||||
|
||||
JS_ASSERT(masm.differenceBetween(inlineShapeLabel, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP);
|
||||
labels.setValueLoad(masm, pic.fastPathRejoin, fastValueLoad);
|
||||
if (pic.hasTypeCheck)
|
||||
labels.setInlineTypeJump(masm, pic.fastPathStart, typeCheck);
|
||||
#ifdef JS_CPU_X64
|
||||
labels.setInlineShapeJump(masm, inlineShapeLabel, inlineShapeJump);
|
||||
#else
|
||||
labels.setInlineShapeJump(masm, pic.shapeGuard, inlineShapeJump);
|
||||
#endif
|
||||
|
||||
/* GETPROP_INLINE_TYPE_GUARD's validity is asserted above. */
|
||||
|
||||
pic.objReg = objReg;
|
||||
frame.pushRegs(shapeReg, objReg);
|
||||
|
||||
@ -3089,7 +3082,9 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck, bool usePropCache)
|
||||
pics.append(pic);
|
||||
return true;
|
||||
}
|
||||
#endif /* JS_POLYIC_GETPROP */
|
||||
|
||||
#if defined JS_POLYIC_CALLPROP
|
||||
bool
|
||||
mjit::Compiler::jsop_callprop_generic(JSAtom *atom)
|
||||
{
|
||||
@ -3171,15 +3166,7 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom)
|
||||
/* Copy the slot value to the expression stack. */
|
||||
Address slot(objReg, 1 << 24);
|
||||
|
||||
#if defined JS_NUNBOX32
|
||||
masm.loadTypeTag(slot, shapeReg);
|
||||
Label typeLoad = masm.label();
|
||||
|
||||
masm.loadPayload(slot, objReg);
|
||||
Label dataLoad = masm.label();
|
||||
#elif defined JS_PUNBOX64
|
||||
Label inlineValueLoadLabel = masm.loadValueAsComponents(slot, shapeReg, objReg);
|
||||
#endif
|
||||
Label fastValueLoad = masm.loadValueWithAddressOffsetPatch(slot, shapeReg, objReg);
|
||||
pic.fastPathRejoin = masm.label();
|
||||
|
||||
/* Assert correctness of hardcoded offsets. */
|
||||
@ -3189,14 +3176,10 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom)
|
||||
GetPropLabels &labels = pic.getPropLabels();
|
||||
labels.setDslotsLoadOffset(masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel));
|
||||
labels.setInlineShapeOffset(masm.differenceBetween(pic.shapeGuard, inlineShapeLabel));
|
||||
labels.setValueLoad(masm, pic.fastPathRejoin, fastValueLoad);
|
||||
#if defined JS_NUNBOX32
|
||||
labels.setTypeLoad(masm.differenceBetween(pic.fastPathRejoin, typeLoad));
|
||||
labels.setDataLoad(masm.differenceBetween(pic.fastPathRejoin, dataLoad));
|
||||
|
||||
JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP);
|
||||
#elif defined JS_PUNBOX64
|
||||
labels.setValueLoad(masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel));
|
||||
|
||||
JS_ASSERT(masm.differenceBetween(inlineShapeLabel, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP);
|
||||
#endif
|
||||
|
||||
@ -3309,15 +3292,7 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom)
|
||||
/* Copy the slot value to the expression stack. */
|
||||
Address slot(objReg, 1 << 24);
|
||||
|
||||
#if defined JS_NUNBOX32
|
||||
masm.loadTypeTag(slot, shapeReg);
|
||||
Label dbgTypeLoad = masm.label();
|
||||
|
||||
masm.loadPayload(slot, objReg);
|
||||
Label dbgDataLoad = masm.label();
|
||||
#elif defined JS_PUNBOX64
|
||||
Label inlineValueLoadLabel = masm.loadValueAsComponents(slot, shapeReg, objReg);
|
||||
#endif
|
||||
Label fastValueLoad = masm.loadValueWithAddressOffsetPatch(slot, shapeReg, objReg);
|
||||
|
||||
pic.fastPathRejoin = masm.label();
|
||||
pic.objReg = objReg;
|
||||
@ -3344,14 +3319,11 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom)
|
||||
GetPropLabels &labels = pic.getPropLabels();
|
||||
labels.setDslotsLoadOffset(masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel));
|
||||
labels.setInlineShapeOffset(masm.differenceBetween(pic.shapeGuard, inlineShapeLabel));
|
||||
#if defined JS_NUNBOX32
|
||||
labels.setTypeLoad(masm.differenceBetween(pic.fastPathRejoin, dbgTypeLoad));
|
||||
labels.setDataLoad(masm.differenceBetween(pic.fastPathRejoin, dbgDataLoad));
|
||||
labels.setValueLoad(masm, pic.fastPathRejoin, fastValueLoad);
|
||||
|
||||
#if defined JS_NUNBOX32
|
||||
JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP);
|
||||
#elif defined JS_PUNBOX64
|
||||
labels.setValueLoad(masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel));
|
||||
|
||||
JS_ASSERT(masm.differenceBetween(inlineShapeLabel, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP);
|
||||
#endif
|
||||
|
||||
@ -3377,7 +3349,9 @@ mjit::Compiler::jsop_callprop(JSAtom *atom)
|
||||
return jsop_callprop_obj(atom);
|
||||
return jsop_callprop_generic(atom);
|
||||
}
|
||||
#endif /* JS_POLYIC_CALLPROP */
|
||||
|
||||
#ifdef JS_POLYIC_SETPROP
|
||||
bool
|
||||
mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache)
|
||||
{
|
||||
@ -3516,7 +3490,9 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache)
|
||||
pics.append(pic);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JS_POLYIC_NAME
|
||||
void
|
||||
mjit::Compiler::jsop_name(JSAtom *atom)
|
||||
{
|
||||
@ -3593,6 +3569,9 @@ mjit::Compiler::jsop_xname(JSAtom *atom)
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* JSOP_POLYIC_NAME */
|
||||
|
||||
#ifdef JS_POLYIC_BIND
|
||||
void
|
||||
mjit::Compiler::jsop_bindname(JSAtom *atom, bool usePropCache)
|
||||
{
|
||||
@ -3641,9 +3620,9 @@ mjit::Compiler::jsop_bindname(JSAtom *atom, bool usePropCache)
|
||||
|
||||
pics.append(pic);
|
||||
}
|
||||
#endif /* JS_POLYIC_BIND */
|
||||
|
||||
#else /* JS_POLYIC */
|
||||
|
||||
#if !defined JS_POLYIC_NAME
|
||||
void
|
||||
mjit::Compiler::jsop_name(JSAtom *atom)
|
||||
{
|
||||
@ -3657,27 +3636,35 @@ mjit::Compiler::jsop_xname(JSAtom *atom)
|
||||
{
|
||||
return jsop_getprop(atom);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined JS_POLYIC_GETPROP
|
||||
bool
|
||||
mjit::Compiler::jsop_getprop(JSAtom *atom, bool typecheck, bool usePropCache)
|
||||
{
|
||||
jsop_getprop_slow(atom, usePropCache);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined JS_POLYIC_CALLPROP
|
||||
bool
|
||||
mjit::Compiler::jsop_callprop(JSAtom *atom)
|
||||
{
|
||||
return jsop_callprop_slow(atom);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined JS_POLYIC_SETPROP
|
||||
bool
|
||||
mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache)
|
||||
{
|
||||
jsop_setprop_slow(atom, usePropCache);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined JS_POLYIC_BIND
|
||||
void
|
||||
mjit::Compiler::jsop_bindname(JSAtom *atom, bool usePropCache)
|
||||
{
|
||||
@ -4355,9 +4342,9 @@ mjit::Compiler::jsop_getgname(uint32 index)
|
||||
Address address(objReg, slot);
|
||||
|
||||
/* Allocate any register other than objReg. */
|
||||
RegisterID dreg = frame.allocReg();
|
||||
RegisterID treg = frame.allocReg();
|
||||
/* After dreg is loaded, it's safe to clobber objReg. */
|
||||
RegisterID treg = objReg;
|
||||
RegisterID dreg = objReg;
|
||||
|
||||
mic.load = masm.loadValueWithAddressOffsetPatch(address, treg, dreg);
|
||||
|
||||
|
@ -1286,7 +1286,7 @@ mjit::Compiler::jsop_setelem(bool popGuaranteed)
|
||||
stubcc.linkExitDirect(ic.holeGuard, ic.slowPathStart);
|
||||
|
||||
stubcc.leave();
|
||||
#ifdef JS_POLYIC
|
||||
#if defined JS_POLYIC && defined JS_POLYIC_SETELEM
|
||||
passICAddress(&ic);
|
||||
ic.slowPathCall = OOL_STUBCALL(STRICT_VARIANT(ic::SetElement));
|
||||
#else
|
||||
@ -1326,7 +1326,7 @@ mjit::Compiler::jsop_setelem(bool popGuaranteed)
|
||||
frame.shimmy(2);
|
||||
stubcc.rejoin(Changes(2));
|
||||
|
||||
#ifdef JS_POLYIC
|
||||
#if defined JS_POLYIC && defined JS_POLYIC_SETELEM
|
||||
if (!setElemICs.append(ic))
|
||||
return false;
|
||||
#endif
|
||||
@ -1341,7 +1341,7 @@ IsCacheableGetElem(FrameEntry *obj, FrameEntry *id)
|
||||
return false;
|
||||
if (id->isTypeKnown() &&
|
||||
!(id->getKnownType() == JSVAL_TYPE_INT32
|
||||
#ifdef JS_POLYIC
|
||||
#if defined JS_POLYIC && defined JS_POLYIC_GETELEM
|
||||
|| id->getKnownType() == JSVAL_TYPE_STRING
|
||||
#endif
|
||||
)) {
|
||||
@ -1471,7 +1471,7 @@ mjit::Compiler::jsop_getelem(bool isCall)
|
||||
stubcc.leave();
|
||||
if (objTypeGuard.isSet())
|
||||
objTypeGuard.get().linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
#ifdef JS_POLYIC
|
||||
#if defined JS_POLYIC && defined JS_POLYIC_GETELEM
|
||||
passICAddress(&ic);
|
||||
if (isCall)
|
||||
ic.slowPathCall = OOL_STUBCALL(ic::CallElement);
|
||||
@ -1493,7 +1493,7 @@ mjit::Compiler::jsop_getelem(bool isCall)
|
||||
|
||||
stubcc.rejoin(Changes(2));
|
||||
|
||||
#ifdef JS_POLYIC
|
||||
#if defined JS_POLYIC && defined JS_POLYIC_GETELEM
|
||||
if (!getElemICs.append(ic))
|
||||
return false;
|
||||
#endif
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "jsvector.h"
|
||||
#include "assembler/assembler/MacroAssembler.h"
|
||||
#include "assembler/assembler/CodeLocation.h"
|
||||
#include "methodjit/CodeGenIncludes.h"
|
||||
#include "methodjit/MethodJIT.h"
|
||||
#include "BaseAssembler.h"
|
||||
#include "RematInfo.h"
|
||||
@ -62,20 +63,89 @@ namespace js {
|
||||
namespace mjit {
|
||||
namespace ic {
|
||||
|
||||
#if defined JS_CPU_X64 || defined JS_CPU_ARM
|
||||
/*
|
||||
* On x64 and ARM, we create offsets dynamically instead of using hardcoded
|
||||
* offsets into the instruction stream. This is done on x64 because of
|
||||
* variable-width instruction encoding when using the extended register set and
|
||||
* it is done on ARM for expediency of implementation.
|
||||
* On x64 and ARM, we record offsets into the labels data structures at runtime
|
||||
* instead of using hardcoded offsets into the instruction stream, as we do on
|
||||
* x86.
|
||||
*
|
||||
* This is done on x64 because of variable-width instruction encoding when
|
||||
* using the extended register set. It is done on ARM for ease of
|
||||
* implementation.
|
||||
*/
|
||||
|
||||
#if defined JS_CPU_X64 || defined JS_CPU_ARM
|
||||
# define JS_HAS_IC_LABELS
|
||||
#endif
|
||||
|
||||
# define JS_POLYIC_OFFSET_BITS 8
|
||||
|
||||
/* GetPropCompiler */
|
||||
struct GetPropLabels {
|
||||
struct GetPropLabels : MacroAssemblerTypedefs {
|
||||
friend class ::ICOffsetInitializer;
|
||||
|
||||
void setValueLoad(MacroAssembler &masm, Label fastPathRejoin, Label fastValueLoad) {
|
||||
int offset = masm.differenceBetween(fastPathRejoin, fastValueLoad);
|
||||
#ifdef JS_HAS_IC_LABELS
|
||||
inlineValueLoadOffset = offset;
|
||||
#endif
|
||||
/*
|
||||
* Note: the offset between the type and data loads for x86 is asserted
|
||||
* in NunboxAssembler::loadValueWithAddressOffsetPatch.
|
||||
*/
|
||||
JS_ASSERT(offset == inlineValueLoadOffset);
|
||||
}
|
||||
|
||||
CodeLocationLabel getValueLoad(CodeLocationLabel fastPathRejoin) {
|
||||
return fastPathRejoin.labelAtOffset(inlineValueLoadOffset);
|
||||
}
|
||||
|
||||
void setDslotsLoad(MacroAssembler &masm, Label fastPathRejoin, Label dslotsLoad) {
|
||||
int offset = masm.differenceBetween(fastPathRejoin, dslotsLoad);
|
||||
setDslotsLoadOffset(offset);
|
||||
}
|
||||
|
||||
CodeLocationInstruction getDslotsLoad(CodeLocationLabel fastPathRejoin) {
|
||||
return fastPathRejoin.instructionAtOffset(getDslotsLoadOffset());
|
||||
}
|
||||
|
||||
void setInlineShapeData(MacroAssembler &masm, Label shapeGuard, DataLabel32 inlineShape) {
|
||||
int offset = masm.differenceBetween(shapeGuard, inlineShape);
|
||||
setInlineShapeOffset(offset);
|
||||
}
|
||||
|
||||
CodeLocationDataLabel32 getInlineShapeData(CodeLocationLabel fastShapeGuard) {
|
||||
return fastShapeGuard.dataLabel32AtOffset(getInlineShapeOffset());
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: on x64, the base is the inlineShapeLabel DataLabel32, whereas on other
|
||||
* platforms the base is the shapeGuard.
|
||||
*/
|
||||
template <typename T>
|
||||
void setInlineShapeJump(MacroAssembler &masm, T base, Label afterJump) {
|
||||
setInlineShapeJumpOffset(masm.differenceBetween(base, afterJump));
|
||||
}
|
||||
|
||||
CodeLocationJump getInlineShapeJump(CodeLocationLabel fastShapeGuard) {
|
||||
return fastShapeGuard.jumpAtOffset(getInlineShapeJumpOffset());
|
||||
}
|
||||
|
||||
void setInlineTypeJump(MacroAssembler &masm, Label fastPathStart, Label afterTypeJump) {
|
||||
int offset = masm.differenceBetween(fastPathStart, afterTypeJump);
|
||||
setInlineTypeJumpOffset(offset);
|
||||
}
|
||||
|
||||
CodeLocationJump getInlineTypeJump(CodeLocationLabel fastPathStart) {
|
||||
#if defined JS_CPU_X86 || defined JS_CPU_X64
|
||||
return fastPathStart.jumpAtOffset(getInlineTypeJumpOffset());
|
||||
#elif defined JS_CPU_ARM
|
||||
/* Type check is after the testObject, so offset by one instruction to get the jump. */
|
||||
return fastPathStart.jumpAtOffset(getInlineTypeJumpOffset() - sizeof(ARMWord));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Offset-based interface */
|
||||
|
||||
void setDslotsLoadOffset(int offset) {
|
||||
#ifdef JS_HAS_IC_LABELS
|
||||
dslotsLoadOffset = offset;
|
||||
@ -92,41 +162,41 @@ struct GetPropLabels {
|
||||
|
||||
void setStubShapeJump(int offset) {
|
||||
#ifdef JS_HAS_IC_LABELS
|
||||
stubShapeJump = offset;
|
||||
stubShapeJumpOffset = offset;
|
||||
#endif
|
||||
JS_ASSERT(offset == stubShapeJump);
|
||||
JS_ASSERT(offset == stubShapeJumpOffset);
|
||||
}
|
||||
|
||||
#if defined JS_NUNBOX32
|
||||
void setTypeLoad(int offset) {
|
||||
# if defined JS_HAS_IC_LABELS
|
||||
inlineTypeLoad = offset;
|
||||
# endif
|
||||
JS_ASSERT(offset == inlineTypeLoad);
|
||||
}
|
||||
void setDataLoad(int offset) {
|
||||
# if defined JS_HAS_IC_LABELS
|
||||
inlineDataLoad = offset;
|
||||
# endif
|
||||
JS_ASSERT(offset == inlineDataLoad);
|
||||
}
|
||||
JSC::CodeLocationDataLabel32 getTypeLoad(JSC::CodeLocationLabel start) {
|
||||
return start.dataLabel32AtOffset(inlineTypeLoad);
|
||||
}
|
||||
JSC::CodeLocationDataLabel32 getDataLoad(JSC::CodeLocationLabel start) {
|
||||
return start.dataLabel32AtOffset(inlineDataLoad);
|
||||
}
|
||||
#elif defined JS_PUNBOX64
|
||||
void setValueLoad(int offset) {
|
||||
# if defined JS_HAS_IC_LABELS
|
||||
inlineValueLoad = offset;
|
||||
# endif
|
||||
JS_ASSERT(offset == inlineValueLoad);
|
||||
}
|
||||
JSC::CodeLocationDataLabel32 getValueLoad(JSC::CodeLocationLabel start) {
|
||||
return start.dataLabel32AtOffset(inlineValueLoad);
|
||||
}
|
||||
int getInlineShapeJumpOffset() {
|
||||
#if defined JS_CPU_X86
|
||||
return INLINE_SHAPE_JUMP;
|
||||
#elif defined JS_CPU_X64
|
||||
return getInlineShapeOffset() + INLINE_SHAPE_JUMP;
|
||||
#elif defined JS_CPU_ARM
|
||||
return INLINE_SHAPE_JUMP - sizeof(ARMWord);
|
||||
#endif
|
||||
}
|
||||
|
||||
void setInlineShapeJumpOffset(int offset) {
|
||||
JS_ASSERT(INLINE_SHAPE_JUMP == offset);
|
||||
}
|
||||
|
||||
int getInlineTypeJumpOffset() {
|
||||
#if defined JS_CPU_X86 || defined JS_CPU_X64
|
||||
return INLINE_TYPE_JUMP;
|
||||
#elif defined JS_CPU_ARM
|
||||
return inlineTypeJumpOffset;
|
||||
#endif
|
||||
}
|
||||
|
||||
void setInlineTypeJumpOffset(int offset) {
|
||||
#if defined JS_CPU_X86 || defined JS_CPU_X64
|
||||
JS_ASSERT(INLINE_TYPE_JUMP == offset);
|
||||
#elif defined JS_CPU_ARM
|
||||
inlineTypeJumpOffset = offset;
|
||||
JS_ASSERT(offset == inlineTypeJumpOffset);
|
||||
#endif
|
||||
}
|
||||
|
||||
int getInlineShapeOffset() {
|
||||
return inlineShapeOffset;
|
||||
@ -134,8 +204,12 @@ struct GetPropLabels {
|
||||
int getDslotsLoadOffset() {
|
||||
return dslotsLoadOffset;
|
||||
}
|
||||
int getStubShapeJump() {
|
||||
return stubShapeJump;
|
||||
int getStubShapeJumpOffset() {
|
||||
#if defined JS_CPU_X86 || defined JS_CPU_X64
|
||||
return stubShapeJumpOffset;
|
||||
#elif defined JS_CPU_ARM
|
||||
return stubShapeJumpOffset - sizeof(ARMWord);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
@ -146,19 +220,28 @@ struct GetPropLabels {
|
||||
int32 inlineShapeOffset : 8;
|
||||
|
||||
/* Offset from storeBack to end of value load. */
|
||||
#ifdef JS_NUNBOX32
|
||||
int32 inlineTypeLoad : 8;
|
||||
int32 inlineDataLoad : 8;
|
||||
#elif JS_PUNBOX64
|
||||
int32 inlineValueLoad : 8;
|
||||
#endif
|
||||
int32 inlineValueLoadOffset : 8;
|
||||
|
||||
/*
|
||||
* Offset from lastStubStart to end of shape jump.
|
||||
* TODO: We can redefine the location of lastStubStart to be
|
||||
* after the jump -- at which point this is always 0.
|
||||
*/
|
||||
int32 stubShapeJump : 8;
|
||||
int32 stubShapeJumpOffset : 8;
|
||||
|
||||
#if defined JS_CPU_X86
|
||||
static const int32 INLINE_SHAPE_JUMP = 12;
|
||||
static const int32 INLINE_TYPE_JUMP = 12;
|
||||
#elif defined JS_CPU_X64
|
||||
static const int32 INLINE_SHAPE_JUMP = 6;
|
||||
static const int32 INLINE_TYPE_JUMP = 19;
|
||||
#elif defined JS_CPU_ARM
|
||||
/* Offset from the shape guard start to the shape guard jump. */
|
||||
static const int32 INLINE_SHAPE_JUMP = 12;
|
||||
|
||||
/* Offset from the fast path to the type guard jump. */
|
||||
int32 inlineTypeJumpOffset : 8;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* SetPropCompiler */
|
||||
@ -206,7 +289,7 @@ struct SetPropLabels {
|
||||
|
||||
private:
|
||||
#ifdef JS_PUNBOX64
|
||||
/* Offset from storeBack to beginning of 'mov dslots, addr' */
|
||||
/* Offset from storeBack to beginning of 'mov dslots, addr'. */
|
||||
int32 dslotsLoadOffset : 8;
|
||||
#endif
|
||||
|
||||
|
@ -98,14 +98,14 @@ class Repatcher : public JSC::RepatchBuffer
|
||||
#if defined JS_CPU_X64 || defined JS_CPU_ARM
|
||||
repatch(label.dataLabel32AtOffset(0), offset);
|
||||
#elif defined JS_CPU_X86
|
||||
static const unsigned LOAD_DATA_OFFSET = 6;
|
||||
static const unsigned LOAD_TYPE_OFFSET = 12;
|
||||
static const unsigned LOAD_TYPE_OFFSET = 6;
|
||||
static const unsigned LOAD_DATA_OFFSET = 12;
|
||||
|
||||
/*
|
||||
* We have the following sequence to patch:
|
||||
*
|
||||
* mov <offset+0>($base), %<data>
|
||||
* mov <offset+4>($base), %<type>
|
||||
* mov <offset+0>($base), %<data>
|
||||
*/
|
||||
repatch(label.dataLabel32AtOffset(LOAD_DATA_OFFSET), offset);
|
||||
repatch(label.dataLabel32AtOffset(LOAD_TYPE_OFFSET), offset + 4);
|
||||
|
@ -166,11 +166,11 @@ class NunboxAssembler : public JSC::MacroAssembler
|
||||
* ICRepatcher::patchAddressOffsetForValueLoad to patch the address'
|
||||
* offset.
|
||||
*
|
||||
* The type register is guaranteed to be clobbered last. (This makes the
|
||||
* base register for the address reusable as 'treg'.)
|
||||
* The data register is guaranteed to be clobbered last. (This makes the
|
||||
* base register for the address reusable as 'dreg'.)
|
||||
*/
|
||||
Label loadValueWithAddressOffsetPatch(Address address, RegisterID treg, RegisterID dreg) {
|
||||
JS_ASSERT(address.base != dreg); /* dreg is clobbered first. */
|
||||
JS_ASSERT(address.base != treg); /* treg is clobbered first. */
|
||||
|
||||
Label start = label();
|
||||
#if defined JS_CPU_X86
|
||||
@ -178,12 +178,12 @@ class NunboxAssembler : public JSC::MacroAssembler
|
||||
* On x86 there are two loads to patch and they both encode the offset
|
||||
* in-line.
|
||||
*/
|
||||
loadPayload(address, dreg);
|
||||
DBGLABEL_NOMASM(endPayload);
|
||||
loadTypeTag(address, treg);
|
||||
DBGLABEL_NOMASM(endType);
|
||||
JS_ASSERT(differenceBetween(start, endPayload) == 6);
|
||||
JS_ASSERT(differenceBetween(endPayload, endType) == 6);
|
||||
loadPayload(address, dreg);
|
||||
DBGLABEL_NOMASM(endPayload);
|
||||
JS_ASSERT(differenceBetween(start, endType) == 6);
|
||||
JS_ASSERT(differenceBetween(endType, endPayload) == 6);
|
||||
return start;
|
||||
#elif defined JS_CPU_ARM
|
||||
/*
|
||||
|
@ -77,9 +77,8 @@ ICOffsetInitializer::ICOffsetInitializer()
|
||||
#if defined JS_CPU_X86
|
||||
labels.dslotsLoadOffset = -15;
|
||||
labels.inlineShapeOffset = 6;
|
||||
labels.inlineTypeLoad = -6;
|
||||
labels.inlineDataLoad = 0;
|
||||
labels.stubShapeJump = 12;
|
||||
labels.stubShapeJumpOffset = 12;
|
||||
labels.inlineValueLoadOffset = -12;
|
||||
#endif
|
||||
}
|
||||
{
|
||||
@ -173,6 +172,7 @@ class PICStubCompiler : public BaseCompiler
|
||||
}
|
||||
};
|
||||
|
||||
#if defined JS_POLYIC_SETPROP
|
||||
class SetPropCompiler : public PICStubCompiler
|
||||
{
|
||||
JSObject *obj;
|
||||
@ -308,7 +308,7 @@ class SetPropCompiler : public PICStubCompiler
|
||||
// the offsets are different.
|
||||
int shapeGuardJumpOffset;
|
||||
if (pic.stubsGenerated)
|
||||
shapeGuardJumpOffset = pic.setPropLabels().getStubShapeJump();
|
||||
shapeGuardJumpOffset = pic.setPropLabels().getStubShapeJumpOffset();
|
||||
else
|
||||
shapeGuardJumpOffset = pic.shapeGuard + inlineShapeJump();
|
||||
repatcher.relink(label.jumpAtOffset(shapeGuardJumpOffset), cs);
|
||||
@ -671,6 +671,7 @@ class SetPropCompiler : public PICStubCompiler
|
||||
return generateStub(obj->shape(), shape, false, !obj->hasSlotsArray());
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
static bool
|
||||
IsCacheableProtoChain(JSObject *obj, JSObject *holder)
|
||||
@ -755,40 +756,13 @@ struct GetPropertyHelper {
|
||||
}
|
||||
};
|
||||
|
||||
#if defined JS_POLYIC_GETPROP
|
||||
class GetPropCompiler : public PICStubCompiler
|
||||
{
|
||||
JSObject *obj;
|
||||
JSAtom *atom;
|
||||
int lastStubSecondShapeGuard;
|
||||
|
||||
static int32 inlineShapeOffset(ic::PICInfo &pic) {
|
||||
return pic.getPropLabels().getInlineShapeOffset();
|
||||
}
|
||||
|
||||
inline int32 inlineShapeOffset() {
|
||||
return inlineShapeOffset(pic);
|
||||
}
|
||||
|
||||
static int32 inlineShapeJump(ic::PICInfo &pic) {
|
||||
#if defined JS_NUNBOX32
|
||||
return GETPROP_INLINE_SHAPE_JUMP;
|
||||
#elif defined JS_PUNBOX64
|
||||
return inlineShapeOffset(pic) + GETPROP_INLINE_SHAPE_JUMP;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int32 inlineShapeJump() {
|
||||
return inlineShapeJump(pic);
|
||||
}
|
||||
|
||||
static int32 dslotsLoad(ic::PICInfo &pic) {
|
||||
return pic.getPropLabels().getDslotsLoadOffset();
|
||||
}
|
||||
|
||||
inline int32 dslotsLoad() {
|
||||
return dslotsLoad(pic);
|
||||
}
|
||||
|
||||
public:
|
||||
GetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, JSAtom *atom,
|
||||
VoidStubPIC stub)
|
||||
@ -799,18 +773,26 @@ class GetPropCompiler : public PICStubCompiler
|
||||
lastStubSecondShapeGuard(pic.secondShapeGuard)
|
||||
{ }
|
||||
|
||||
int getLastStubSecondShapeGuard() const {
|
||||
#if defined JS_CPU_ARM
|
||||
/* Jumps on ARM point at the beginning of the instruction. */
|
||||
return lastStubSecondShapeGuard ? lastStubSecondShapeGuard - sizeof(JSC::ARMWord) : 0;
|
||||
#else
|
||||
return lastStubSecondShapeGuard;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void reset(Repatcher &repatcher, ic::PICInfo &pic)
|
||||
{
|
||||
repatcher.repatchLEAToLoadPtr(pic.fastPathRejoin.instructionAtOffset(dslotsLoad(pic)));
|
||||
repatcher.repatch(pic.fastPathStart.dataLabel32AtOffset(
|
||||
pic.shapeGuard + inlineShapeOffset(pic)),
|
||||
GetPropLabels &labels = pic.getPropLabels();
|
||||
repatcher.repatchLEAToLoadPtr(labels.getDslotsLoad(pic.fastPathRejoin));
|
||||
repatcher.repatch(labels.getInlineShapeData(pic.getFastShapeGuard()),
|
||||
int32(JSObjectMap::INVALID_SHAPE));
|
||||
repatcher.relink(pic.fastPathStart.jumpAtOffset(pic.shapeGuard + inlineShapeJump(pic)),
|
||||
pic.slowPathStart);
|
||||
repatcher.relink(labels.getInlineShapeJump(pic.getFastShapeGuard()), pic.slowPathStart);
|
||||
|
||||
if (pic.hasTypeCheck()) {
|
||||
repatcher.relink(pic.fastPathStart.jumpAtOffset(GETPROP_INLINE_TYPE_GUARD),
|
||||
pic.slowPathStart.labelAtOffset(pic.u.get.typeCheckOffset));
|
||||
/* TODO: combine pic.u.get into ICLabels? */
|
||||
repatcher.relink(labels.getInlineTypeJump(pic.fastPathStart), pic.getSlowTypeCheck());
|
||||
}
|
||||
|
||||
VoidStubPIC stub;
|
||||
@ -1001,7 +983,7 @@ class GetPropCompiler : public PICStubCompiler
|
||||
return disable("code memory is out of range");
|
||||
}
|
||||
|
||||
buffer.link(notString, pic.slowPathStart.labelAtOffset(pic.u.get.typeCheckOffset));
|
||||
buffer.link(notString, pic.getSlowTypeCheck());
|
||||
buffer.link(shapeMismatch, pic.slowPathStart);
|
||||
buffer.link(done, pic.fastPathRejoin);
|
||||
|
||||
@ -1012,7 +994,7 @@ class GetPropCompiler : public PICStubCompiler
|
||||
/* Patch the type check to jump here. */
|
||||
if (pic.hasTypeCheck()) {
|
||||
Repatcher repatcher(f.jit());
|
||||
repatcher.relink(pic.fastPathStart.jumpAtOffset(GETPROP_INLINE_TYPE_GUARD), cs);
|
||||
repatcher.relink(pic.getPropLabels().getInlineTypeJump(pic.fastPathStart), cs);
|
||||
}
|
||||
|
||||
/* Disable the PIC so we don't keep generating stubs on the above shape mismatch. */
|
||||
@ -1043,7 +1025,7 @@ class GetPropCompiler : public PICStubCompiler
|
||||
return disable("code memory is out of range");
|
||||
}
|
||||
|
||||
buffer.link(notString, pic.slowPathStart.labelAtOffset(pic.u.get.typeCheckOffset));
|
||||
buffer.link(notString, pic.getSlowTypeCheck());
|
||||
buffer.link(done, pic.fastPathRejoin);
|
||||
|
||||
CodeLocationLabel start = buffer.finalize();
|
||||
@ -1052,7 +1034,7 @@ class GetPropCompiler : public PICStubCompiler
|
||||
|
||||
if (pic.hasTypeCheck()) {
|
||||
Repatcher repatcher(f.jit());
|
||||
repatcher.relink(pic.fastPathStart.jumpAtOffset(GETPROP_INLINE_TYPE_GUARD), start);
|
||||
repatcher.relink(pic.getPropLabels().getInlineTypeJump(pic.fastPathStart), start);
|
||||
}
|
||||
|
||||
disable("generated string length stub");
|
||||
@ -1064,11 +1046,11 @@ class GetPropCompiler : public PICStubCompiler
|
||||
{
|
||||
spew("patch", "inline");
|
||||
Repatcher repatcher(f.jit());
|
||||
GetPropLabels &labels = pic.getPropLabels();
|
||||
|
||||
int32 offset;
|
||||
if (!holder->hasSlotsArray()) {
|
||||
JSC::CodeLocationInstruction istr;
|
||||
istr = pic.fastPathRejoin.instructionAtOffset(dslotsLoad());
|
||||
CodeLocationInstruction istr = labels.getDslotsLoad(pic.fastPathRejoin);
|
||||
repatcher.repatchLoadPtrToLEA(istr);
|
||||
|
||||
//
|
||||
@ -1086,15 +1068,8 @@ class GetPropCompiler : public PICStubCompiler
|
||||
offset = shape->slot * sizeof(Value);
|
||||
}
|
||||
|
||||
uint32 shapeOffs = pic.shapeGuard + inlineShapeOffset();
|
||||
repatcher.repatch(pic.fastPathStart.dataLabel32AtOffset(shapeOffs), obj->shape());
|
||||
GetPropLabels &labels = pic.getPropLabels();
|
||||
#if defined JS_NUNBOX32
|
||||
repatcher.repatch(labels.getTypeLoad(pic.fastPathRejoin), offset + 4);
|
||||
repatcher.repatch(labels.getDataLoad(pic.fastPathRejoin), offset);
|
||||
#elif defined JS_PUNBOX64
|
||||
repatcher.repatch(labels.getValueLoad(pic.fastPathRejoin), offset);
|
||||
#endif
|
||||
repatcher.repatch(labels.getInlineShapeData(pic.getFastShapeGuard()), obj->shape());
|
||||
repatcher.patchAddressOffsetForValueLoad(labels.getValueLoad(pic.fastPathRejoin), offset);
|
||||
|
||||
pic.inlinePathPatched = true;
|
||||
|
||||
@ -1108,13 +1083,14 @@ class GetPropCompiler : public PICStubCompiler
|
||||
Assembler masm;
|
||||
|
||||
Label start;
|
||||
Jump shapeGuard;
|
||||
Jump shapeGuardJump;
|
||||
DataLabel32 shapeGuardData;
|
||||
Jump argsLenGuard;
|
||||
|
||||
bool setStubShapeOffset = true;
|
||||
if (obj->isDenseArray()) {
|
||||
start = masm.label();
|
||||
shapeGuard = masm.testObjClass(Assembler::NotEqual, pic.objReg, obj->getClass());
|
||||
shapeGuardJump = masm.testObjClass(Assembler::NotEqual, pic.objReg, obj->getClass());
|
||||
|
||||
/*
|
||||
* No need to assert validity of GETPROP_STUB_SHAPE_JUMP in this case:
|
||||
@ -1130,13 +1106,12 @@ class GetPropCompiler : public PICStubCompiler
|
||||
}
|
||||
|
||||
start = masm.label();
|
||||
shapeGuard = masm.branch32_force32(Assembler::NotEqual, pic.shapeReg,
|
||||
Imm32(obj->shape()));
|
||||
shapeGuardJump = masm.branch32WithPatch(Assembler::NotEqual, pic.shapeReg,
|
||||
Imm32(obj->shape()), shapeGuardData);
|
||||
}
|
||||
|
||||
Label stubShapeJumpLabel = masm.label();
|
||||
|
||||
if (!shapeMismatches.append(shapeGuard))
|
||||
if (!shapeMismatches.append(shapeGuardJump))
|
||||
return error();
|
||||
|
||||
RegisterID holderReg = pic.objReg;
|
||||
@ -1204,12 +1179,12 @@ class GetPropCompiler : public PICStubCompiler
|
||||
// the offsets are different.
|
||||
int shapeGuardJumpOffset;
|
||||
if (pic.stubsGenerated)
|
||||
shapeGuardJumpOffset = pic.getPropLabels().getStubShapeJump();
|
||||
shapeGuardJumpOffset = pic.getPropLabels().getStubShapeJumpOffset();
|
||||
else
|
||||
shapeGuardJumpOffset = pic.shapeGuard + inlineShapeJump();
|
||||
shapeGuardJumpOffset = pic.shapeGuard + pic.getPropLabels().getInlineShapeJumpOffset();
|
||||
repatcher.relink(label.jumpAtOffset(shapeGuardJumpOffset), cs);
|
||||
if (lastStubSecondShapeGuard)
|
||||
repatcher.relink(label.jumpAtOffset(lastStubSecondShapeGuard), cs);
|
||||
if (int secondGuardOffset = getLastStubSecondShapeGuard())
|
||||
repatcher.relink(label.jumpAtOffset(secondGuardOffset), cs);
|
||||
}
|
||||
|
||||
LookupStatus update()
|
||||
@ -1227,7 +1202,9 @@ class GetPropCompiler : public PICStubCompiler
|
||||
return generateStub(getprop.holder, getprop.shape);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined JS_POLYIC_NAME
|
||||
class ScopeNameCompiler : public PICStubCompiler
|
||||
{
|
||||
JSObject *scopeChain;
|
||||
@ -1543,7 +1520,9 @@ class ScopeNameCompiler : public PICStubCompiler
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if defined JS_POLYIC_BIND
|
||||
class BindNameCompiler : public PICStubCompiler
|
||||
{
|
||||
JSObject *scopeChain;
|
||||
@ -1668,7 +1647,9 @@ class BindNameCompiler : public PICStubCompiler
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined JS_POLYIC_GETPROP
|
||||
static void JS_FASTCALL
|
||||
DisabledLengthIC(VMFrame &f, ic::PICInfo *pic)
|
||||
{
|
||||
@ -1750,7 +1731,9 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic)
|
||||
THROW();
|
||||
f.regs.sp[-1] = v;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined JS_POLYIC_SETPROP
|
||||
template <JSBool strict>
|
||||
static void JS_FASTCALL
|
||||
DisabledSetPropIC(VMFrame &f, ic::PICInfo *pic)
|
||||
@ -1797,7 +1780,9 @@ ic::SetProp(VMFrame &f, ic::PICInfo *pic)
|
||||
Value rval = f.regs.sp[-1];
|
||||
stub(f, pic);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined JS_POLYIC_GETPROP
|
||||
static void JS_FASTCALL
|
||||
DisabledCallPropIC(VMFrame &f, ic::PICInfo *pic)
|
||||
{
|
||||
@ -1914,7 +1899,9 @@ ic::CallProp(VMFrame &f, ic::PICInfo *pic)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined JS_POLYIC_NAME
|
||||
static void JS_FASTCALL
|
||||
DisabledNameIC(VMFrame &f, ic::PICInfo *pic)
|
||||
{
|
||||
@ -1963,7 +1950,9 @@ ic::Name(VMFrame &f, ic::PICInfo *pic)
|
||||
THROW();
|
||||
f.regs.sp[0] = rval;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined JS_POLYIC_BIND
|
||||
static void JS_FASTCALL
|
||||
DisabledBindNameIC(VMFrame &f, ic::PICInfo *pic)
|
||||
{
|
||||
@ -1994,6 +1983,7 @@ ic::BindName(VMFrame &f, ic::PICInfo *pic)
|
||||
|
||||
f.regs.sp[0].setObject(*obj);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
BaseIC::isCallOp()
|
||||
@ -2032,6 +2022,7 @@ BaseIC::shouldUpdate(JSContext *cx)
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined JS_POLYIC_ELEM
|
||||
static void JS_FASTCALL
|
||||
DisabledGetElem(VMFrame &f, ic::GetElementIC *ic)
|
||||
{
|
||||
@ -2739,6 +2730,7 @@ ic::SetElement(VMFrame &f, ic::SetElementIC *ic)
|
||||
|
||||
template void JS_FASTCALL ic::SetElement<true>(VMFrame &f, SetElementIC *ic);
|
||||
template void JS_FASTCALL ic::SetElement<false>(VMFrame &f, SetElementIC *ic);
|
||||
#endif /* JS_POLYIC_ELEM */
|
||||
|
||||
void
|
||||
JITScript::purgePICs()
|
||||
@ -2751,21 +2743,29 @@ JITScript::purgePICs()
|
||||
for (uint32 i = 0; i < nPICs; i++) {
|
||||
ic::PICInfo &pic = pics[i];
|
||||
switch (pic.kind) {
|
||||
#ifdef JS_POLYIC_SETPROP
|
||||
case ic::PICInfo::SET:
|
||||
case ic::PICInfo::SETMETHOD:
|
||||
SetPropCompiler::reset(repatcher, pic);
|
||||
break;
|
||||
#endif
|
||||
#ifdef JS_POLYIC_NAME
|
||||
case ic::PICInfo::NAME:
|
||||
case ic::PICInfo::XNAME:
|
||||
ScopeNameCompiler::reset(repatcher, pic);
|
||||
break;
|
||||
#endif
|
||||
#ifdef JS_POLYIC_BIND
|
||||
case ic::PICInfo::BIND:
|
||||
BindNameCompiler::reset(repatcher, pic);
|
||||
break;
|
||||
#endif
|
||||
#ifdef JS_POLYIC_GETPROP
|
||||
case ic::PICInfo::CALL: /* fall-through */
|
||||
case ic::PICInfo::GET:
|
||||
GetPropCompiler::reset(repatcher, pic);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
JS_NOT_REACHED("Unhandled PIC kind");
|
||||
break;
|
||||
@ -2773,10 +2773,12 @@ JITScript::purgePICs()
|
||||
pic.reset();
|
||||
}
|
||||
|
||||
#if defined JS_POLYIC_ELEM
|
||||
for (uint32 i = 0; i < nGetElems; i++)
|
||||
getElems[i].purge(repatcher);
|
||||
for (uint32 i = 0; i < nSetElems; i++)
|
||||
setElems[i].purge(repatcher);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -78,15 +78,6 @@ static const int32 SETPROP_INLINE_STORE_VALUE = 0; //asserted
|
||||
static const int32 SETPROP_INLINE_SHAPE_JUMP = 6; //asserted
|
||||
#endif
|
||||
|
||||
/* GetPropCompiler */
|
||||
#if defined JS_CPU_X86
|
||||
static const int32 GETPROP_INLINE_TYPE_GUARD = 12; //asserted
|
||||
static const int32 GETPROP_INLINE_SHAPE_JUMP = 12; //asserted
|
||||
#elif defined JS_CPU_X64
|
||||
static const int32 GETPROP_INLINE_TYPE_GUARD = 19; //asserted
|
||||
static const int32 GETPROP_INLINE_SHAPE_JUMP = 6; //asserted
|
||||
#endif
|
||||
|
||||
/* ScopeNameCompiler */
|
||||
#if defined JS_CPU_X86
|
||||
static const int32 SCOPENAME_JUMP_OFFSET = 5; //asserted
|
||||
@ -450,6 +441,15 @@ struct PICInfo : public BasePolyIC {
|
||||
return CodeLocationLabel(lastStubStart.start());
|
||||
}
|
||||
|
||||
CodeLocationLabel getFastShapeGuard() {
|
||||
return fastPathStart.labelAtOffset(shapeGuard);
|
||||
}
|
||||
|
||||
CodeLocationLabel getSlowTypeCheck() {
|
||||
JS_ASSERT(isGet());
|
||||
return slowPathStart.labelAtOffset(u.get.typeCheckOffset);
|
||||
}
|
||||
|
||||
// Return a JITCode block corresponding to the code memory to attach a
|
||||
// new stub to.
|
||||
JITCode lastCodeBlock(JITScript *jit) {
|
||||
|
Loading…
Reference in New Issue
Block a user