Bug 1357759 - Support proxies ICs for JSOP_IN draft
authorTed Campbell <tcampbell@mozilla.com>
Tue, 26 Sep 2017 15:40:43 -0400
changeset 672654 945135f3ffb793c4433808c8ced4b19d452186a0
parent 670880 116000a837a3526b9b465ab4130da9103402876f
child 672655 27a484fb86e171b129a99abcd8bf780c45b9b50b
push id82322
push userbmo:tcampbell@mozilla.com
push dateFri, 29 Sep 2017 15:16:57 +0000
bugs1357759
milestone58.0a1
Bug 1357759 - Support proxies ICs for JSOP_IN MozReview-Commit-ID: nyoeWmmOaZ
js/src/jit/BaselineCacheIRCompiler.cpp
js/src/jit/CacheIR.cpp
js/src/jit/CacheIR.h
js/src/jit/IonCacheIRCompiler.cpp
js/src/proxy/Proxy.cpp
js/src/proxy/Proxy.h
--- 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);