зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1338828 part 1 - Add CacheIR SetProp/SetElem stubs for proxies. r=h4writer
This commit is contained in:
Родитель
f9bc8c7133
Коммит
71aecda25d
|
@ -1505,6 +1505,79 @@ BaselineCacheIRCompiler::emitCallSetArrayLength()
|
|||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*ProxySetPropertyFn)(JSContext*, HandleObject, HandleId, HandleValue, bool);
|
||||
static const VMFunction ProxySetPropertyInfo =
|
||||
FunctionInfo<ProxySetPropertyFn>(ProxySetProperty, "ProxySetProperty");
|
||||
|
||||
bool
|
||||
BaselineCacheIRCompiler::emitCallProxySet()
|
||||
{
|
||||
Register obj = allocator.useRegister(masm, reader.objOperandId());
|
||||
ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
|
||||
Address idAddr(stubAddress(reader.stubOffset()));
|
||||
bool strict = reader.readBool();
|
||||
|
||||
AutoScratchRegister scratch(allocator, masm);
|
||||
|
||||
allocator.discardStack(masm);
|
||||
|
||||
AutoStubFrame stubFrame(*this);
|
||||
stubFrame.enter(masm, scratch);
|
||||
|
||||
// Load the jsid in the scratch register.
|
||||
masm.loadPtr(idAddr, scratch);
|
||||
|
||||
masm.Push(Imm32(strict));
|
||||
masm.Push(val);
|
||||
masm.Push(scratch);
|
||||
masm.Push(obj);
|
||||
|
||||
if (!callVM(masm, ProxySetPropertyInfo))
|
||||
return false;
|
||||
|
||||
stubFrame.leave(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*ProxySetPropertyByValueFn)(JSContext*, HandleObject, HandleValue, HandleValue, bool);
|
||||
static const VMFunction ProxySetPropertyByValueInfo =
|
||||
FunctionInfo<ProxySetPropertyByValueFn>(ProxySetPropertyByValue, "ProxySetPropertyByValue");
|
||||
|
||||
bool
|
||||
BaselineCacheIRCompiler::emitCallProxySetByValue()
|
||||
{
|
||||
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(val);
|
||||
masm.Push(idVal);
|
||||
masm.Push(obj);
|
||||
|
||||
if (!callVM(masm, ProxySetPropertyByValueInfo))
|
||||
return false;
|
||||
|
||||
stubFrame.leave(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCacheIRCompiler::emitTypeMonitorResult()
|
||||
{
|
||||
|
|
|
@ -1447,7 +1447,6 @@ SetPropIRGenerator::maybeEmitIdGuard(jsid id)
|
|||
emitIdGuard(setElemKeyValueId(), id);
|
||||
}
|
||||
|
||||
|
||||
GetNameIRGenerator::GetNameIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc,
|
||||
HandleObject env, HandlePropertyName name)
|
||||
: IRGenerator(cx, script, pc, CacheKind::GetName),
|
||||
|
@ -1904,9 +1903,14 @@ SetPropIRGenerator::tryAttachStub()
|
|||
return true;
|
||||
if (tryAttachSetArrayLength(obj, objId, id, rhsValId))
|
||||
return true;
|
||||
if (tryAttachProxy(obj, objId, id, rhsValId))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tryAttachProxyElement(obj, objId, rhsValId))
|
||||
return true;
|
||||
|
||||
uint32_t index;
|
||||
Int32OperandId indexId;
|
||||
if (maybeGuardInt32Index(idVal_, setElemKeyValueId(), &index, &indexId)) {
|
||||
|
@ -2506,6 +2510,69 @@ SetPropIRGenerator::tryAttachSetUnboxedArrayElementHole(HandleObject obj, ObjOpe
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SetPropIRGenerator::tryAttachGenericProxy(HandleObject obj, ObjOperandId objId, HandleId id,
|
||||
ValOperandId rhsId)
|
||||
{
|
||||
MOZ_ASSERT(obj->is<ProxyObject>());
|
||||
|
||||
writer.guardIsProxy(objId);
|
||||
|
||||
// Ensure that the incoming object is not a DOM proxy, so that we can get to
|
||||
// the specialized stubs
|
||||
writer.guardNotDOMProxy(objId);
|
||||
|
||||
if (cacheKind_ == CacheKind::SetProp) {
|
||||
writer.callProxySet(objId, id, rhsId, IsStrictSetPC(pc_));
|
||||
} else {
|
||||
// We could call maybeEmitIdGuard here and then emit CallProxySet, but
|
||||
// for SetElem we prefer to attach a stub that can handle any Value
|
||||
// so we don't attach a new stub for every id.
|
||||
MOZ_ASSERT(cacheKind_ == CacheKind::SetElem);
|
||||
writer.callProxySetByValue(objId, setElemKeyValueId(), rhsId, IsStrictSetPC(pc_));
|
||||
}
|
||||
|
||||
writer.returnFromIC();
|
||||
|
||||
trackAttached("GenericProxy");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SetPropIRGenerator::tryAttachProxy(HandleObject obj, ObjOperandId objId, HandleId id,
|
||||
ValOperandId rhsId)
|
||||
{
|
||||
switch (GetProxyStubType(cx_, obj, id)) {
|
||||
case ProxyStubType::None:
|
||||
return false;
|
||||
case ProxyStubType::DOMExpando:
|
||||
case ProxyStubType::DOMShadowed:
|
||||
case ProxyStubType::DOMUnshadowed:
|
||||
case ProxyStubType::Generic:
|
||||
return tryAttachGenericProxy(obj, objId, id, rhsId);
|
||||
}
|
||||
|
||||
MOZ_CRASH("Unexpected ProxyStubType");
|
||||
}
|
||||
|
||||
bool
|
||||
SetPropIRGenerator::tryAttachProxyElement(HandleObject obj, ObjOperandId objId, ValOperandId rhsId)
|
||||
{
|
||||
if (!obj->is<ProxyObject>())
|
||||
return false;
|
||||
|
||||
writer.guardIsProxy(objId);
|
||||
|
||||
// Like GetPropIRGenerator::tryAttachProxyElement, don't check for DOM
|
||||
// proxies here as we don't have specialized DOM stubs for this.
|
||||
MOZ_ASSERT(cacheKind_ == CacheKind::SetElem);
|
||||
writer.callProxySetByValue(objId, setElemKeyValueId(), rhsId, IsStrictSetPC(pc_));
|
||||
writer.returnFromIC();
|
||||
|
||||
trackAttached("ProxyElement");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SetPropIRGenerator::tryAttachAddSlotStub(HandleObjectGroup oldGroup, HandleShape oldShape)
|
||||
{
|
||||
|
|
|
@ -195,6 +195,8 @@ extern const char* CacheKindNames[];
|
|||
_(CallNativeSetter) \
|
||||
_(CallScriptedSetter) \
|
||||
_(CallSetArrayLength) \
|
||||
_(CallProxySet) \
|
||||
_(CallProxySetByValue) \
|
||||
\
|
||||
/* The *Result ops load a value into the cache's result register. */ \
|
||||
_(LoadFixedSlotResult) \
|
||||
|
@ -707,6 +709,18 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
|
|||
buffer_.writeByte(uint32_t(strict));
|
||||
writeOperandId(rhs);
|
||||
}
|
||||
void callProxySet(ObjOperandId obj, jsid id, ValOperandId rhs, bool strict) {
|
||||
writeOpWithOperandId(CacheOp::CallProxySet, obj);
|
||||
writeOperandId(rhs);
|
||||
addStubField(uintptr_t(JSID_BITS(id)), StubField::Type::Id);
|
||||
buffer_.writeByte(uint32_t(strict));
|
||||
}
|
||||
void callProxySetByValue(ObjOperandId obj, ValOperandId id, ValOperandId rhs, bool strict) {
|
||||
writeOpWithOperandId(CacheOp::CallProxySetByValue, obj);
|
||||
writeOperandId(id);
|
||||
writeOperandId(rhs);
|
||||
buffer_.writeByte(uint32_t(strict));
|
||||
}
|
||||
|
||||
void loadBooleanResult(bool val) {
|
||||
writeOp(CacheOp::LoadBooleanResult);
|
||||
|
@ -1077,6 +1091,11 @@ class MOZ_RAII SetPropIRGenerator : public IRGenerator
|
|||
bool tryAttachSetUnboxedArrayElementHole(HandleObject obj, ObjOperandId objId, uint32_t index,
|
||||
Int32OperandId indexId, ValOperandId rhsId);
|
||||
|
||||
bool tryAttachGenericProxy(HandleObject obj, ObjOperandId objId, HandleId id,
|
||||
ValOperandId rhsId);
|
||||
bool tryAttachProxy(HandleObject obj, ObjOperandId objId, HandleId id, ValOperandId rhsId);
|
||||
bool tryAttachProxyElement(HandleObject obj, ObjOperandId objId, ValOperandId rhsId);
|
||||
|
||||
void trackAttached(const char* name);
|
||||
|
||||
public:
|
||||
|
|
|
@ -933,6 +933,18 @@ IonCacheIRCompiler::emitCallSetArrayLength()
|
|||
MOZ_CRASH("Baseline-specific op");
|
||||
}
|
||||
|
||||
bool
|
||||
IonCacheIRCompiler::emitCallProxySet()
|
||||
{
|
||||
MOZ_CRASH("Baseline-specific op");
|
||||
}
|
||||
|
||||
bool
|
||||
IonCacheIRCompiler::emitCallProxySetByValue()
|
||||
{
|
||||
MOZ_CRASH("Baseline-specific op");
|
||||
}
|
||||
|
||||
bool
|
||||
IonCacheIRCompiler::emitLoadTypedObjectResult()
|
||||
{
|
||||
|
|
|
@ -1440,15 +1440,6 @@ EmitObjectOpResultCheck(MacroAssembler& masm, Label* failure, bool strict,
|
|||
masm.bind(&noStrictError);
|
||||
}
|
||||
|
||||
static bool
|
||||
ProxySetProperty(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v, bool strict)
|
||||
{
|
||||
RootedValue receiver(cx, ObjectValue(*proxy));
|
||||
ObjectOpResult result;
|
||||
return Proxy::set(cx, proxy, id, v, receiver, result)
|
||||
&& result.checkStrictErrorOrWarning(cx, proxy, id, strict);
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitCallProxySet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& attacher,
|
||||
HandleId propId, LiveRegisterSet liveRegs, Register object,
|
||||
|
|
|
@ -354,6 +354,31 @@ Proxy::set(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v, Handle
|
|||
return handler->set(cx, proxy, id, v, receiver, result);
|
||||
}
|
||||
|
||||
bool
|
||||
js::ProxySetProperty(JSContext* cx, HandleObject proxy, HandleId id, HandleValue val, bool strict)
|
||||
{
|
||||
ObjectOpResult result;
|
||||
RootedValue receiver(cx, ObjectValue(*proxy));
|
||||
if (!Proxy::set(cx, proxy, id, val, receiver, result))
|
||||
return false;
|
||||
return result.checkStrictErrorOrWarning(cx, proxy, id, strict);
|
||||
}
|
||||
|
||||
bool
|
||||
js::ProxySetPropertyByValue(JSContext* cx, HandleObject proxy, HandleValue idVal, HandleValue val,
|
||||
bool strict)
|
||||
{
|
||||
RootedId id(cx);
|
||||
if (!ValueToId<CanGC>(cx, idVal, &id))
|
||||
return false;
|
||||
|
||||
ObjectOpResult result;
|
||||
RootedValue receiver(cx, ObjectValue(*proxy));
|
||||
if (!Proxy::set(cx, proxy, id, val, receiver, result))
|
||||
return false;
|
||||
return result.checkStrictErrorOrWarning(cx, proxy, id, strict);
|
||||
}
|
||||
|
||||
bool
|
||||
Proxy::getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy, AutoIdVector& props)
|
||||
{
|
||||
|
|
|
@ -79,7 +79,7 @@ proxy_Call(JSContext* cx, unsigned argc, Value* vp);
|
|||
bool
|
||||
proxy_Construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
// These two functions are used by JIT code
|
||||
// These functions are used by JIT code
|
||||
|
||||
bool
|
||||
ProxyGetProperty(JSContext* cx, HandleObject proxy, HandleId id, MutableHandleValue vp);
|
||||
|
@ -88,6 +88,13 @@ bool
|
|||
ProxyGetPropertyByValue(JSContext* cx, HandleObject proxy, HandleValue idVal,
|
||||
MutableHandleValue vp);
|
||||
|
||||
bool
|
||||
ProxySetProperty(JSContext* cx, HandleObject proxy, HandleId id, HandleValue val, bool strict);
|
||||
|
||||
bool
|
||||
ProxySetPropertyByValue(JSContext* cx, HandleObject proxy, HandleValue idVal, HandleValue val,
|
||||
bool strict);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* proxy_Proxy_h */
|
||||
|
|
Загрузка…
Ссылка в новой задаче