Bug 1319437 part 1 - Add a generic proxy GETPROP stub to CacheIR. r=nbp
authorJan de Mooij <jdemooij@mozilla.com>
Sat, 26 Nov 2016 21:19:22 +0100
changeset 324355 00c4f6b6f300527750b306d5e28ab3f4f4244292
parent 324354 8f0356af174c3f132eb3ef6bd2b4ad84e145e1bb
child 324356 febcffbc2d4aa18f999a049f425b71ee65e39be4
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersnbp
bugs1319437
milestone53.0a1
Bug 1319437 part 1 - Add a generic proxy GETPROP stub to CacheIR. r=nbp
js/src/jit/BaselineCacheIR.cpp
js/src/jit/CacheIR.cpp
js/src/jit/CacheIR.h
js/src/jit/IonCaches.cpp
js/src/jit/JitFrames.cpp
js/src/jit/MacroAssembler.cpp
js/src/jit/VMFunctions.cpp
js/src/jit/VMFunctions.h
--- a/js/src/jit/BaselineCacheIR.cpp
+++ b/js/src/jit/BaselineCacheIR.cpp
@@ -995,16 +995,45 @@ BaselineCacheIRCompiler::emitGuardClass(
     }
 
     MOZ_ASSERT(clasp);
     masm.branchTestObjClass(Assembler::NotEqual, obj, scratch, clasp, failure->label());
     return true;
 }
 
 bool
+BaselineCacheIRCompiler::emitGuardIsProxy()
+{
+    Register obj = allocator.useRegister(masm, reader.objOperandId());
+    AutoScratchRegister scratch(allocator, masm);
+
+    FailurePath* failure;
+    if (!addFailurePath(&failure))
+        return false;
+
+    masm.branchTestObjectIsProxy(false, obj, scratch, failure->label());
+    return true;
+}
+
+bool
+BaselineCacheIRCompiler::emitGuardNotDOMProxy()
+{
+    Register obj = allocator.useRegister(masm, reader.objOperandId());
+    AutoScratchRegister scratch(allocator, masm);
+
+    FailurePath* failure;
+    if (!addFailurePath(&failure))
+        return false;
+
+    masm.branchTestProxyHandlerFamily(Assembler::Equal, obj, scratch,
+                                      GetDOMProxyHandlerFamily(), failure->label());
+    return true;
+}
+
+bool
 BaselineCacheIRCompiler::emitGuardSpecificObject()
 {
     Register obj = allocator.useRegister(masm, reader.objOperandId());
 
     FailurePath* failure;
     if (!addFailurePath(&failure))
         return false;
 
@@ -1168,16 +1197,52 @@ BaselineCacheIRCompiler::emitCallNativeG
 
     if (!callVM(masm, DoCallNativeGetterInfo))
         return false;
 
     leaveStubFrame(masm);
     return true;
 }
 
