Bug 1388388 - Add a megamorphic SetElement stub. r=evilpie

This commit is contained in:
Jan de Mooij 2017-08-10 11:12:51 +02:00
parent 9f891645fa
commit 0cbf2d7387
8 changed files with 100 additions and 11 deletions

View File

@ -2006,6 +2006,42 @@ BaselineCacheIRCompiler::emitCallProxySetByValue()
return true;
}
bool
BaselineCacheIRCompiler::emitMegamorphicSetElement()
{
Register obj = allocator.useRegister(masm, reader.objOperandId());
ValueOperand idVal = allocator.useValueRegister(masm, reader.valOperandId());
ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
bool strict = reader.readBool();
allocator.discardStack(masm);
// We need a scratch register but we don't have any registers available on
// x86, so temporarily store |obj| in the frame's scratch slot.
int scratchOffset = BaselineFrame::reverseOffsetOfScratchValue();
masm.storePtr(obj, Address(BaselineFrameReg, scratchOffset));
AutoStubFrame stubFrame(*this);
stubFrame.enter(masm, obj);
// Restore |obj|. Because we entered a stub frame we first have to load
// the original frame pointer.
masm.loadPtr(Address(BaselineFrameReg, 0), obj);
masm.loadPtr(Address(obj, scratchOffset), obj);
masm.Push(Imm32(strict));
masm.Push(TypedOrValueRegister(MIRType::Object, AnyRegister(obj)));
masm.Push(val);
masm.Push(idVal);
masm.Push(obj);
if (!callVM(masm, SetObjectElementInfo))
return false;
stubFrame.leave(masm);
return true;
}
bool
BaselineCacheIRCompiler::emitTypeMonitorResult()
{

View File

@ -2359,11 +2359,6 @@ BaselineCompiler::emit_JSOP_STRICTSETELEM()
return emit_JSOP_SETELEM();
}
typedef bool (*SetObjectElementFn)(JSContext*, HandleObject, HandleValue,
HandleValue, HandleValue, bool);
static const VMFunction SetObjectElementInfo =
FunctionInfo<SetObjectElementFn>(js::SetObjectElement, "SetObjectElement");
bool
BaselineCompiler::emit_JSOP_SETELEM_SUPER()
{

View File

@ -2646,6 +2646,10 @@ SetPropIRGenerator::tryAttachStub()
return false;
ObjOperandId objId = writer.guardIsObject(objValId);
if (IsPropertySetOp(JSOp(*pc_))) {
if (tryAttachMegamorphicSetElement(obj, objId, rhsValId))
return true;
}
if (nameOrSymbol) {
if (tryAttachNativeSetSlot(obj, objId, id, rhsValId))
return true;
@ -3573,6 +3577,26 @@ SetPropIRGenerator::tryAttachProxyElement(HandleObject obj, ObjOperandId objId,
return true;
}
bool
SetPropIRGenerator::tryAttachMegamorphicSetElement(HandleObject obj, ObjOperandId objId,
ValOperandId rhsId)
{
MOZ_ASSERT(IsPropertySetOp(JSOp(*pc_)));
if (mode_ != ICState::Mode::Megamorphic || cacheKind_ != CacheKind::SetElem)
return false;
// The generic proxy stubs are faster.
if (obj->is<ProxyObject>())
return false;
writer.megamorphicSetElement(objId, setElemKeyValueId(), rhsId, IsStrictSetPC(pc_));
writer.returnFromIC();
trackAttached("MegamorphicSetElement");
return true;
}
bool
SetPropIRGenerator::tryAttachWindowProxy(HandleObject obj, ObjOperandId objId, HandleId id,
ValOperandId rhsId)

View File

@ -203,6 +203,7 @@ extern const char* CacheKindNames[];
_(MegamorphicLoadSlotResult) \
_(MegamorphicLoadSlotByValueResult) \
_(MegamorphicStoreSlot) \
_(MegamorphicSetElement) \
_(MegamorphicHasOwnResult) \
\
/* See CacheIR.cpp 'DOM proxies' comment. */ \
@ -880,6 +881,12 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
writeOperandId(rhs);
buffer_.writeByte(needsTypeBarrier);
}
void megamorphicSetElement(ObjOperandId obj, ValOperandId id, ValOperandId rhs, bool strict) {
writeOpWithOperandId(CacheOp::MegamorphicSetElement, obj);
writeOperandId(id);
writeOperandId(rhs);
buffer_.writeByte(uint32_t(strict));
}
void megamorphicHasOwnResult(ObjOperandId obj, ValOperandId id) {
writeOpWithOperandId(CacheOp::MegamorphicHasOwnResult, obj);
writeOperandId(id);
@ -1424,6 +1431,7 @@ class MOZ_RAII SetPropIRGenerator : public IRGenerator
ValOperandId rhsId);
bool tryAttachProxy(HandleObject obj, ObjOperandId objId, HandleId id, ValOperandId rhsId);
bool tryAttachProxyElement(HandleObject obj, ObjOperandId objId, ValOperandId rhsId);
bool tryAttachMegamorphicSetElement(HandleObject obj, ObjOperandId objId, ValOperandId rhsId);
void trackAttached(const char* name);

View File

@ -10211,18 +10211,15 @@ CodeGenerator::visitCallGetElement(LCallGetElement* lir)
}
}
typedef bool (*SetObjectElementFn)(JSContext*, HandleObject, HandleValue, HandleValue,
bool strict);
static const VMFunction SetObjectElementInfo =
FunctionInfo<SetObjectElementFn>(SetObjectElement, "SetObjectElement");
void
CodeGenerator::visitCallSetElement(LCallSetElement* lir)
{
Register obj = ToRegister(lir->getOperand(0));
pushArg(Imm32(lir->mir()->strict()));
pushArg(TypedOrValueRegister(MIRType::Object, AnyRegister(obj)));
pushArg(ToValue(lir, LCallSetElement::Value));
pushArg(ToValue(lir, LCallSetElement::Index));
pushArg(ToRegister(lir->getOperand(0)));
pushArg(obj);
callVM(SetObjectElementInfo, lir);
}

