Bug 683802 - Coalesce type-specific cleanup indicators. r=mrbkap
authorBobby Holley <bobbyholley@gmail.com>
Sun, 25 Sep 2011 15:38:01 +0100
changeset 77534 b254267d7599d204186505821b16fa565bad159c
parent 77533 8b2c81d7bd77495382c8e18ca0be321c259dc97e
child 77535 04dc934f61d5b15d53af6f95a9f2430f21de0ed7
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersmrbkap
bugs683802
milestone9.0a1
Bug 683802 - Coalesce type-specific cleanup indicators. r=mrbkap
content/xslt/src/xpath/txXPCOMExtensionFunction.cpp
js/src/xpconnect/src/xpcvariant.cpp
js/src/xpconnect/src/xpcwrappednative.cpp
xpcom/reflect/xptcall/public/xptcall.h
--- a/content/xslt/src/xpath/txXPCOMExtensionFunction.cpp
+++ b/content/xslt/src/xpath/txXPCOMExtensionFunction.cpp
@@ -345,21 +345,26 @@ private:
     PRUint8 mCount;
 };
 
 txParamArrayHolder::~txParamArrayHolder()
 {
     PRUint8 i;
     for (i = 0; i < mCount; ++i) {
         nsXPTCVariant &variant = mArray[i];
-        if (variant.IsValInterface()) {
-            static_cast<nsISupports*>(variant.val.p)->Release();
-        }
-        else if (variant.IsValDOMString()) {
-            delete (nsAString*)variant.val.p;
+        if (variant.DoesValNeedCleanup()) {
+            if (variant.type.TagPart() == nsXPTType::T_DOMSTRING)
+                delete (nsAString*)variant.val.p;
+            else {
+                NS_ABORT_IF_FALSE(variant.type.TagPart() == nsXPTType::T_INTERFACE ||
+                                  variant.type.TagPart() == nsXPTType::T_INTERFACE_IS,
+                                  "We only support cleanup of strings and interfaces "
+                                  "here, and this looks like neither!");
+                static_cast<nsISupports*>(variant.val.p)->Release();
+            }
         }
     }
 }
 
 PRBool
 txParamArrayHolder::Init(PRUint8 aCount)
 {
     mCount = aCount;
@@ -414,17 +419,17 @@ txXPCOMExtensionFunctionCall::evaluate(t
         // Create context wrapper.
         context = new txFunctionEvaluationContext(aContext, mState);
         if (!context) {
             return NS_ERROR_OUT_OF_MEMORY;
         }
 
         nsXPTCVariant &invokeParam = invokeParams[0];
         invokeParam.type = paramInfo.GetType();
-        invokeParam.SetValIsInterface();
+        invokeParam.SetValNeedsCleanup();
         NS_ADDREF((txIFunctionEvaluationContext*&)invokeParam.val.p = context);
 
         // Skip first argument, since it's the context.
         paramStart = 1;
     }
     else {
         context = nsnull;
     }
@@ -462,17 +467,17 @@ txXPCOMExtensionFunctionCall::evaluate(t
                 if (!adaptor) {
                     return NS_ERROR_OUT_OF_MEMORY;
                 }
 
                 nsCOMPtr<txINodeSet> nodeSet = adaptor;
                 rv = adaptor->Init();
                 NS_ENSURE_SUCCESS(rv, rv);
 
-                invokeParam.SetValIsInterface();
+                invokeParam.SetValNeedsCleanup();
                 nodeSet.swap((txINodeSet*&)invokeParam.val.p);
                 break;
             }
             case eBOOLEAN:
             {
                 rv = expr->evaluateToBool(aContext, invokeParam.val.b);
                 NS_ENSURE_SUCCESS(rv, rv);
 
@@ -492,33 +497,33 @@ txXPCOMExtensionFunctionCall::evaluate(t
                 nsString *value = new nsString();
                 if (!value) {
                     return NS_ERROR_OUT_OF_MEMORY;
                 }
 
                 rv = expr->evaluateToString(aContext, *value);
                 NS_ENSURE_SUCCESS(rv, rv);
 
-                invokeParam.SetValIsDOMString();
+                invokeParam.SetValNeedsCleanup();
                 invokeParam.val.p = value;
                 break;
             }
             case eOBJECT:
             {
               nsRefPtr<txAExprResult> exprRes;
               rv = expr->evaluate(aContext, getter_AddRefs(exprRes));
               NS_ENSURE_SUCCESS(rv, rv);
 
               nsCOMPtr<txIXPathObject> adaptor =
                 new txXPathObjectAdaptor(exprRes);
               if (!adaptor) {
                   return NS_ERROR_OUT_OF_MEMORY;
               }
 
-              invokeParam.SetValIsInterface();
+              invokeParam.SetValNeedsCleanup();
               adaptor.swap((txIXPathObject*&)invokeParam.val.p);
               break;
             }
             case eCONTEXT:
             case eUNKNOWN:
             {
                 // We only support passing the context as the *first* argument.
                 return NS_ERROR_FAILURE;
@@ -535,23 +540,23 @@ txXPCOMExtensionFunctionCall::evaluate(t
     nsXPTCVariant &returnParam = invokeParams[inArgs];
     returnParam.type = returnInfo.GetType();
     if (returnType == eSTRING) {
         nsString *value = new nsString();
         if (!value) {
             return NS_ERROR_FAILURE;
         }
 
-        returnParam.SetValIsDOMString();
+        returnParam.SetValNeedsCleanup();
         returnParam.val.p = value;
     }
     else {
         returnParam.SetIndirect();
         if (returnType == eNODESET || returnType == eOBJECT) {
-            returnParam.SetValIsInterface();
+            returnParam.SetValNeedsCleanup();
         }
     }
 
     rv = NS_InvokeByIndex(mHelper, mMethodIndex, paramCount, invokeParams);
 
     // In case someone is holding on to the txFunctionEvaluationContext which
     // could thus stay alive longer than this function.
     if (context) {
--- a/js/src/xpconnect/src/xpcvariant.cpp
+++ b/js/src/xpconnect/src/xpcvariant.cpp
@@ -550,51 +550,51 @@ XPCVariant::VariantDataToJS(XPCLazyCallC
                 return JS_FALSE;
             xpctvar.type = (uint8)(TD_UTF8STRING | XPT_TDP_POINTER);
             xpctvar.val.p = &utf8String;
             break;       
         case nsIDataType::VTYPE_CHAR_STR:       
             if(NS_FAILED(variant->GetAsString((char**)&xpctvar.val.p)))
                 return JS_FALSE;
             xpctvar.type = (uint8)(TD_PSTRING | XPT_TDP_POINTER);
-            xpctvar.SetValIsAllocated();
+            xpctvar.SetValNeedsCleanup();
             break;
         case nsIDataType::VTYPE_STRING_SIZE_IS:
             if(NS_FAILED(variant->GetAsStringWithSize(&size, 
                                                       (char**)&xpctvar.val.p)))
                 return JS_FALSE;
             xpctvar.type = (uint8)(TD_PSTRING_SIZE_IS | XPT_TDP_POINTER);
-            xpctvar.SetValIsAllocated();
+            xpctvar.SetValNeedsCleanup();
             break;
         case nsIDataType::VTYPE_WCHAR_STR:        
             if(NS_FAILED(variant->GetAsWString((PRUnichar**)&xpctvar.val.p)))
                 return JS_FALSE;
             xpctvar.type = (uint8)(TD_PWSTRING | XPT_TDP_POINTER);
-            xpctvar.SetValIsAllocated();
+            xpctvar.SetValNeedsCleanup();
             break;
         case nsIDataType::VTYPE_WSTRING_SIZE_IS:        
             if(NS_FAILED(variant->GetAsWStringWithSize(&size, 
                                                       (PRUnichar**)&xpctvar.val.p)))
                 return JS_FALSE;
             xpctvar.type = (uint8)(TD_PWSTRING_SIZE_IS | XPT_TDP_POINTER);
-            xpctvar.SetValIsAllocated();
+            xpctvar.SetValNeedsCleanup();
             break;
         case nsIDataType::VTYPE_INTERFACE:        
         case nsIDataType::VTYPE_INTERFACE_IS:        
         {
             nsID* piid;
             if(NS_FAILED(variant->GetAsInterface(&piid, &xpctvar.val.p)))
                 return JS_FALSE;
 
             iid = *piid;
             nsMemory::Free((char*)piid);
 
             xpctvar.type = (uint8)(TD_INTERFACE_IS_TYPE | XPT_TDP_POINTER);
             if(xpctvar.val.p)
-                xpctvar.SetValIsInterface();
+                xpctvar.SetValNeedsCleanup();
             break;
         }
         case nsIDataType::VTYPE_ARRAY:
         {
             nsDiscriminatedUnion du;
             nsVariant::Initialize(&du);
             nsresult rv;
 
@@ -705,20 +705,25 @@ VARIANT_DONE:
     else
     {
         success = XPCConvert::NativeData2JS(lccx, pJSVal,
                                             (const void*)&xpctvar.val,
                                             xpctvar.type,
                                             &iid, pErr);
     }
 
-    if(xpctvar.IsValAllocated())
-        nsMemory::Free((char*)xpctvar.val.p);
-    else if(xpctvar.IsValInterface())
-        ((nsISupports*)xpctvar.val.p)->Release();
+    // We may have done something in the above code that requires cleanup.
+    if (xpctvar.DoesValNeedCleanup())
+    {
+        if (type == nsIDataType::VTYPE_INTERFACE ||
+            type == nsIDataType::VTYPE_INTERFACE_IS)
+            ((nsISupports*)xpctvar.val.p)->Release();
+        else
+            nsMemory::Free((char*)xpctvar.val.p);
+    }
 
     return success;
 }
 
 /***************************************************************************/
 /***************************************************************************/
 // XXX These default implementations need to be improved to allow for
 // some more interesting conversions.
--- a/js/src/xpconnect/src/xpcwrappednative.cpp
+++ b/js/src/xpconnect/src/xpcwrappednative.cpp
@@ -2235,16 +2235,18 @@ class CallMethodHelper
     }
 
     JS_ALWAYS_INLINE JSBool InitializeDispatchParams();
 
     JS_ALWAYS_INLINE JSBool ConvertIndependentParams(JSBool* foundDependentParam);
     JS_ALWAYS_INLINE JSBool ConvertIndependentParam(uint8 i);
     JS_ALWAYS_INLINE JSBool ConvertDependentParams();
 
+    JS_ALWAYS_INLINE void CleanupParam(nsXPTCMiniVariant& param, nsXPTType& type);
+
     JS_ALWAYS_INLINE JSBool HandleDipperParam(nsXPTCVariant* dp,
                                               const nsXPTParamInfo& paramInfo);
 
     JS_ALWAYS_INLINE nsresult Invoke();
 
 public:
 
     CallMethodHelper(XPCCallContext& ccx)
@@ -2386,79 +2388,59 @@ CallMethodHelper::Call()
 CallMethodHelper::~CallMethodHelper()
 {
     uint8 paramCount = mMethodInfo->GetParamCount();
     if (mDispatchParams.Length())
     {
         for(uint8 i = 0; i < paramCount; i++)
         {
             nsXPTCVariant* dp = GetDispatchParam(i);
-
-            if(dp->IsValArray())
+            const nsXPTParamInfo& paramInfo = mMethodInfo->GetParam(i);
+
+            if(paramInfo.GetType().IsArray())
             {
                 void* p = dp->val.p;
                 if(!p)
                     continue;
 
-                // going to have to cleanup the array and perhaps its contents
-                if(dp->IsValAllocated() || dp->IsValInterface())
+                // Clean up the array contents if necessary.
+                if(dp->DoesValNeedCleanup())
                 {
-                    // we need to figure out how many elements are present.
+                    // We need some basic information to properly destroy the array.
                     JSUint32 array_count;
-
-                    if(!GetArraySizeFromParam(i, &array_count))
+                    nsXPTType datum_type;
+                    if(!GetArraySizeFromParam(i, &array_count) ||
+                       !NS_SUCCEEDED(mIFaceInfo->GetTypeForParam(mVTableIndex,
+                                                                 &paramInfo,
+                                                                 1, &datum_type)))
                     {
-                        NS_ERROR("failed to get array length, we'll leak here");
+                        // XXXbholley - I'm not convinced that the above calls will
+                        // ever fail.
+                        NS_ERROR("failed to get array information, we'll leak here");
                         continue;
                     }
-                    if(dp->IsValAllocated())
+
+                    // Loop over the array contents. For each one, we create a
+                    // dummy 'val' and pass it to the cleanup helper.
+                    for(JSUint32 k = 0; k < array_count; k++)
                     {
-                        void** a = (void**)p;
-                        for(JSUint32 k = 0; k < array_count; k++)
-                        {
-                            void* o = a[k];
-                            if(o) nsMemory::Free(o);
-                        }
-                    }
-                    else // if(dp->IsValInterface())
-                    {
-                        nsISupports** a = (nsISupports**)p;
-                        for(JSUint32 k = 0; k < array_count; k++)
-                        {
-                            nsISupports* o = a[k];
-                            NS_IF_RELEASE(o);
-                        }
+                        nsXPTCMiniVariant v;
+                        v.val.p = static_cast<void**>(p)[k];
+                        CleanupParam(v, datum_type);
                     }
                 }
+
                 // always free the array itself
                 nsMemory::Free(p);
             }
             else
             {
-                if(dp->IsValJSRoot())
-                {
-                    NS_ASSERTION(!dp->IsValAllocated() && !dp->IsValInterface(),
-                                 "jsvals are their own class of values");
-                    JS_RemoveValueRoot(mCallContext, (jsval*)dp->ptr);
-                    continue;
-                }
-
-                void* p = dp->val.p;
-                if(!p)
-                    continue;
-                if(dp->IsValAllocated())
-                    nsMemory::Free(p);
-                else if(dp->IsValInterface())
-                    ((nsISupports*)p)->Release();
-                else if(dp->IsValDOMString())
-                    mCallContext.DeleteString((nsAString*)p);
-                else if(dp->IsValUTF8String())
-                    delete (nsCString*) p;
-                else if(dp->IsValCString())
-                    delete (nsCString*) p;
+                // Clean up single parameters (if requested).
+                if (dp->DoesValNeedCleanup())
+                    CleanupParam(*dp, dp->type);
             }
         }
     }
 
 }
 
 JSBool
 CallMethodHelper::GetArrayInfoFromParam(uint8 paramIndex, SizeMode mode,
@@ -2831,78 +2813,78 @@ CallMethodHelper::ConvertIndependentPara
         return HandleDipperParam(dp, paramInfo);
 
     // Specify the correct storage/calling semantics.
     if(paramInfo.IsIndirect())
         dp->SetIndirect();
 
     if(type_tag == nsXPTType::T_INTERFACE)
     {
-        dp->SetValIsInterface();
+        dp->SetValNeedsCleanup();
     }
 
     jsval src;
 
     if (!GetOutParamSource(i, &src))
         return JS_FALSE;
 
     // The JSVal proper is always stored within the 'val' union and passed
     // indirectly, regardless of in/out-ness.
     if(type_tag == nsXPTType::T_JSVAL)
     {
         // Root the value.
         dp->val.j = JSVAL_VOID;
         if (!JS_AddValueRoot(mCallContext, &dp->val.j))
             return JS_FALSE;
-        dp->SetValIsJSRoot();
+        dp->SetValNeedsCleanup();
     }
 
     if(paramInfo.IsOut())
     {
         if(type.IsPointer() &&
            type_tag != nsXPTType::T_INTERFACE &&
            !paramInfo.IsShared())
         {
             useAllocator = JS_TRUE;
-            dp->SetValIsAllocated();
+            dp->SetValNeedsCleanup();
         }
 
         if(!paramInfo.IsIn())
             return JS_TRUE;
     }
     else
     {
         if(type.IsPointer())
         {
             switch(type_tag)
             {
             case nsXPTType::T_IID:
-                dp->SetValIsAllocated();
+                dp->SetValNeedsCleanup();
                 useAllocator = JS_TRUE;
                 break;
             case nsXPTType::T_CHAR_STR:
-                dp->SetValIsAllocated();
+                dp->SetValNeedsCleanup();
                 useAllocator = JS_TRUE;
                 break;
             case nsXPTType::T_ASTRING:
                 // Fall through to the T_DOMSTRING case
 
             case nsXPTType::T_DOMSTRING:
 
                 // Is an 'in' DOMString. Set 'useAllocator' to indicate
                 // that JSData2Native should allocate a new
                 // nsAString.
-                dp->SetValIsDOMString();
+                dp->SetValNeedsCleanup();
                 useAllocator = JS_TRUE;
                 break;
 
             case nsXPTType::T_UTF8STRING:
                 // Fall through to the C string case for now...
             case nsXPTType::T_CSTRING:
-                dp->SetValIsCString();
+                dp->SetValNeedsCleanup();
                 useAllocator = JS_TRUE;
                 break;
             }
         }
 
         // Do this *after* the above because in the case where we have a
         // "T_DOMSTRING && IsDipper()" then arg might be null since this
         // is really an 'out' param masquerading as an 'in' param.
@@ -2963,46 +2945,44 @@ CallMethodHelper::ConvertDependentParams
         dp->type = type;
 
         // Specify the correct storage/calling semantics.
         if(paramInfo.IsIndirect())
             dp->SetIndirect();
 
         if(isArray)
         {
-            dp->SetValIsArray();
-
             if(NS_FAILED(mIFaceInfo->GetTypeForParam(mVTableIndex, &paramInfo, 1,
                                                      &datum_type)))
             {
                 Throw(NS_ERROR_XPC_CANT_GET_ARRAY_INFO, mCallContext);
                 return JS_FALSE;
             }
         }
         else
             datum_type = type;
 
         if(datum_type.IsInterfacePointer())
         {
-            dp->SetValIsInterface();
+            dp->SetValNeedsCleanup();
         }
 
         jsval src;
 
         if (!GetOutParamSource(i, &src))
             return JS_FALSE;
 
         if(paramInfo.IsOut())
         {
             if(datum_type.IsPointer() &&
                !datum_type.IsInterfacePointer() &&
                (isArray || !paramInfo.IsShared()))
             {
                 useAllocator = JS_TRUE;
-                dp->SetValIsAllocated();
+                dp->SetValNeedsCleanup();
             }
 
             if(!paramInfo.IsIn())
                 continue;
         }
         else
         {
             NS_ASSERTION(i < mArgc || paramInfo.IsOptional(),
@@ -3010,17 +2990,17 @@ CallMethodHelper::ConvertDependentParams
             src = i < mArgc ? mArgv[i] : JSVAL_NULL;
 
             if((datum_type.IsPointer() &&
                 (datum_type.TagPart() == nsXPTType::T_IID ||
                  datum_type.TagPart() == nsXPTType::T_PSTRING_SIZE_IS)) ||
                (isArray && datum_type.TagPart() == nsXPTType::T_CHAR_STR))
             {
                 useAllocator = JS_TRUE;
-                dp->SetValIsAllocated();
+                dp->SetValNeedsCleanup();
             }
         }
 
         nsID param_iid;
         if(datum_type.IsInterfacePointer() &&
            !GetInterfaceTypeFromParam(i, datum_type, &param_iid))
             return JS_FALSE;
 
@@ -3070,16 +3050,55 @@ CallMethodHelper::ConvertDependentParams
                 return JS_FALSE;
             }
         }
     }
 
     return JS_TRUE;
 }
 
+// Performs all necessary teardown on a parameter after method invocation.
+//
+// This method should only be called if the value in question was flagged
+// for cleanup (ie, if dp->DoesValNeedCleanup()).
+void
+CallMethodHelper::CleanupParam(nsXPTCMiniVariant& param, nsXPTType& type)
+{
+    // We handle array elements, but not the arrays themselves.
+    NS_ABORT_IF_FALSE(type.TagPart() != nsXPTType::T_ARRAY, "Can't handle arrays.");
+
+    // Pointers may sometimes be null even if cleanup was requested. Combine
+    // the null checking for all the different types into one check here.
+    if (type.TagPart() != nsXPTType::T_JSVAL && param.val.p == nsnull)
+        return;
+
+    switch(type.TagPart())
+    {
+        case nsXPTType::T_JSVAL:
+            JS_RemoveValueRoot(mCallContext, (jsval*)&param.val);
+            break;
+        case nsXPTType::T_INTERFACE:
+        case nsXPTType::T_INTERFACE_IS:
+            ((nsISupports*)param.val.p)->Release();
+            break;
+        case nsXPTType::T_ASTRING:
+        case nsXPTType::T_DOMSTRING:
+            mCallContext.DeleteString((nsAString*)param.val.p);
+            break;
+        case nsXPTType::T_UTF8STRING:
+        case nsXPTType::T_CSTRING:
+            delete (nsCString*) param.val.p;
+            break;
+        default:
+            NS_ABORT_IF_FALSE(type.IsPointer(), "Cleanup requested on unexpected type.");
+            nsMemory::Free(param.val.p);
+            break;
+    }
+}
+
 // Handle parameters with dipper types.
 //
 // Dipper types are one of the more inscrutable aspects of xpidl. In a
 // nutshell, dippers are empty container objects, created and passed by
 // the caller, and filled by the callee. The callee receives a
 // fully-formed object, and thus does not have to construct anything. But
 // the object is functionally empty, and the callee is responsible for
 // putting something useful inside of it.
@@ -3112,33 +3131,30 @@ CallMethodHelper::HandleDipperParam(nsXP
                       type_tag == nsXPTType::T_DOMSTRING ||
                       type_tag == nsXPTType::T_UTF8STRING ||
                       type_tag == nsXPTType::T_CSTRING,
                       "Unexpected dipper type!");
 
     // ASTRING and DOMSTRING are very similar, and both use nsAutoString.
     // UTF8_STRING and CSTRING are also quite similar, and both use nsCString.
     if(type_tag == nsXPTType::T_ASTRING || type_tag == nsXPTType::T_DOMSTRING)
-    {
-        dp->SetValIsDOMString();
         dp->val.p = new nsAutoString();
-    }
     else
-    {
-        dp->SetValIsCString();
         dp->val.p = new nsCString();
-    }
 
     // Check for OOM, in either case.
     if(!dp->val.p)
     {
         JS_ReportOutOfMemory(mCallContext);
         return JS_FALSE;
     }
 
+    // We allocated, so we need to deallocate after the method call completes.
+    dp->SetValNeedsCleanup();
+
     return JS_TRUE;
 }
 
 nsresult
 CallMethodHelper::Invoke()
 {
     PRUint32 argc = mDispatchParams.Length();
     nsXPTCVariant* argv = mDispatchParams.Elements();
--- a/xpcom/reflect/xptcall/public/xptcall.h
+++ b/xpcom/reflect/xptcall/public/xptcall.h
@@ -109,43 +109,31 @@ struct nsXPTCVariant : public nsXPTCMini
         // explicitly with SetIndirect() and IsIndirect().
         //
         // Since ptr always points to &val, the semantics of this flag are kind of
         // dumb, since the ptr field is unnecessary. But changing them would
         // require changing dozens of assembly files, so they're likely to stay
         // the way they are.
         PTR_IS_DATA    = 0x1,
 
-        VAL_IS_ALLOCD  = 0x2,  // val.p holds alloc'd ptr that must be freed
-        VAL_IS_IFACE   = 0x4,  // val.p holds interface ptr that must be released
-        VAL_IS_ARRAY   = 0x8,  // val.p holds a pointer to an array needing cleanup
-        VAL_IS_DOMSTR  = 0x10, // val.p holds a pointer to domstring needing cleanup
-        VAL_IS_UTF8STR = 0x20, // val.p holds a pointer to utf8string needing cleanup
-        VAL_IS_CSTR    = 0x40, // val.p holds a pointer to cstring needing cleanup
-        VAL_IS_JSROOT  = 0x80  // val.p holds a pointer to a jsval that must be unrooted
+        // Indicates that the value we hold requires some sort of cleanup (memory
+        // deallocation, interface release, jsval unrooting, etc). The precise
+        // cleanup that is performed depends on the 'type' field above.
+        // If the value is an array, this flag specifies whether the elements
+        // within the array require cleanup (we always clean up the array itself,
+        // so this flag would be redundant for that purpose).
+        VAL_NEEDS_CLEANUP = 0x2
     };
 
     void ClearFlags()         {flags = 0;}
     void SetIndirect()        {ptr = &val; flags |= PTR_IS_DATA;}
-    void SetValIsAllocated()  {flags |= VAL_IS_ALLOCD;}
-    void SetValIsInterface()  {flags |= VAL_IS_IFACE;}
-    void SetValIsArray()      {flags |= VAL_IS_ARRAY;}
-    void SetValIsDOMString()  {flags |= VAL_IS_DOMSTR;}
-    void SetValIsUTF8String() {flags |= VAL_IS_UTF8STR;}
-    void SetValIsCString()    {flags |= VAL_IS_CSTR;}
-    void SetValIsJSRoot()     {flags |= VAL_IS_JSROOT;}
+    void SetValNeedsCleanup() {flags |= VAL_NEEDS_CLEANUP;}
 
-    PRBool IsIndirect()      const  {return 0 != (flags & PTR_IS_DATA);}
-    PRBool IsValAllocated()  const  {return 0 != (flags & VAL_IS_ALLOCD);}
-    PRBool IsValInterface()  const  {return 0 != (flags & VAL_IS_IFACE);}
-    PRBool IsValArray()      const  {return 0 != (flags & VAL_IS_ARRAY);}
-    PRBool IsValDOMString()  const  {return 0 != (flags & VAL_IS_DOMSTR);}
-    PRBool IsValUTF8String() const  {return 0 != (flags & VAL_IS_UTF8STR);}
-    PRBool IsValCString()    const  {return 0 != (flags & VAL_IS_CSTR);}    
-    PRBool IsValJSRoot()     const  {return 0 != (flags & VAL_IS_JSROOT);}
+    PRBool IsIndirect()         const  {return 0 != (flags & PTR_IS_DATA);}
+    PRBool DoesValNeedCleanup() const  {return 0 != (flags & VAL_NEEDS_CLEANUP);}
 
     // Internal use only. Use IsIndirect() instead.
     PRBool IsPtrData()       const  {return 0 != (flags & PTR_IS_DATA);}
 
     void Init(const nsXPTCMiniVariant& mv, const nsXPTType& t, PRUint8 f)
     {
         type = t;
         flags = f;