Backed out changeset 152d407cf4d2 (bug 1124195) for Hazard analysis failures.
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 22 Jan 2015 12:24:36 -0500
changeset 225148 6b087f5cd1e4ba3999e5e0d7875f18320caf14e2
parent 225147 a21adc873ee4a5c6852a0f35220af9bf1d55f02d
child 225149 1d5fe20ad2bb492b6f78feafe4577af593be825b
push id54463
push userryanvm@gmail.com
push dateThu, 22 Jan 2015 17:24:40 +0000
treeherdermozilla-inbound@6b087f5cd1e4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1124195
milestone38.0a1
backs out152d407cf4d2cb5fe5bf7e834cf0b0ced04d9a04
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
Backed out changeset 152d407cf4d2 (bug 1124195) for Hazard analysis failures. CLOSED TREE
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;
-      auto intermediate = cx->make_pod_array<char>(arraySize);
+      AutoPtr<char> intermediate(cx->pod_malloc<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);
-      auto intermediate = cx->make_pod_array<char>(structSize);
+      AutoPtr<char> intermediate(cx->pod_malloc<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());
   }
 
-  UniquePtrFFIType result;
+  AutoPtr<ffi_type> 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.release();
+  return result.forget();
 }
 
 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());
 }
 
-UniquePtrFFIType
+ffi_type*
 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.
-  auto ffiType = cx->make_unique<ffi_type>();
+  AutoPtr<ffi_type> ffiType(cx->new_<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 Move(ffiType);
+  return ffiType.forget();
 }
 
 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'.)
-  auto fields = cx->make_unique<FieldInfoHash>();
+  AutoPtr<FieldInfoHash> fields(cx->new_<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,72 +4968,77 @@ 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.release()));
+  JS_SetReservedSlot(typeObj, SLOT_FIELDINFO, PRIVATE_TO_JSVAL(fields.forget()));
 
   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;
 }
 
-UniquePtrFFIType
+ffi_type*
 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);
 
-  auto ffiType = cx->make_unique<ffi_type>();
+  AutoPtr<ffi_type> ffiType(cx->new_<ffi_type>());
   if (!ffiType) {
     JS_ReportOutOfMemory(cx);
     return nullptr;
   }
   ffiType->type = FFI_TYPE_STRUCT;
 
-  size_t count = len != 0 ? len + 1 : 2;
-  auto elements = cx->make_pod_array<ffi_type*>(count);
-  if (!elements) {
-    JS_ReportOutOfMemory(cx);
-    return nullptr;
-  }
-
+  AutoPtr<ffi_type*> elements;
   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.release();
+  ffiType->elements = elements.get();
 
 #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;
@@ -5045,17 +5050,18 @@ 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
 
-  return Move(ffiType);
+  elements.forget();
+  return ffiType.forget();
 }
 
 bool
 StructType::Define(JSContext* cx, unsigned argc, jsval* vp)
 {
   CallArgs args = CallArgsFromVp(argc, vp);
   RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
   if (!obj)
@@ -6079,17 +6085,17 @@ CClosure::Create(JSContext* cx,
   if (!result)
     return nullptr;
 
   // Get the FunctionInfo from the FunctionType.
   FunctionInfo* fninfo = FunctionType::GetFunctionInfo(typeObj);
   MOZ_ASSERT(!fninfo->mIsVariadic);
   MOZ_ASSERT(GetABICode(fninfo->mABI) != ABI_WINAPI);
 
-  auto cinfo = cx->make_unique<ClosureInfo>(JS_GetRuntime(cx));
+  AutoPtr<ClosureInfo> cinfo(cx->new_<ClosureInfo>(JS_GetRuntime(cx)));
   if (!cinfo) {
     JS_ReportOutOfMemory(cx);
     return nullptr;
   }
 
   // Get the prototype of the FunctionType object, of class CTypeProto,
   // which stores our JSContext for use with the closure.
   RootedObject proto(cx);
@@ -6149,17 +6155,17 @@ CClosure::Create(JSContext* cx,
   ffi_status status = ffi_prep_closure_loc(cinfo->closure, &fninfo->mCIF,
     CClosure::ClosureStub, cinfo.get(), code);
   if (status != FFI_OK) {
     JS_ReportError(cx, "couldn't create closure - libffi error");
     return nullptr;
   }
 
   // Stash the ClosureInfo struct on our new object.
-  JS_SetReservedSlot(result, SLOT_CLOSUREINFO, PRIVATE_TO_JSVAL(cinfo.release()));
+  JS_SetReservedSlot(result, SLOT_CLOSUREINFO, PRIVATE_TO_JSVAL(cinfo.forget()));
 
   // Casting between void* and a function pointer is forbidden in C and C++.
   // Do it via an integral type.
   *fnptr = reinterpret_cast<PRFuncPtr>(reinterpret_cast<uintptr_t>(code));
   return result;
 }
 
 void
--- a/js/src/ctypes/CTypes.h
+++ b/js/src/ctypes/CTypes.h
@@ -1,34 +1,65 @@
 /* -*-  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");
 };
 
@@ -436,35 +467,33 @@ 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);
-  UniquePtrFFIType BuildFFIType(JSContext* cx, JSObject* obj);
+  ffi_type* 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);
-  UniquePtrFFIType BuildFFIType(JSContext* cx, JSObject* obj);
+  ffi_type* 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);