View File

@ -2066,6 +2066,28 @@ IonCacheIRCompiler::emitCallProxySetByValue()
return callVM(masm, ProxySetPropertyByValueInfo);
}
bool
IonCacheIRCompiler::emitMegamorphicSetElement()
{
AutoSaveLiveRegisters save(*this);
Register obj = allocator.useRegister(masm, reader.objOperandId());
ConstantOrRegister idVal = allocator.useConstantOrRegister(masm, reader.valOperandId());
ConstantOrRegister val = allocator.useConstantOrRegister(masm, reader.valOperandId());
bool strict = reader.readBool();
allocator.discardStack(masm);
prepareVMCall(masm);
masm.Push(Imm32(strict));
masm.Push(TypedOrValueRegister(MIRType::Object, AnyRegister(obj)));
masm.Push(val);
masm.Push(idVal);
masm.Push(obj);
return callVM(masm, SetObjectElementInfo);
}
bool
IonCacheIRCompiler::emitLoadTypedObjectResult()
{

View File

@ -1820,5 +1820,10 @@ GetPrototypeOf(JSContext* cx, HandleObject target, MutableHandleValue rval)
return true;
}
typedef bool (*SetObjectElementFn)(JSContext*, HandleObject, HandleValue,
HandleValue, HandleValue, bool);
const VMFunction SetObjectElementInfo =
FunctionInfo<SetObjectElementFn>(js::SetObjectElement, "SetObjectElement");
} // namespace jit
} // namespace js

View File

@ -892,6 +892,8 @@ TypeOfObject(JSObject* obj, JSRuntime* rt);
bool
GetPrototypeOf(JSContext* cx, HandleObject target, MutableHandleValue rval);
extern const VMFunction SetObjectElementInfo;
} // namespace jit
} // namespace js