+typedef bool (*ProxyGetPropertyFn)(JSContext*, HandleObject, HandleId, MutableHandleValue);
+static const VMFunction ProxyGetPropertyInfo =
+    FunctionInfo<ProxyGetPropertyFn>(ProxyGetProperty, "ProxyGetProperty");
+
+bool
+BaselineCacheIRCompiler::emitCallProxyGetResult()
+{
+    // We use ICTailCallReg when entering the stub frame, so ensure it's not
+    // used for something else.
+    Maybe<AutoScratchRegister> tail;
+    if (allocator.isAllocatable(ICTailCallReg))
+        tail.emplace(allocator, masm, ICTailCallReg);
+
+    Register obj = allocator.useRegister(masm, reader.objOperandId());
+    Address idAddr(stubAddress(reader.stubOffset()));
+
+    AutoScratchRegister scratch(allocator, masm);
+
+    allocator.discardStack(masm);
+
+    // Push a stub frame so that we can perform a non-tail call.
+    enterStubFrame(masm, scratch);
+
+    // Load the jsid in the scratch register.
+    masm.loadPtr(idAddr, scratch);
+
+    masm.Push(scratch);
+    masm.Push(obj);
+
+    if (!callVM(masm, ProxyGetPropertyInfo))
+        return false;
+
+    leaveStubFrame(masm);
+    return true;
+}
+
 bool
 BaselineCacheIRCompiler::emitLoadUnboxedPropertyResult()
 {
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     AutoScratchRegister scratch(allocator, masm);
 
     JSValueType fieldType = reader.valueType();
     Address fieldOffset(stubAddress(reader.stubOffset()));
@@ -1378,37 +1443,49 @@ CacheIRStubInfo::getStubField(ICStub* st
 template GCPtr<Shape*>& CacheIRStubInfo::getStubField(ICStub* stub, uint32_t offset) const;
 template GCPtr<ObjectGroup*>& CacheIRStubInfo::getStubField(ICStub* stub, uint32_t offset) const;
 template GCPtr<JSObject*>& CacheIRStubInfo::getStubField(ICStub* stub, uint32_t offset) const;
 
 template <typename T>
 static void
 InitGCPtr(uintptr_t* ptr, uintptr_t val)
 {
-    AsGCPtr<T*>(ptr)->init((T*)val);
+    AsGCPtr<T>(ptr)->init(T(val));
+}
+
+template <>
+void
+InitGCPtr<jsid>(uintptr_t* ptr, uintptr_t val)
+{
+    jsid id;
+    id.asBits = val;
+    AsGCPtr<jsid>(ptr)->init(id);
 }
 
 void
 CacheIRWriter::copyStubData(uint8_t* dest) const
 {
     uintptr_t* destWords = reinterpret_cast<uintptr_t*>(dest);
 
     for (size_t i = 0; i < stubFields_.length(); i++) {
         switch (stubFields_[i].gcType) {
           case StubField::GCType::NoGCThing:
             destWords[i] = stubFields_[i].word;
             continue;
           case StubField::GCType::Shape:
-            InitGCPtr<Shape>(destWords + i, stubFields_[i].word);
+            InitGCPtr<Shape*>(destWords + i, stubFields_[i].word);
             continue;
           case StubField::GCType::JSObject:
-            InitGCPtr<JSObject>(destWords + i, stubFields_[i].word);
+            InitGCPtr<JSObject*>(destWords + i, stubFields_[i].word);
             continue;
           case StubField::GCType::ObjectGroup:
-            InitGCPtr<ObjectGroup>(destWords + i, stubFields_[i].word);
+            InitGCPtr<ObjectGroup*>(destWords + i, stubFields_[i].word);
+            continue;
+          case StubField::GCType::Id:
+            InitGCPtr<jsid>(destWords + i, stubFields_[i].word);
             continue;
           case StubField::GCType::Limit:
             break;
         }
         MOZ_CRASH();
     }
 }
 
@@ -1562,36 +1639,38 @@ jit::TraceBaselineCacheIRStub(JSTracer* 
           case StubField::GCType::ObjectGroup:
             TraceNullableEdge(trc, &stubInfo->getStubField<ObjectGroup*>(stub, field),
                               "baseline-cacheir-group");
             break;
           case StubField::GCType::JSObject:
             TraceNullableEdge(trc, &stubInfo->getStubField<JSObject*>(stub, field),
                               "baseline-cacheir-object");
             break;
+          case StubField::GCType::Id:
+            TraceEdge(trc, &stubInfo->getStubField<jsid>(stub, field), "baseline-cacheir-id");
+            break;
           case StubField::GCType::Limit:
             return; // Done.
-          default:
-            MOZ_CRASH();
         }
         field++;
     }
 }
 
 size_t
 CacheIRStubInfo::stubDataSize() const
 {
     size_t field = 0;
     size_t size = 0;
     while (true) {
         switch (gcType(field++)) {
           case StubField::GCType::NoGCThing:
           case StubField::GCType::Shape:
           case StubField::GCType::ObjectGroup:
           case StubField::GCType::JSObject:
+          case StubField::GCType::Id:
             size += sizeof(uintptr_t);
             continue;
           case StubField::GCType::Limit:
             return size;
         }
         MOZ_CRASH("unreachable");
     }
 }
@@ -1612,16 +1691,19 @@ CacheIRStubInfo::copyStubData(ICStub* sr
             getStubField<Shape*>(dest, field).init(getStubField<Shape*>(src, field));
             break;
           case StubField::GCType::JSObject:
             getStubField<JSObject*>(dest, field).init(getStubField<JSObject*>(src, field));
             break;
           case StubField::GCType::ObjectGroup:
             getStubField<ObjectGroup*>(dest, field).init(getStubField<ObjectGroup*>(src, field));
             break;
+          case StubField::GCType::Id:
+            getStubField<jsid>(dest, field).init(getStubField<jsid>(src, field));
+            break;
           case StubField::GCType::Limit:
             return; // Done.
         }
         field++;
     }
 }
 
 
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -69,16 +69,18 @@ GetPropIRGenerator::tryAttachStub(Maybe<
         if (!emitted_ && !tryAttachUnboxedExpando(*writer, obj, objId))
             return false;
         if (!emitted_ && !tryAttachTypedObject(*writer, obj, objId))
             return false;
         if (!emitted_ && !tryAttachModuleNamespace(*writer, obj, objId))
             return false;
         if (!emitted_ && !tryAttachWindowProxy(*writer, obj, objId))
             return false;
+        if (!emitted_ && !tryAttachProxy(*writer, obj, objId))
+            return false;
         return true;
     }
 
     if (!emitted_ && !tryAttachPrimitive(*writer, valId))
         return false;
 
     return true;
 }
@@ -377,16 +379,47 @@ GetPropIRGenerator::tryAttachWindowProxy
     // on the Window object.
     writer.guardClass(objId, GuardClassKind::WindowProxy);
     ObjOperandId windowObjId = writer.loadObject(windowObj);
     EmitCallGetterResult(writer, windowObj, holder, shape, windowObjId);
     return true;
 }
 
 bool
+GetPropIRGenerator::tryAttachGenericProxy(CacheIRWriter& writer, HandleObject obj,
+                                          ObjOperandId objId)
+{
+    MOZ_ASSERT(!emitted_);
+    MOZ_ASSERT(obj->is<ProxyObject>());
+
+    emitted_ = true;
+
+    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);
+
+    writer.callProxyGetResult(objId, NameToId(name_));
+    writer.typeMonitorResult();
+    return true;
+}
+
+bool
+GetPropIRGenerator::tryAttachProxy(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId)
+{
+    MOZ_ASSERT(!emitted_);
+
+    if (!obj->is<ProxyObject>())
+        return true;
+
+    return tryAttachGenericProxy(writer, obj, objId);
+}
+
+bool
 GetPropIRGenerator::tryAttachUnboxed(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId)
 {
     MOZ_ASSERT(!emitted_);
 
     if (!obj->is<UnboxedPlainObject>())
         return true;
 
     const UnboxedLayout::Property* property = obj->as<UnboxedPlainObject>().layout().lookup(name_);
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -80,16 +80,18 @@ class ObjOperandId : public OperandId
 
 #define CACHE_IR_OPS(_)                   \
     _(GuardIsObject)                      \
     _(GuardType)                          \
     _(GuardShape)                         \
     _(GuardGroup)                         \
     _(GuardProto)                         \
     _(GuardClass)                         \
+    _(GuardIsProxy)                       \
+    _(GuardNotDOMProxy)                   \
     _(GuardSpecificObject)                \
     _(GuardNoDetachedTypedObjects)        \
     _(GuardNoUnboxedExpando)              \
     _(GuardAndLoadUnboxedExpando)         \
     _(LoadObject)                         \
     _(LoadProto)                          \
                                           \
     /* The *Result ops load a value into the cache's result register. */ \
@@ -97,16 +99,17 @@ class ObjOperandId : public OperandId
     _(LoadDynamicSlotResult)              \
     _(LoadUnboxedPropertyResult)          \
     _(LoadTypedObjectResult)              \
     _(LoadInt32ArrayLengthResult)         \
     _(LoadUnboxedArrayLengthResult)       \
     _(LoadArgumentsObjectLengthResult)    \
     _(CallScriptedGetterResult)           \
     _(CallNativeGetterResult)             \
+    _(CallProxyGetResult)                 \
     _(LoadUndefinedResult)                \
                                           \
     _(TypeMonitorResult)                  \
     _(ReturnFromIC)
 
 enum class CacheOp {
 #define DEFINE_OP(op) op,
     CACHE_IR_OPS(DEFINE_OP)
@@ -114,16 +117,17 @@ enum class CacheOp {
 };
 
 struct StubField {
     enum class GCType {
         NoGCThing,
         Shape,
         ObjectGroup,
         JSObject,
+        Id,
         Limit
     };
 
     uintptr_t word;
     GCType gcType;
 
     StubField(uintptr_t word, GCType gcType)
       : word(word), gcType(gcType)
@@ -273,16 +277,22 @@ class MOZ_RAII CacheIRWriter
         addStubWord(uintptr_t(proto), StubField::GCType::JSObject);
     }
     void guardClass(ObjOperandId obj, GuardClassKind kind) {
         static_assert(sizeof(GuardClassKind) == sizeof(uint8_t),
                       "GuardClassKind must fit in a byte");
         writeOpWithOperandId(CacheOp::GuardClass, obj);
         buffer_.writeByte(uint32_t(kind));
     }
+    void guardIsProxy(ObjOperandId obj) {
+        writeOpWithOperandId(CacheOp::GuardIsProxy, obj);
+    }
+    void guardNotDOMProxy(ObjOperandId obj) {
+        writeOpWithOperandId(CacheOp::GuardNotDOMProxy, obj);
+    }
     void guardSpecificObject(ObjOperandId obj, JSObject* expected) {
         writeOpWithOperandId(CacheOp::GuardSpecificObject, obj);
         addStubWord(uintptr_t(expected), StubField::GCType::JSObject);
     }
     void guardNoDetachedTypedObjects() {
         writeOp(CacheOp::GuardNoDetachedTypedObjects);
     }
     void guardNoUnboxedExpando(ObjOperandId obj) {
@@ -345,16 +355,20 @@ class MOZ_RAII CacheIRWriter
     void callScriptedGetterResult(ObjOperandId obj, JSFunction* getter) {
         writeOpWithOperandId(CacheOp::CallScriptedGetterResult, obj);
         addStubWord(uintptr_t(getter), StubField::GCType::JSObject);
     }
     void callNativeGetterResult(ObjOperandId obj, JSFunction* getter) {
         writeOpWithOperandId(CacheOp::CallNativeGetterResult, obj);
         addStubWord(uintptr_t(getter), StubField::GCType::JSObject);
     }
+    void callProxyGetResult(ObjOperandId obj, jsid id) {
+        writeOpWithOperandId(CacheOp::CallProxyGetResult, obj);
+        addStubWord(uintptr_t(JSID_BITS(id)), StubField::GCType::Id);
+    }
 
     void typeMonitorResult() {
         writeOp(CacheOp::TypeMonitorResult);
     }
     void returnFromIC() {
         writeOp(CacheOp::ReturnFromIC);
     }
 };
@@ -444,16 +458,20 @@ class MOZ_RAII GetPropIRGenerator
                                            ObjOperandId objId);
     MOZ_MUST_USE bool tryAttachObjectLength(CacheIRWriter& writer, HandleObject obj,
                                             ObjOperandId objId);
     MOZ_MUST_USE bool tryAttachModuleNamespace(CacheIRWriter& writer, HandleObject obj,
                                                ObjOperandId objId);
     MOZ_MUST_USE bool tryAttachWindowProxy(CacheIRWriter& writer, HandleObject obj,
                                            ObjOperandId objId);
 
+    MOZ_MUST_USE bool tryAttachGenericProxy(CacheIRWriter& writer, HandleObject obj,
+                                            ObjOperandId objId);
+    MOZ_MUST_USE bool tryAttachProxy(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId);
+
     MOZ_MUST_USE bool tryAttachPrimitive(CacheIRWriter& writer, ValOperandId valId);
 
     GetPropIRGenerator(const GetPropIRGenerator&) = delete;
     GetPropIRGenerator& operator=(const GetPropIRGenerator&) = delete;
 
   public:
     GetPropIRGenerator(JSContext* cx, jsbytecode* pc, ICStubEngine engine,
                        bool* isTemporarilyUnoptimizable,
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -1681,23 +1681,16 @@ static void
 PushObjectOpResult(MacroAssembler& masm)
 {
     static_assert(sizeof(ObjectOpResult) == sizeof(uintptr_t),
                   "ObjectOpResult size must match size reserved by masm.Push() here");
     masm.Push(ImmWord(ObjectOpResult::Uninitialized));
 }
 
 static bool
-ProxyGetProperty(JSContext* cx, HandleObject proxy, HandleId id, MutableHandleValue vp)
-{
-    RootedValue receiver(cx, ObjectValue(*proxy));
-    return Proxy::get(cx, proxy, receiver, id, vp);
-}
-
-static bool
 EmitCallProxyGet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& attacher,
                  jsid id, LiveRegisterSet liveRegs, Register object, TypedOrValueRegister output,
                  jsbytecode* pc, void* returnAddr)
 {
     MOZ_ASSERT(output.hasValue());
     MacroAssembler::AfterICSaveLive aic = masm.icSaveLive(liveRegs);
 
     // Remaining registers should be free, but we need to use |object| still
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -1333,25 +1333,27 @@ TraceJitExitFrame(JSTracer* trc, const J
           case VMFunction::RootObject: {
             // Sometimes we can bake in HandleObjects to nullptr.
             JSObject** pobj = reinterpret_cast<JSObject**>(argBase);
             if (*pobj)
                 TraceRoot(trc, pobj, "ion-vm-args");
             break;
           }
           case VMFunction::RootString:
-          case VMFunction::RootPropertyName:
             TraceRoot(trc, reinterpret_cast<JSString**>(argBase), "ion-vm-args");
             break;
           case VMFunction::RootFunction:
             TraceRoot(trc, reinterpret_cast<JSFunction**>(argBase), "ion-vm-args");
             break;
           case VMFunction::RootValue:
             TraceRoot(trc, reinterpret_cast<Value*>(argBase), "ion-vm-args");
             break;
+          case VMFunction::RootId:
+            TraceRoot(trc, reinterpret_cast<jsid*>(argBase), "ion-vm-args");
+            break;
           case VMFunction::RootCell:
             TraceGenericPointerRoot(trc, reinterpret_cast<gc::Cell**>(argBase), "ion-vm-args");
             break;
         }
 
         switch (f->argProperties(explicitArg)) {
           case VMFunction::WordByValue:
           case VMFunction::WordByRef:
@@ -1367,25 +1369,27 @@ TraceJitExitFrame(JSTracer* trc, const J
     if (f->outParam == Type_Handle) {
         switch (f->outParamRootType) {
           case VMFunction::RootNone:
             MOZ_CRASH("Handle outparam must have root type");
           case VMFunction::RootObject:
             TraceRoot(trc, footer->outParam<JSObject*>(), "ion-vm-out");
             break;
           case VMFunction::RootString:
-          case VMFunction::RootPropertyName:
             TraceRoot(trc, footer->outParam<JSString*>(), "ion-vm-out");
             break;
           case VMFunction::RootFunction:
             TraceRoot(trc, footer->outParam<JSFunction*>(), "ion-vm-out");
             break;
           case VMFunction::RootValue:
             TraceRoot(trc, footer->outParam<Value>(), "ion-vm-outvp");
             break;
+          case VMFunction::RootId:
+            TraceRoot(trc, footer->outParam<jsid>(), "ion-vm-outvp");
+            break;
           case VMFunction::RootCell:
             TraceGenericPointerRoot(trc, footer->outParam<gc::Cell*>(), "ion-vm-out");
             break;
         }
     }
 
     TraceJitExitFrameCopiedArguments(trc, f, footer);
 }
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -2501,39 +2501,41 @@ MacroAssembler::PushValue(const Address&
 void
 MacroAssembler::PushEmptyRooted(VMFunction::RootType rootType)
 {
     switch (rootType) {
       case VMFunction::RootNone:
         MOZ_CRASH("Handle must have root type");
       case VMFunction::RootObject:
       case VMFunction::RootString:
-      case VMFunction::RootPropertyName:
       case VMFunction::RootFunction:
       case VMFunction::RootCell:
         Push(ImmPtr(nullptr));
         break;
       case VMFunction::RootValue:
         Push(UndefinedValue());
         break;
+      case VMFunction::RootId:
+        Push(ImmWord(JSID_BITS(JSID_VOID)));
+        break;
     }
 }
 
 void
 MacroAssembler::popRooted(VMFunction::RootType rootType, Register cellReg,
                           const ValueOperand& valueReg)
 {
     switch (rootType) {
       case VMFunction::RootNone:
         MOZ_CRASH("Handle must have root type");
       case VMFunction::RootObject:
       case VMFunction::RootString:
-      case VMFunction::RootPropertyName:
       case VMFunction::RootFunction:
       case VMFunction::RootCell:
+      case VMFunction::RootId:
         Pop(cellReg);
         break;
       case VMFunction::RootValue:
         Pop(valueReg);
         break;
     }
 }
 
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -1350,10 +1350,17 @@ ThrowObjectCoercible(JSContext* cx, Hand
 }
 
 bool
 BaselineGetFunctionThis(JSContext* cx, BaselineFrame* frame, MutableHandleValue res)
 {
     return GetFunctionThis(cx, frame, res);
 }
 
+bool
+ProxyGetProperty(JSContext* cx, HandleObject proxy, HandleId id, MutableHandleValue vp)
+{
+    RootedValue receiver(cx, ObjectValue(*proxy));
+    return Proxy::get(cx, proxy, receiver, id, vp);
+}
+
 } // namespace jit
 } // namespace js
--- a/js/src/jit/VMFunctions.h
+++ b/js/src/jit/VMFunctions.h
@@ -107,17 +107,17 @@ struct VMFunction
     // nullptr before discarding its value.
     DataType returnType;
 
     // Note: a maximum of seven root types is supported.
     enum RootType {
         RootNone = 0,
         RootObject,
         RootString,
-        RootPropertyName,
+        RootId,
         RootFunction,
         RootValue,
         RootCell
     };
 
     // Contains an combination of enumerated types used by the gc for marking
     // arguments of the VM wrapper.
     uint64_t argumentRootTypes;
@@ -279,16 +279,17 @@ template <> struct TypeToDataType<Handle
 template <> struct TypeToDataType<Handle<GeneratorObject*> > { static const DataType result = Type_Handle; };
 template <> struct TypeToDataType<Handle<PlainObject*> > { static const DataType result = Type_Handle; };
 template <> struct TypeToDataType<Handle<WithScope*> > { static const DataType result = Type_Handle; };
 template <> struct TypeToDataType<Handle<LexicalScope*> > { static const DataType result = Type_Handle; };
 template <> struct TypeToDataType<Handle<Scope*> > { static const DataType result = Type_Handle; };
 template <> struct TypeToDataType<HandleScript> { static const DataType result = Type_Handle; };
 template <> struct TypeToDataType<HandleValue> { static const DataType result = Type_Handle; };
 template <> struct TypeToDataType<MutableHandleValue> { static const DataType result = Type_Handle; };
+template <> struct TypeToDataType<HandleId> { static const DataType result = Type_Handle; };
 
 // Convert argument types to properties of the argument known by the jit.
 template <class T> struct TypeToArgProperties {
     static const uint32_t result =
         (sizeof(T) <= sizeof(void*) ? VMFunction::Word : VMFunction::Double);
 };
 template <> struct TypeToArgProperties<const Value&> {
     static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef;
@@ -333,16 +334,19 @@ template <> struct TypeToArgProperties<H
     static const uint32_t result = TypeToArgProperties<JSScript*>::result | VMFunction::ByRef;
 };
 template <> struct TypeToArgProperties<HandleValue> {
     static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef;
 };
 template <> struct TypeToArgProperties<MutableHandleValue> {
     static const uint32_t result = TypeToArgProperties<Value>::result | VMFunction::ByRef;
 };
+template <> struct TypeToArgProperties<HandleId> {
+    static const uint32_t result = TypeToArgProperties<jsid>::result | VMFunction::ByRef;
+};
 template <> struct TypeToArgProperties<HandleShape> {
     static const uint32_t result = TypeToArgProperties<Shape*>::result | VMFunction::ByRef;
 };
 template <> struct TypeToArgProperties<HandleObjectGroup> {
     static const uint32_t result = TypeToArgProperties<ObjectGroup*>::result | VMFunction::ByRef;
 };
 
 // Convert argument type to whether or not it should be passed in a float
@@ -360,27 +364,30 @@ template <class T> struct TypeToRootType
 };
 template <> struct TypeToRootType<HandleObject> {
     static const uint32_t result = VMFunction::RootObject;
 };
 template <> struct TypeToRootType<HandleString> {
     static const uint32_t result = VMFunction::RootString;
 };
 template <> struct TypeToRootType<HandlePropertyName> {
-    static const uint32_t result = VMFunction::RootPropertyName;
+    static const uint32_t result = VMFunction::RootString;
 };
 template <> struct TypeToRootType<HandleFunction> {
     static const uint32_t result = VMFunction::RootFunction;
 };
 template <> struct TypeToRootType<HandleValue> {
     static const uint32_t result = VMFunction::RootValue;
 };
 template <> struct TypeToRootType<MutableHandleValue> {
     static const uint32_t result = VMFunction::RootValue;
 };
+template <> struct TypeToRootType<HandleId> {
+    static const uint32_t result = VMFunction::RootId;
+};
 template <> struct TypeToRootType<HandleShape> {
     static const uint32_t result = VMFunction::RootCell;
 };
 template <> struct TypeToRootType<HandleObjectGroup> {
     static const uint32_t result = VMFunction::RootCell;
 };
 template <> struct TypeToRootType<HandleScript> {
     static const uint32_t result = VMFunction::RootCell;
@@ -797,12 +804,15 @@ MOZ_MUST_USE bool
 ThrowBadDerivedReturn(JSContext* cx, HandleValue v);
 
 MOZ_MUST_USE bool
 ThrowObjectCoercible(JSContext* cx, HandleValue v);
 
 MOZ_MUST_USE bool
 BaselineGetFunctionThis(JSContext* cx, BaselineFrame* frame, MutableHandleValue res);
 
+MOZ_MUST_USE bool
+ProxyGetProperty(JSContext* cx, HandleObject proxy, HandleId id, MutableHandleValue vp);
+
 } // namespace jit
 } // namespace js
 
 #endif /* jit_VMFunctions_h */