Bug 1357759 - Support proxies ICs for JSOP_IN
MozReview-Commit-ID: nyoeWmmOaZ
--- a/js/src/jit/BaselineCacheIRCompiler.cpp
+++ b/js/src/jit/BaselineCacheIRCompiler.cpp
@@ -752,37 +752,46 @@ BaselineCacheIRCompiler::emitCallProxyGe
if (!callVM(masm, ProxyGetPropertyByValueInfo))
return false;
stubFrame.leave(masm);
return true;
}
+typedef bool (*ProxyHasFn)(JSContext*, HandleObject, HandleValue, MutableHandleValue);
+static const VMFunction ProxyHasInfo = FunctionInfo<ProxyHasFn>(ProxyHas, "ProxyHas");
+
typedef bool (*ProxyHasOwnFn)(JSContext*, HandleObject, HandleValue, MutableHandleValue);
static const VMFunction ProxyHasOwnInfo = FunctionInfo<ProxyHasOwnFn>(ProxyHasOwn, "ProxyHasOwn");
bool
-BaselineCacheIRCompiler::emitCallProxyHasOwnResult()
+BaselineCacheIRCompiler::emitCallProxyHasPropResult()
{
Register obj = allocator.useRegister(masm, reader.objOperandId());
ValueOperand idVal = allocator.useValueRegister(masm, reader.valOperandId());
+ bool hasOwn = reader.readBool();
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;
+ if (hasOwn) {
+ if (!callVM(masm, ProxyHasOwnInfo))
+ return false;
+ } else {
+ if (!callVM(masm, ProxyHasInfo))
+ return false;
+ }
stubFrame.leave(masm);
return true;
}
bool
BaselineCacheIRCompiler::emitLoadUnboxedPropertyResult()
{
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -2560,23 +2560,23 @@ HasPropIRGenerator::tryAttachDoesNotExis
return false;
}
bool
HasPropIRGenerator::tryAttachProxyElement(HandleObject obj, ObjOperandId objId,
ValOperandId keyId)
{
- MOZ_ASSERT(cacheKind_ == CacheKind::HasOwn);
+ bool hasOwn = (cacheKind_ == CacheKind::HasOwn);
if (!obj->is<ProxyObject>())
return false;
writer.guardIsProxy(objId);
- writer.callProxyHasOwnResult(objId, keyId);
+ writer.callProxyHasPropResult(objId, keyId, hasOwn);
writer.returnFromIC();
trackAttached("ProxyHasProp");
return true;
}
bool
HasPropIRGenerator::tryAttachStub()
@@ -2592,21 +2592,19 @@ HasPropIRGenerator::tryAttachStub()
if (!val_.isObject()) {
trackNotAttached();
return false;
}
RootedObject obj(cx_, &val_.toObject());
ObjOperandId objId = writer.guardIsObject(valId);
- // Optimize DOM Proxies for JSOP_HASOWN
- if (cacheKind_ == CacheKind::HasOwn) {
- if (tryAttachProxyElement(obj, objId, keyId))
- return true;
- }
+ // Optimize Proxies
+ if (tryAttachProxyElement(obj, objId, keyId))
+ return true;
RootedId id(cx_);
bool nameOrSymbol;
if (!ValueToNameOrSymbolId(cx_, idVal_, &id, &nameOrSymbol)) {
cx_->clearPendingException();
return false;
}
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -256,17 +256,17 @@ extern const char* CacheKindNames[];
_(LoadFrameArgumentResult) \
_(LoadEnvironmentFixedSlotResult) \
_(LoadEnvironmentDynamicSlotResult) \
_(LoadObjectResult) \
_(CallScriptedGetterResult) \
_(CallNativeGetterResult) \
_(CallProxyGetResult) \
_(CallProxyGetByValueResult) \
- _(CallProxyHasOwnResult) \
+ _(CallProxyHasPropResult) \
_(LoadUndefinedResult) \
_(LoadBooleanResult) \
_(LoadStringResult) \
_(LoadTypeOfObjectResult) \
\
_(CallStringSplitResult) \
\
_(CompareStringResult) \
@@ -987,19 +987,20 @@ class MOZ_RAII CacheIRWriter : public JS
void callProxyGetResult(ObjOperandId obj, jsid id) {
writeOpWithOperandId(CacheOp::CallProxyGetResult, obj);
addStubField(uintptr_t(JSID_BITS(id)), StubField::Type::Id);
}
void callProxyGetByValueResult(ObjOperandId obj, ValOperandId idVal) {
writeOpWithOperandId(CacheOp::CallProxyGetByValueResult, obj);
writeOperandId(idVal);
}
- void callProxyHasOwnResult(ObjOperandId obj, ValOperandId idVal) {
- writeOpWithOperandId(CacheOp::CallProxyHasOwnResult, obj);
+ void callProxyHasPropResult(ObjOperandId obj, ValOperandId idVal, bool hasOwn) {
+ writeOpWithOperandId(CacheOp::CallProxyHasPropResult, obj);
writeOperandId(idVal);
+ buffer_.writeByte(uint32_t(hasOwn));
}
void loadEnvironmentFixedSlotResult(ObjOperandId obj, size_t offset) {
writeOpWithOperandId(CacheOp::LoadEnvironmentFixedSlotResult, obj);
addStubField(offset, StubField::Type::RawWord);
}
void loadEnvironmentDynamicSlotResult(ObjOperandId obj, size_t offset) {
writeOpWithOperandId(CacheOp::LoadEnvironmentDynamicSlotResult, obj);
addStubField(offset, StubField::Type::RawWord);
--- a/js/src/jit/IonCacheIRCompiler.cpp
+++ b/js/src/jit/IonCacheIRCompiler.cpp
@@ -1174,37 +1174,46 @@ IonCacheIRCompiler::emitCallProxyGetByVa
if (!callVM(masm, ProxyGetPropertyByValueInfo))
return false;
masm.storeCallResultValue(output);
return true;
}
+typedef bool (*ProxyHasFn)(JSContext*, HandleObject, HandleValue, MutableHandleValue);
+static const VMFunction ProxyHasInfo = FunctionInfo<ProxyHasFn>(ProxyHas, "ProxyHas");
+
typedef bool (*ProxyHasOwnFn)(JSContext*, HandleObject, HandleValue, MutableHandleValue);
static const VMFunction ProxyHasOwnInfo = FunctionInfo<ProxyHasOwnFn>(ProxyHasOwn, "ProxyHasOwn");
bool
-IonCacheIRCompiler::emitCallProxyHasOwnResult()
+IonCacheIRCompiler::emitCallProxyHasPropResult()
{
AutoSaveLiveRegisters save(*this);
AutoOutputRegister output(*this);
Register obj = allocator.useRegister(masm, reader.objOperandId());
ValueOperand idVal = allocator.useValueRegister(masm, reader.valOperandId());
+ bool hasOwn = reader.readBool();
allocator.discardStack(masm);
prepareVMCall(masm);
masm.Push(idVal);
masm.Push(obj);
- if (!callVM(masm, ProxyHasOwnInfo))
- return false;
+ if (hasOwn) {
+ if (!callVM(masm, ProxyHasOwnInfo))
+ return false;
+ } else {
+ if (!callVM(masm, ProxyHasInfo))
+ return false;
+ }
masm.storeCallResultValue(output);
return true;
}
bool
IonCacheIRCompiler::emitLoadUnboxedPropertyResult()
--- a/js/src/proxy/Proxy.cpp
+++ b/js/src/proxy/Proxy.cpp
@@ -267,16 +267,31 @@ Proxy::has(JSContext* cx, HandleObject p
return HasProperty(cx, proto, id, bp);
}
return handler->has(cx, proxy, id, bp);
}
bool
+js::ProxyHas(JSContext* cx, HandleObject proxy, HandleValue idVal, MutableHandleValue result)
+{
+ RootedId id(cx);
+ if (!ValueToId<CanGC>(cx, idVal, &id))
+ return false;
+
+ bool has;
+ if (!Proxy::has(cx, proxy, id, &has))
+ return false;
+
+ result.setBoolean(has);
+ return true;
+}
+
+bool
Proxy::hasOwn(JSContext* cx, HandleObject proxy, HandleId id, bool* bp)
{
if (!CheckRecursionLimit(cx))
return false;
const BaseProxyHandler* handler = proxy->as<ProxyObject>().handler();
*bp = false; // default result if we refuse to perform this action
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true);
if (!policy.allowed())
--- a/js/src/proxy/Proxy.h
+++ b/js/src/proxy/Proxy.h
@@ -81,16 +81,19 @@ proxy_Call(JSContext* cx, unsigned argc,
bool
proxy_Construct(JSContext* cx, unsigned argc, Value* vp);
size_t
proxy_ObjectMoved(JSObject* obj, JSObject* old);
// These functions are used by JIT code
bool
+ProxyHas(JSContext* cx, HandleObject proxy, HandleValue idVal, MutableHandleValue result);
+
+bool
ProxyHasOwn(JSContext* cx, HandleObject proxy, HandleValue idVal, MutableHandleValue result);
bool
ProxyGetProperty(JSContext* cx, HandleObject proxy, HandleId id, MutableHandleValue vp);
bool
ProxyGetPropertyByValue(JSContext* cx, HandleObject proxy, HandleValue idVal,
MutableHandleValue vp);