Bug 1124195 - Replace use of AutoPtr with mozilla::UniquePtr r=sfink
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 22 Jan 2015 14:11:12 +0000
changeset 225275 775bb50c16d6abcba3e241c1494a62a688f3c0ce
parent 225274 468c1db9e3389094980c3d3f3e464587e182334c
child 225276 f4a464da4b43e38322bbcb9f4951eaaa8fc434fd
push id54517
push userjcoppeard@mozilla.com
push dateFri, 23 Jan 2015 09:58:15 +0000
treeherdermozilla-inbound@f4a464da4b43 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1124195
milestone38.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1124195 - Replace use of AutoPtr with mozilla::UniquePtr r=sfink
js/src/ctypes/CTypes.cpp
js/src/ctypes/CTypes.h
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -2578,17 +2578,17 @@ ImplicitConvert(JSContext* cx,
           targetLength != size_t(sourceLength)) {
         JS_ReportError(cx, "ArrayType length does not match source array length");
         return false;
       }
 
       // Convert into an intermediate, in case of failure.
       size_t elementSize = CType::GetSize(baseType);
       size_t arraySize = elementSize * targetLength;
-      AutoPtr<char> intermediate(cx->pod_malloc<char>(arraySize));
+      auto intermediate = cx->make_pod_array<char>(arraySize);
       if (!intermediate) {
         JS_ReportAllocationOverflow(cx);
         return false;
       }
 
       for (uint32_t i = 0; i < sourceLength; ++i) {
         RootedValue item(cx);
         if (!JS_GetElement(cx, valObj, i, &item))
@@ -2643,17 +2643,17 @@ ImplicitConvert(JSContext* cx,
       // Enumerate the properties of the object; if they match the struct
       // specification, convert the fields.
       AutoIdArray props(cx, JS_Enumerate(cx, valObj));
       if (!props)
         return false;
 
       // Convert into an intermediate, in case of failure.
       size_t structSize = CType::GetSize(targetType);
-      AutoPtr<char> intermediate(cx->pod_malloc<char>(structSize));
+      auto intermediate = cx->make_pod_array<char>(structSize);
       if (!intermediate) {
         JS_ReportAllocationOverflow(cx);
         return false;
       }
 
       const FieldInfoHash* fields = StructType::GetFieldInfo(targetType);
       if (props.length() != fields->count()) {
         JS_ReportError(cx, "missing fields");
@@ -3627,34 +3627,34 @@ CType::GetFFIType(JSContext* cx, JSObjec
   MOZ_ASSERT(CType::IsCType(obj));
 
   jsval slot = JS_GetReservedSlot(obj, SLOT_FFITYPE);
 
   if (!slot.isUndefined()) {
     return static_cast<ffi_type*>(slot.toPrivate());
   }
 
-  AutoPtr<ffi_type> result;
+  UniquePtrFFIType result;
   switch (CType::GetTypeCode(obj)) {
   case TYPE_array:
     result = ArrayType::BuildFFIType(cx, obj);
     break;
 
   case TYPE_struct:
     result = StructType::BuildFFIType(cx, obj);
     break;
 
   default:
     MOZ_CRASH("simple types must have an ffi_type");
   }
 
   if (!result)
     return nullptr;
   JS_SetReservedSlot(obj, SLOT_FFITYPE, PRIVATE_TO_JSVAL(result.get()));
-  return result.forget();
+  return result.release();
 }
 
 JSString*
 CType::GetName(JSContext* cx, HandleObject obj)
 {
   MOZ_ASSERT(CType::IsCType(obj));
 
   jsval string = JS_GetReservedSlot(obj, SLOT_NAME);
@@ -4491,17 +4491,17 @@ ArrayType::GetLength(JSObject* obj)
   // The "length" property can be an int, a double, or JSVAL_VOID
   // (for arrays of undefined length), and must always fit in a size_t.
   // For callers who know it can never be JSVAL_VOID, return a size_t directly.
   if (length.isInt32())
     return length.toInt32();
   return Convert<size_t>(length.toDouble());
 }
 
-ffi_type*
+UniquePtrFFIType
 ArrayType::BuildFFIType(JSContext* cx, JSObject* obj)
 {
   MOZ_ASSERT(CType::IsCType(obj));
   MOZ_ASSERT(CType::GetTypeCode(obj) == TYPE_array);
   MOZ_ASSERT(CType::IsSizeDefined(obj));
 
   JSObject* baseType = ArrayType::GetBaseType(obj);
   ffi_type* ffiBaseType = CType::GetFFIType(cx, baseType);
@@ -4512,17 +4512,17 @@ ArrayType::BuildFFIType(JSContext* cx, J
 
   // Create an ffi_type to represent the array. This is necessary for the case
   // where the array is part of a struct. Since libffi has no intrinsic
   // support for array types, we approximate it by creating a struct type
   // with elements of type 'baseType' and with appropriate size and alignment
   // values. It would be nice to not do all the work of setting up 'elements',
   // but some libffi platforms currently require that it be meaningful. I'm
   // looking at you, x86_64.
-  AutoPtr<ffi_type> ffiType(cx->new_<ffi_type>());
+  auto ffiType = cx->make_unique<ffi_type>();
   if (!ffiType) {
     JS_ReportOutOfMemory(cx);
     return nullptr;
   }
 
   ffiType->type = FFI_TYPE_STRUCT;
   ffiType->size = CType::GetSize(obj);
   ffiType->alignment = CType::GetAlignment(obj);
@@ -4531,17 +4531,17 @@ ArrayType::BuildFFIType(JSContext* cx, J
     JS_ReportAllocationOverflow(cx);
     return nullptr;
   }
 
   for (size_t i = 0; i < length; ++i)
     ffiType->elements[i] = ffiBaseType;
   ffiType->elements[length] = nullptr;
 
-  return ffiType.forget();
+  return Move(ffiType);
 }
 
 bool
 ArrayType::IsArrayType(HandleValue v)
 {
   if (!v.isObject())
     return false;
   JSObject* obj = &v.toObject();
@@ -4875,17 +4875,17 @@ StructType::DefineInternal(JSContext* cx
   if (!JS_DefineProperty(cx, prototype, "constructor", typeObj,
                          JSPROP_READONLY | JSPROP_PERMANENT))
     return false;
 
   // Create a FieldInfoHash to stash on the type object, and an array to root
   // its constituents. (We cannot simply stash the hash in a reserved slot now
   // to get GC safety for free, since if anything in this function fails we
   // do not want to mutate 'typeObj'.)
-  AutoPtr<FieldInfoHash> fields(cx->new_<FieldInfoHash>());
+  auto fields = cx->make_unique<FieldInfoHash>();
   if (!fields || !fields->init(len)) {
     JS_ReportOutOfMemory(cx);
     return false;
   }
   JS::AutoValueVector fieldRoots(cx);
   if (!fieldRoots.resize(len)) {
     JS_ReportOutOfMemory(cx);
     return false;
@@ -4968,77 +4968,72 @@ StructType::DefineInternal(JSContext* cx
     structSize = 1;
     structAlign = 1;
   }
 
   RootedValue sizeVal(cx);
   if (!SizeTojsval(cx, structSize, &sizeVal))
     return false;
 
-  JS_SetReservedSlot(typeObj, SLOT_FIELDINFO, PRIVATE_TO_JSVAL(fields.forget()));
+  JS_SetReservedSlot(typeObj, SLOT_FIELDINFO, PRIVATE_TO_JSVAL(fields.release()));
 
   JS_SetReservedSlot(typeObj, SLOT_SIZE, sizeVal);
   JS_SetReservedSlot(typeObj, SLOT_ALIGN, INT_TO_JSVAL(structAlign));
   //if (!JS_FreezeObject(cx, prototype)0 // XXX fixme - see bug 541212!
   //  return false;
   JS_SetReservedSlot(typeObj, SLOT_PROTO, OBJECT_TO_JSVAL(prototype));
   return true;
 }
 
-ffi_type*
+UniquePtrFFIType
 StructType::BuildFFIType(JSContext* cx, JSObject* obj)
 {
   MOZ_ASSERT(CType::IsCType(obj));
   MOZ_ASSERT(CType::GetTypeCode(obj) == TYPE_struct);
   MOZ_ASSERT(CType::IsSizeDefined(obj));
 
   const FieldInfoHash* fields = GetFieldInfo(obj);
   size_t len = fields->count();
 
   size_t structSize = CType::GetSize(obj);
   size_t structAlign = CType::GetAlignment(obj);
 
-  AutoPtr<ffi_type> ffiType(cx->new_<ffi_type>());
+  auto ffiType = cx->make_unique<ffi_type>();
   if (!ffiType) {
     JS_ReportOutOfMemory(cx);
     return nullptr;
   }
   ffiType->type = FFI_TYPE_STRUCT;
 
-  AutoPtr<ffi_type*> elements;
+  size_t count = len != 0 ? len + 1 : 2;
+  auto elements = cx->make_pod_array<ffi_type*>(count);
+  if (!elements) {
+    JS_ReportOutOfMemory(cx);
+    return nullptr;
+  }
+
   if (len != 0) {
-    elements = cx->pod_malloc<ffi_type*>(len + 1);
-    if (!elements) {
-      JS_ReportOutOfMemory(cx);
-      return nullptr;
-    }
     elements[len] = nullptr;
 
     for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) {
       const FieldInfoHash::Entry& entry = r.front();
       ffi_type* fieldType = CType::GetFFIType(cx, entry.value().mType);
       if (!fieldType)
         return nullptr;
       elements[entry.value().mIndex] = fieldType;
     }
-
   } else {
     // Represent an empty struct as having a size of 1 byte, just like C++.
     MOZ_ASSERT(structSize == 1);
     MOZ_ASSERT(structAlign == 1);
-    elements = cx->pod_malloc<ffi_type*>(2);
-    if (!elements) {
-      JS_ReportOutOfMemory(cx);
-      return nullptr;
-    }
     elements[0] = &ffi_type_uint8;
     elements[1] = nullptr;
   }
 
-  ffiType->elements = elements.get();
+  ffiType->elements = elements.release();
 
 #ifdef DEBUG
   // Perform a sanity check: the result of our struct size and alignment
   // calculations should match libffi's. We force it to do this calculation
   // by calling ffi_prep_cif.
   ffi_cif cif;
   ffiType->size = 0;
   ffiType->alignment = 0;
@@ -5050,18 +5045,17 @@ StructType::BuildFFIType(JSContext* cx, 
   // Fill in the ffi_type's size and align fields. This makes libffi treat the
   // type as initialized; it will not recompute the values. (We assume
   // everything agrees; if it doesn't, we really want to know about it, which
   // is the purpose of the above debug-only check.)
   ffiType->size = structSize;
   ffiType->alignment = structAlign;
 #endif
 
-  elements.forget();
-  return ffiType.forget();
+  return Move(ffiType);
 }
 
 bool
 StructType::Define(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
   RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
   if (!obj)
--- a/js/src/ctypes/CTypes.h
+++ b/js/src/ctypes/CTypes.h
@@ -1,65 +1,34 @@
 /* -*-  Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef ctypes_CTypes_h
 #define ctypes_CTypes_h
 
+#include "mozilla/UniquePtr.h"
+
 #include "ffi.h"
 #include "jsalloc.h"
 #include "prlink.h"
 
 #include "ctypes/typedefs.h"
 #include "js/HashTable.h"
 #include "js/Vector.h"
 #include "vm/String.h"
 
 namespace js {
 namespace ctypes {
 
 /*******************************************************************************
 ** Utility classes
 *******************************************************************************/
 
-// Class that takes ownership of a pointer T*, and calls cx->delete_() or
-// cx->array_delete() upon destruction.
-template<class T>
-class AutoPtr {
-private:
-  typedef AutoPtr<T> self_type;
-
-public:
-  AutoPtr() : mPtr(nullptr) { }
-  explicit AutoPtr(T* ptr) : mPtr(ptr) { }
-  ~AutoPtr() { js_delete(mPtr); }
-
-  T*   operator->()         { return mPtr; }
-  bool operator!()          { return mPtr == nullptr; }
-  T&   operator[](size_t i) { return *(mPtr + i); }
-  // Note: we cannot safely provide an 'operator T*()', since this would allow
-  // the compiler to perform implicit conversion from one AutoPtr to another
-  // via the constructor AutoPtr(T*).
-
-  T*   get()         { return mPtr; }
-  void set(T* other) { MOZ_ASSERT(mPtr == nullptr); mPtr = other; }
-  T*   forget()      { T* result = mPtr; mPtr = nullptr; return result; }
-
-  self_type& operator=(T* rhs) { mPtr = rhs; return *this; }
-
-private:
-  // Do not allow copy construction or assignment from another AutoPtr.
-  AutoPtr(AutoPtr<T>&);
-  self_type& operator=(AutoPtr<T>& rhs);
-
-  T* mPtr;
-};
-
 // Container class for Vector, using SystemAllocPolicy.
 template<class T, size_t N = 0>
 class Array : public Vector<T, N, SystemAllocPolicy>
 {
   static_assert(!mozilla::IsSame<T, JS::Value>::value,
                 "use JS::AutoValueVector instead");
 };
 
@@ -467,33 +436,35 @@ namespace CType {
 }
 
 namespace PointerType {
   JSObject* CreateInternal(JSContext* cx, HandleObject baseType);
 
   JSObject* GetBaseType(JSObject* obj);
 }
 
+typedef mozilla::UniquePtr<ffi_type, JS::DeletePolicy<ffi_type>> UniquePtrFFIType;
+
 namespace ArrayType {
   JSObject* CreateInternal(JSContext* cx, HandleObject baseType, size_t length,
     bool lengthDefined);
 
   JSObject* GetBaseType(JSObject* obj);
   size_t GetLength(JSObject* obj);
   bool GetSafeLength(JSObject* obj, size_t* result);
-  ffi_type* BuildFFIType(JSContext* cx, JSObject* obj);
+  UniquePtrFFIType BuildFFIType(JSContext* cx, JSObject* obj);
 }
 
 namespace StructType {
   bool DefineInternal(JSContext* cx, JSObject* typeObj, JSObject* fieldsObj);
 
   const FieldInfoHash* GetFieldInfo(JSObject* obj);
   const FieldInfo* LookupField(JSContext* cx, JSObject* obj, JSFlatString *name);
   JSObject* BuildFieldsArray(JSContext* cx, JSObject* obj);
-  ffi_type* BuildFFIType(JSContext* cx, JSObject* obj);
+  UniquePtrFFIType BuildFFIType(JSContext* cx, JSObject* obj);
 }
 
 namespace FunctionType {
   JSObject* CreateInternal(JSContext* cx, HandleValue abi, HandleValue rtype,
     const HandleValueArray& args);
 
   JSObject* ConstructWithObject(JSContext* cx, JSObject* typeObj,
     JSObject* refObj, PRFuncPtr fnptr, JSObject* result);