mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
JM: OOL fast path for setting array holes, bug 580355
This commit is contained in:
parent
211b338724
commit
e56731d546
@ -811,7 +811,8 @@ array_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||
if (!obj->isDenseArray())
|
||||
return js_SetProperty(cx, obj, id, vp);
|
||||
|
||||
if (!js_IdIsIndex(id, &i) || INDEX_TOO_SPARSE(obj, i)) {
|
||||
if (!js_IdIsIndex(id, &i) || js_PrototypeHasIndexedProperties(cx, obj) ||
|
||||
INDEX_TOO_SPARSE(obj, i)) {
|
||||
if (!obj->makeDenseArraySlow(cx))
|
||||
return JS_FALSE;
|
||||
return js_SetProperty(cx, obj, id, vp);
|
||||
|
@ -222,9 +222,7 @@ struct JSScope : public JSObjectMap
|
||||
#endif
|
||||
JSObject *object; /* object that owns this scope */
|
||||
uint32 freeslot; /* index of next free slot in object */
|
||||
protected:
|
||||
uint8 flags; /* flags, see below */
|
||||
public:
|
||||
int8 hashShift; /* multiplicative hash shift */
|
||||
|
||||
uint16 spare; /* reserved */
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "jsbool.h"
|
||||
#include "jslibmath.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsscope.h"
|
||||
#include "methodjit/MethodJIT.h"
|
||||
#include "methodjit/Compiler.h"
|
||||
#include "methodjit/StubCalls.h"
|
||||
@ -964,6 +965,14 @@ mjit::Compiler::jsop_setelem()
|
||||
} else {
|
||||
RegisterID idReg = maybeIdReg.reg();
|
||||
|
||||
/*
|
||||
* Register for use only in OOL hole path. TODO: would be nice
|
||||
* for the frame to do any associated spilling in the OOL path.
|
||||
*/
|
||||
RegisterID T1 = frame.allocReg();
|
||||
|
||||
Label syncTarget = stubcc.syncExitAndJump(Uses(3));
|
||||
|
||||
/* guard not a hole */
|
||||
BaseIndex slot(objReg, idReg, Assembler::JSVAL_SCALE);
|
||||
#if defined JS_NUNBOX32
|
||||
@ -972,7 +981,57 @@ mjit::Compiler::jsop_setelem()
|
||||
masm.loadTypeTag(slot, Registers::ValueReg);
|
||||
Jump notHole = masm.branchPtr(Assembler::Equal, Registers::ValueReg, ImmType(JSVAL_TYPE_MAGIC));
|
||||
#endif
|
||||
stubcc.linkExit(notHole, Uses(3));
|
||||
|
||||
/* Make an OOL path for setting array holes. */
|
||||
Label lblHole = stubcc.masm.label();
|
||||
stubcc.linkExitDirect(notHole, lblHole);
|
||||
|
||||
/* Need a new handle on the object, as objReg now holds the dslots. */
|
||||
RegisterID baseReg = frame.tempRegForData(obj, objReg, stubcc.masm);
|
||||
|
||||
/*
|
||||
* Check if the object has a prototype with indexed properties,
|
||||
* in which case it might have a setter for this element. For dense
|
||||
* arrays we only need to check Array.prototype and Object.prototype.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test for indexed properties in Array.prototype. flags is a one byte
|
||||
* quantity, but will be aligned on 4 bytes.
|
||||
*/
|
||||
stubcc.masm.loadPtr(Address(baseReg, offsetof(JSObject, proto)), T1);
|
||||
stubcc.masm.loadPtr(Address(T1, offsetof(JSObject, map)), T1);
|
||||
stubcc.masm.load32(Address(T1, offsetof(JSScope, flags)), T1);
|
||||
stubcc.masm.and32(Imm32(JSScope::INDEXED_PROPERTIES), T1);
|
||||
Jump extendedArray = stubcc.masm.branchTest32(Assembler::NonZero, T1, T1);
|
||||
extendedArray.linkTo(syncTarget, &stubcc.masm);
|
||||
|
||||
/* Test for indexed properties in Object.prototype. */
|
||||
stubcc.masm.loadPtr(Address(baseReg, offsetof(JSObject, proto)), T1);
|
||||
stubcc.masm.loadPtr(Address(T1, offsetof(JSObject, proto)), T1);
|
||||
stubcc.masm.loadPtr(Address(T1, offsetof(JSObject, map)), T1);
|
||||
stubcc.masm.load32(Address(T1, offsetof(JSScope, flags)), T1);
|
||||
stubcc.masm.and32(Imm32(JSScope::INDEXED_PROPERTIES), T1);
|
||||
Jump extendedObject = stubcc.masm.branchTest32(Assembler::NonZero, T1, T1);
|
||||
extendedObject.linkTo(syncTarget, &stubcc.masm);
|
||||
|
||||
/* Update the array length if needed. Don't worry about overflow. */
|
||||
Address arrayLength(baseReg, offsetof(JSObject, fslots[JSObject::JSSLOT_ARRAY_LENGTH]));
|
||||
stubcc.masm.loadPayload(arrayLength, T1);
|
||||
Jump underLength = stubcc.masm.branch32(Assembler::LessThan, idReg, T1);
|
||||
stubcc.masm.move(idReg, T1);
|
||||
stubcc.masm.add32(Imm32(1), T1);
|
||||
stubcc.masm.storePayload(T1, arrayLength);
|
||||
underLength.linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
|
||||
/* Restore the dslots register if we clobbered it with the object. */
|
||||
if (baseReg == objReg)
|
||||
stubcc.masm.loadPtr(Address(objReg, offsetof(JSObject, dslots)), objReg);
|
||||
|
||||
/* Rejoin OOL path with inline path to do the store itself. */
|
||||
Jump jmpHoleExit = stubcc.masm.jump();
|
||||
Label lblRejoin = masm.label();
|
||||
stubcc.crossJump(jmpHoleExit, lblRejoin);
|
||||
|
||||
stubcc.leave();
|
||||
stubcc.call(stubs::SetElem);
|
||||
@ -993,6 +1052,7 @@ mjit::Compiler::jsop_setelem()
|
||||
}
|
||||
|
||||
frame.freeReg(idReg);
|
||||
frame.freeReg(T1);
|
||||
}
|
||||
frame.freeReg(objReg);
|
||||
|
||||
|
@ -442,6 +442,23 @@ FrameState::tempRegInMaskForData(FrameEntry *fe, uint32 mask)
|
||||
return reg;
|
||||
}
|
||||
|
||||
inline JSC::MacroAssembler::RegisterID
|
||||
FrameState::tempRegForData(FrameEntry *fe, RegisterID reg, Assembler &masm) const
|
||||
{
|
||||
JS_ASSERT(!fe->data.isConstant());
|
||||
|
||||
if (fe->isCopy())
|
||||
fe = fe->copyOf();
|
||||
|
||||
if (fe->data.inRegister()) {
|
||||
JS_ASSERT(fe->data.reg() != reg);
|
||||
return fe->data.reg();
|
||||
} else {
|
||||
masm.loadPayload(addressOf(fe), reg);
|
||||
return reg;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool
|
||||
FrameState::shouldAvoidTypeRemat(FrameEntry *fe)
|
||||
{
|
||||
|
@ -320,6 +320,12 @@ class FrameState
|
||||
*/
|
||||
inline RegisterID tempRegInMaskForData(FrameEntry *fe, uint32 mask);
|
||||
|
||||
/*
|
||||
* Same as above, except loads into reg (using masm) if the entry does not
|
||||
* already have a register, and does not change the frame state in doing so.
|
||||
*/
|
||||
inline RegisterID tempRegForData(FrameEntry *fe, RegisterID reg, Assembler &masm) const;
|
||||
|
||||
/*
|
||||
* Forcibly loads the type tag for the specified FrameEntry
|
||||
* into a register already marked as owning the type.
|
||||
|
Loading…
Reference in New Issue
Block a user