зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1357468 - More Object.hasOwnProperty optimizations for Speedometer. r=jandem
- IC support dense elements, like [0].hasOwnProperty("0") - IC support unboxed objects - IC support proxies, i.e. NodeList or other DOM proxies mostly
This commit is contained in:
Родитель
58b4255414
Коммит
9d47f2ea8d
|
@ -672,6 +672,32 @@ BaselineCacheIRCompiler::emitCallProxyGetByValueResult()
|
|||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*ProxyHasOwnFn)(JSContext*, HandleObject, HandleValue, MutableHandleValue);
|
||||
static const VMFunction ProxyHasOwnInfo = FunctionInfo<ProxyHasOwnFn>(ProxyHasOwn, "ProxyHasOwn");
|
||||
|
||||
bool
|
||||
BaselineCacheIRCompiler::emitCallProxyHasOwnResult()
|
||||
{
|
||||
Register obj = allocator.useRegister(masm, reader.objOperandId());
|
||||
ValueOperand idVal = allocator.useValueRegister(masm, reader.valOperandId());
|
||||
|
||||
AutoScratchRegister scratch(allocator, masm);
|
||||
|
||||
allocator.discardStack(masm);
|
||||
|
||||
AutoStubFrame stubFrame(*this);
|
||||
stubFrame.enter(masm, scratch);
|
||||
|
||||
masm.Push(idVal);
|
||||
masm.Push(obj);
|
||||
|
||||
if (!callVM(masm, ProxyHasOwnInfo))
|
||||
return false;
|
||||
|
||||
stubFrame.leave(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCacheIRCompiler::emitLoadUnboxedPropertyResult()
|
||||
{
|
||||
|
|
|
@ -2159,7 +2159,10 @@ HasOwnIRGenerator::tryAttachNativeHasOwn(HandleId key, ValOperandId keyId,
|
|||
if (!LookupOwnPropertyPure(cx_, obj, key, &prop))
|
||||
return false;
|
||||
|
||||
if (!prop.isNativeProperty())
|
||||
if (!prop.isFound())
|
||||
return false;
|
||||
|
||||
if (!obj->isNative() && !obj->is<UnboxedPlainObject>())
|
||||
return false;
|
||||
|
||||
if (mode_ == ICState::Mode::Megamorphic) {
|
||||
|
@ -2169,9 +2172,9 @@ HasOwnIRGenerator::tryAttachNativeHasOwn(HandleId key, ValOperandId keyId,
|
|||
return true;
|
||||
}
|
||||
|
||||
Maybe<ObjOperandId> holderId;
|
||||
Maybe<ObjOperandId> expandoId;
|
||||
emitIdGuard(keyId, key);
|
||||
EmitReadSlotGuard(writer, obj, obj, prop.shape(), objId, &holderId);
|
||||
TestMatchingReceiver(writer, obj, nullptr, objId, &expandoId);
|
||||
writer.loadBooleanResult(true);
|
||||
writer.returnFromIC();
|
||||
|
||||
|
@ -2203,6 +2206,37 @@ HasOwnIRGenerator::tryAttachNativeHasOwnDoesNotExist(HandleId key, ValOperandId
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
HasOwnIRGenerator::tryAttachProxyElement(ValOperandId keyId, HandleObject obj, ObjOperandId objId)
|
||||
{
|
||||
if (!obj->is<ProxyObject>())
|
||||
return false;
|
||||
|
||||
writer.guardIsProxy(objId);
|
||||
writer.callProxyHasOwnResult(objId, keyId);
|
||||
writer.returnFromIC();
|
||||
|
||||
trackAttached("ProxyHasOwn");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
HasOwnIRGenerator::tryAttachDenseHasOwn(uint32_t index, Int32OperandId indexId,
|
||||
HandleObject obj, ObjOperandId objId)
|
||||
{
|
||||
if (!obj->isNative())
|
||||
return false;
|
||||
if (!obj->as<NativeObject>().containsDenseElement(index))
|
||||
return false;
|
||||
|
||||
writer.guardShape(objId, obj->as<NativeObject>().lastProperty());
|
||||
writer.loadDenseElementExistsResult(objId, indexId);
|
||||
writer.returnFromIC();
|
||||
|
||||
trackAttached("DenseHasOwn");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
HasOwnIRGenerator::tryAttachStub()
|
||||
{
|
||||
|
@ -2221,6 +2255,9 @@ HasOwnIRGenerator::tryAttachStub()
|
|||
|
||||
ObjOperandId objId = writer.guardIsObject(valId);
|
||||
|
||||
if (tryAttachProxyElement(keyId, obj, objId))
|
||||
return true;
|
||||
|
||||
RootedId id(cx_);
|
||||
bool nameOrSymbol;
|
||||
if (!ValueToNameOrSymbolId(cx_, key_, &id, &nameOrSymbol)) {
|
||||
|
@ -2238,6 +2275,16 @@ HasOwnIRGenerator::tryAttachStub()
|
|||
return false;
|
||||
}
|
||||
|
||||
uint32_t index;
|
||||
Int32OperandId indexId;
|
||||
if (maybeGuardInt32Index(key_, keyId, &index, &indexId)) {
|
||||
if (tryAttachDenseHasOwn(index, indexId, obj, objId))
|
||||
return true;
|
||||
|
||||
trackNotAttached();
|
||||
return false;
|
||||
}
|
||||
|
||||
trackNotAttached();
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -242,6 +242,7 @@ extern const char* CacheKindNames[];
|
|||
_(CallNativeGetterResult) \
|
||||
_(CallProxyGetResult) \
|
||||
_(CallProxyGetByValueResult) \
|
||||
_(CallProxyHasOwnResult) \
|
||||
_(LoadUndefinedResult) \
|
||||
_(LoadBooleanResult) \
|
||||
\
|
||||
|
@ -885,6 +886,10 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
|
|||
writeOpWithOperandId(CacheOp::CallProxyGetByValueResult, obj);
|
||||
writeOperandId(idVal);
|
||||
}
|
||||
void callProxyHasOwnResult(ObjOperandId obj, ValOperandId idVal) {
|
||||
writeOpWithOperandId(CacheOp::CallProxyHasOwnResult, obj);
|
||||
writeOperandId(idVal);
|
||||
}
|
||||
void loadEnvironmentFixedSlotResult(ObjOperandId obj, size_t offset) {
|
||||
writeOpWithOperandId(CacheOp::LoadEnvironmentFixedSlotResult, obj);
|
||||
addStubField(offset, StubField::Type::RawWord);
|
||||
|
@ -1286,6 +1291,9 @@ class MOZ_RAII HasOwnIRGenerator : public IRGenerator
|
|||
HandleValue key_;
|
||||
HandleValue val_;
|
||||
|
||||
bool tryAttachProxyElement(ValOperandId keyId, HandleObject obj, ObjOperandId objId);
|
||||
bool tryAttachDenseHasOwn(uint32_t index, Int32OperandId indexId,
|
||||
HandleObject obj, ObjOperandId objId);
|
||||
bool tryAttachNativeHasOwn(HandleId key, ValOperandId keyId,
|
||||
HandleObject obj, ObjOperandId objId);
|
||||
bool tryAttachNativeHasOwnDoesNotExist(HandleId key, ValOperandId keyId,
|
||||
|
|
|
@ -1040,6 +1040,33 @@ IonCacheIRCompiler::emitCallProxyGetByValueResult()
|
|||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*ProxyHasOwnFn)(JSContext*, HandleObject, HandleValue, MutableHandleValue);
|
||||
static const VMFunction ProxyHasOwnInfo = FunctionInfo<ProxyHasOwnFn>(ProxyHasOwn, "ProxyHasOwn");
|
||||
|
||||
bool
|
||||
IonCacheIRCompiler::emitCallProxyHasOwnResult()
|
||||
{
|
||||
AutoSaveLiveRegisters save(*this);
|
||||
AutoOutputRegister output(*this);
|
||||
|
||||
Register obj = allocator.useRegister(masm, reader.objOperandId());
|
||||
ValueOperand idVal = allocator.useValueRegister(masm, reader.valOperandId());
|
||||
|
||||
allocator.discardStack(masm);
|
||||
|
||||
prepareVMCall(masm);
|
||||
|
||||
masm.Push(idVal);
|
||||
masm.Push(obj);
|
||||
|
||||
if (!callVM(masm, ProxyHasOwnInfo))
|
||||
return false;
|
||||
|
||||
masm.storeCallResultValue(output);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
IonCacheIRCompiler::emitLoadUnboxedPropertyResult()
|
||||
{
|
||||
|
|
|
@ -1740,15 +1740,21 @@ HasOwnNativeDataProperty(JSContext* cx, JSObject* obj, Value* vp)
|
|||
{
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
|
||||
if (MOZ_UNLIKELY(!obj->isNative()))
|
||||
return false;
|
||||
|
||||
// vp[0] contains the id, result will be stored in vp[1].
|
||||
Value idVal = vp[0];
|
||||
jsid id;
|
||||
if (!ValueToAtomOrSymbol(cx, idVal, &id))
|
||||
return false;
|
||||
|
||||
if (!obj->isNative()) {
|
||||
if (obj->is<UnboxedPlainObject>()) {
|
||||
bool res = obj->as<UnboxedPlainObject>().containsUnboxedOrExpandoProperty(cx, id);
|
||||
vp[1].setBoolean(res);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NativeObject* nobj = &obj->as<NativeObject>();
|
||||
if (nobj->lastProperty()->search(cx, id)) {
|
||||
vp[1].setBoolean(true);
|
||||
|
|
|
@ -284,6 +284,21 @@ Proxy::hasOwn(JSContext* cx, HandleObject proxy, HandleId id, bool* bp)
|
|||
return handler->hasOwn(cx, proxy, id, bp);
|
||||
}
|
||||
|
||||
bool
|
||||
js::ProxyHasOwn(JSContext* cx, HandleObject proxy, HandleValue idVal, MutableHandleValue result)
|
||||
{
|
||||
RootedId id(cx);
|
||||
if (!ValueToId<CanGC>(cx, idVal, &id))
|
||||
return false;
|
||||
|
||||
bool hasOwn;
|
||||
if (!Proxy::hasOwn(cx, proxy, id, &hasOwn))
|
||||
return false;
|
||||
|
||||
result.setBoolean(hasOwn);
|
||||
return true;
|
||||
}
|
||||
|
||||
static Value
|
||||
ValueToWindowProxyIfWindow(const Value& v)
|
||||
{
|
||||
|
|
|
@ -80,6 +80,9 @@ proxy_Construct(JSContext* cx, unsigned argc, Value* vp);
|
|||
|
||||
// These functions are used by JIT code
|
||||
|
||||
bool
|
||||
ProxyHasOwn(JSContext* cx, HandleObject proxy, HandleValue idVal, MutableHandleValue result);
|
||||
|
||||
bool
|
||||
ProxyGetProperty(JSContext* cx, HandleObject proxy, HandleId id, MutableHandleValue vp);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче