Merge b-s to m-c
authorKyle Huey <khuey@kylehuey.com>
Wed, 29 Jun 2011 16:37:41 -0700
changeset 72514 d452aaf438f1ca254bd1cf2a81b8d0375ce1c2da
parent 72510 323029d49c8dbc7d95e8750cf3e8213f088d5eed (current diff)
parent 72513 b2a1b2fd6d234a7fadc7ccf2603975d6a61f918a (diff)
child 72515 98285b0ee9a171051c4a7763bcb6c7ca83243318
push id159
push usereakhgari@mozilla.com
push dateTue, 16 Aug 2011 17:53:11 +0000
treeherdermozilla-beta@8786e3e49240 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone7.0a1
first release with
nightly linux32
d452aaf438f1 / 7.0a1 / 20110630030749 / files
nightly linux64
d452aaf438f1 / 7.0a1 / 20110630030749 / files
nightly mac
d452aaf438f1 / 7.0a1 / 20110630030749 / files
nightly win32
d452aaf438f1 / 7.0a1 / 20110630030749 / files
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
Merge b-s to m-c
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -38,16 +38,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "IDBObjectStore.h"
 
 #include "nsIJSContextStack.h"
 #include "nsIVariant.h"
 
 #include "jscntxt.h"
+#include "jsclone.h"
 #include "mozilla/storage.h"
 #include "nsContentUtils.h"
 #include "nsDOMClassInfo.h"
 #include "nsEventDispatcher.h"
 #include "nsJSUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 
@@ -70,19 +71,20 @@ class AddHelper : public AsyncConnection
 {
 public:
   AddHelper(IDBTransaction* aTransaction,
             IDBRequest* aRequest,
             IDBObjectStore* aObjectStore,
             JSAutoStructuredCloneBuffer& aCloneBuffer,
             const Key& aKey,
             bool aOverwrite,
-            nsTArray<IndexUpdateInfo>& aIndexUpdateInfo)
+            nsTArray<IndexUpdateInfo>& aIndexUpdateInfo,
+            PRUint64 aOffsetToKeyProp)
   : AsyncConnectionHelper(aTransaction, aRequest), mObjectStore(aObjectStore),
-    mKey(aKey), mOverwrite(aOverwrite)
+    mKey(aKey), mOverwrite(aOverwrite), mOffsetToKeyProp(aOffsetToKeyProp)
   {
     mCloneBuffer.swap(aCloneBuffer);
     mIndexUpdateInfo.SwapElements(aIndexUpdateInfo);
   }
 
   ~AddHelper()
   {
     IDBObjectStore::ClearStructuredCloneBuffer(mCloneBuffer);
@@ -106,16 +108,17 @@ private:
   // In-params.
   nsRefPtr<IDBObjectStore> mObjectStore;
 
   // These may change in the autoincrement case.
   JSAutoStructuredCloneBuffer mCloneBuffer;
   Key mKey;
   const bool mOverwrite;
   nsTArray<IndexUpdateInfo> mIndexUpdateInfo;
+  PRUint64 mOffsetToKeyProp;
 };
 
 class GetHelper : public AsyncConnectionHelper
 {
 public:
   GetHelper(IDBTransaction* aTransaction,
             IDBRequest* aRequest,
             IDBObjectStore* aObjectStore,
@@ -418,16 +421,51 @@ already_AddRefed<IDBRequest>
 GenerateRequest(IDBObjectStore* aObjectStore)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   IDBDatabase* database = aObjectStore->Transaction()->Database();
   return IDBRequest::Create(aObjectStore, database->ScriptContext(),
                             database->Owner(), aObjectStore->Transaction());
 }
 
+JSClass gDummyPropClass = {
+  "dummy", 0,
+  JS_PropertyStub,  JS_PropertyStub,
+  JS_PropertyStub,  JS_StrictPropertyStub,
+  JS_EnumerateStub, JS_ResolveStub,
+  JS_ConvertStub, JS_FinalizeStub,
+  JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+JSBool
+StructuredCloneWriteDummyProp(JSContext* aCx,
+                              JSStructuredCloneWriter* aWriter,
+                              JSObject* aObj,
+                              void* aClosure)
+{
+  if (JS_GET_CLASS(aCx, aObj) == &gDummyPropClass) {
+    PRUint64* closure = reinterpret_cast<PRUint64*>(aClosure);
+
+    NS_ASSERTION(*closure == 0, "We should not have been here before!");
+    *closure = js_GetSCOffset(aWriter);
+
+    PRUint64 value = 0;
+    return JS_WriteBytes(aWriter, &value, sizeof(value));
+  }
+
+  // try using the runtime callbacks
+  const JSStructuredCloneCallbacks* runtimeCallbacks =
+    aCx->runtime->structuredCloneCallbacks;
+  if (runtimeCallbacks) {
+    return runtimeCallbacks->write(aCx, aWriter, aObj, nsnull);
+  }
+
+  return JS_FALSE;
+}
+
 } // anonymous namespace
 
 // static
 already_AddRefed<IDBObjectStore>
 IDBObjectStore::Create(IDBTransaction* aTransaction,
                        const ObjectStoreInfo* aStoreInfo)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@@ -835,45 +873,49 @@ IDBObjectStore::ClearStructuredCloneBuff
     }
   }
 }
 
 // static
 bool
 IDBObjectStore::DeserializeValue(JSContext* aCx,
                                  JSAutoStructuredCloneBuffer& aBuffer,
-                                 jsval* aValue)
+                                 jsval* aValue,
+                                 JSStructuredCloneCallbacks* aCallbacks,
+                                 void* aClosure)
 {
   NS_ASSERTION(NS_IsMainThread(),
                "Should only be deserializing on the main thread!");
   NS_ASSERTION(aCx, "A JSContext is required!");
 
   if (!aBuffer.data()) {
     *aValue = JSVAL_VOID;
     return true;
   }
 
   JSAutoRequest ar(aCx);
 
-  return aBuffer.read(aValue, aCx, nsnull);
+  return aBuffer.read(aValue, aCx, aCallbacks, aClosure);
 }
 
 // static
 bool
 IDBObjectStore::SerializeValue(JSContext* aCx,
                                JSAutoStructuredCloneBuffer& aBuffer,
-                               jsval aValue)
+                               jsval aValue,
+                               JSStructuredCloneCallbacks* aCallbacks,
+                               void* aClosure)
 {
   NS_ASSERTION(NS_IsMainThread(),
                "Should only be serializing on the main thread!");
   NS_ASSERTION(aCx, "A JSContext is required!");
 
   JSAutoRequest ar(aCx);
 
-  return aBuffer.write(aCx, aValue, nsnull);
+  return aBuffer.write(aCx, aValue, aCallbacks, aClosure);
 }
 
 static inline jsdouble
 SwapBytes(PRUint64 u)
 {
 #ifdef IS_BIG_ENDIAN
     return ((u & 0x00000000000000ffLLU) << 56) |
            ((u & 0x000000000000ff00LLU) << 40) |
@@ -885,69 +927,55 @@ SwapBytes(PRUint64 u)
            ((u & 0xff00000000000000LLU) >> 56);
 #else
      return u;
 #endif
 }
 
 nsresult
 IDBObjectStore::ModifyValueForNewKey(JSAutoStructuredCloneBuffer& aBuffer,
-                                     Key& aKey)
+                                     Key& aKey,
+                                     PRUint64 aOffsetToKeyProp)
 {
   NS_ASSERTION(IsAutoIncrement() && KeyPath().IsEmpty() && aKey.IsInt(),
                "Don't call me!");
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread");
-  NS_ASSERTION(mKeyPathSerializationOffset, "How did this happen?");
-
-  // The minus 8 dangling off the end here is to account for the null entry
-  // that terminates the buffer
-  const PRUint32 keyPropLen = mKeyPathSerialization.nbytes() -
-                              mKeyPathSerializationOffset - sizeof(PRUint64);
-
-  const char* location = nsCRT::memmem((char*)aBuffer.data(),
-                                       aBuffer.nbytes(),
-                                       (char*)mKeyPathSerialization.data() +
-                                       mKeyPathSerializationOffset,
-                                       keyPropLen);
-  NS_ASSERTION(location, "How did this happen?");
 
   // This is a duplicate of the js engine's byte munging here
   union {
     jsdouble d;
     PRUint64 u;
   } pun;
 
   pun.d = SwapBytes(aKey.IntValue());
 
-  memcpy(const_cast<char*>(location) + keyPropLen -
-         sizeof(pun.u), // We're overwriting the last 8 bytes
-         &pun.u, sizeof(PRUint64));
+  memcpy((char*)aBuffer.data() + aOffsetToKeyProp, &pun.u, sizeof(PRUint64));
   return NS_OK;
 }
 
 IDBObjectStore::IDBObjectStore()
 : mId(LL_MININT),
-  mAutoIncrement(PR_FALSE),
-  mKeyPathSerializationOffset(0)
+  mAutoIncrement(PR_FALSE)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 }
 
 IDBObjectStore::~IDBObjectStore()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 }
 
 nsresult
 IDBObjectStore::GetAddInfo(JSContext* aCx,
                            jsval aValue,
                            jsval aKeyVal,
                            JSAutoStructuredCloneBuffer& aCloneBuffer,
                            Key& aKey,
-                           nsTArray<IndexUpdateInfo>& aUpdateInfoArray)
+                           nsTArray<IndexUpdateInfo>& aUpdateInfoArray,
+                           PRUint64* aOffsetToKeyProp)
 {
   nsresult rv;
 
   // Return DATA_ERR if a key was passed in and this objectStore uses inline
   // keys.
   if (!JSVAL_IS_VOID(aKeyVal) && !mKeyPath.IsEmpty()) {
     return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
   }
@@ -988,33 +1016,41 @@ IDBObjectStore::GetAddInfo(JSContext* aC
   const jschar* keyPathChars =
     reinterpret_cast<const jschar*>(mKeyPath.get());
   const size_t keyPathLen = mKeyPath.Length();
   JSBool ok = JS_FALSE;
 
   if (!mKeyPath.IsEmpty() && aKey.IsUnset()) {
     NS_ASSERTION(mAutoIncrement, "Should have bailed earlier!");
 
-    jsval key;
-    ok = JS_NewNumberValue(aCx, kTotallyRandomNumber, &key);
-    NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+    JSObject* obj = JS_NewObject(aCx, &gDummyPropClass, nsnull, nsnull);
+    NS_ENSURE_TRUE(obj, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
+
+    jsval key = OBJECT_TO_JSVAL(obj);
  
     ok = JS_DefineUCProperty(aCx, JSVAL_TO_OBJECT(aValue), keyPathChars,
                              keyPathLen, key, nsnull, nsnull,
                              JSPROP_ENUMERATE);
     NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
     // From this point on we have to try to remove the property.
-    rv = EnsureKeyPathSerializationData(aCx);
   }
 
+  JSStructuredCloneCallbacks callbacks = {
+    nsnull,
+    StructuredCloneWriteDummyProp,
+    nsnull
+  };
+  *aOffsetToKeyProp = 0;
+
   // We guard on rv being a success because we need to run the property
   // deletion code below even if we should not be serializing the value
   if (NS_SUCCEEDED(rv) && 
-      !IDBObjectStore::SerializeValue(aCx, aCloneBuffer, aValue)) {
+      !IDBObjectStore::SerializeValue(aCx, aCloneBuffer, aValue, &callbacks,
+                                      aOffsetToKeyProp)) {
     rv = NS_ERROR_DOM_DATA_CLONE_ERR;
   }
 
   if (ok) {
     // If this fails, we lose, and the web page sees a magical property
     // appear on the object :-(
     jsval succeeded;
     ok = JS_DeleteUCProperty2(aCx, JSVAL_TO_OBJECT(aValue), keyPathChars,
@@ -1046,81 +1082,43 @@ IDBObjectStore::AddOrPut(const jsval& aV
     return NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR;
   }
 
   jsval keyval = (aOptionalArgCount >= 1) ? aKey : JSVAL_VOID;
 
   JSAutoStructuredCloneBuffer cloneBuffer;
   Key key;
   nsTArray<IndexUpdateInfo> updateInfo;
-
-  nsresult rv = GetAddInfo(aCx, aValue, keyval, cloneBuffer, key, updateInfo);
+  PRUint64 offset;
+
+  nsresult rv =
+    GetAddInfo(aCx, aValue, keyval, cloneBuffer, key, updateInfo, &offset);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   // Put requires a key.
   if (aOverwrite && key.IsUnset()) {
     return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   nsRefPtr<AddHelper> helper =
     new AddHelper(mTransaction, request, this, cloneBuffer, key, aOverwrite,
-                  updateInfo);
+                  updateInfo, offset);
 
   rv = helper->DispatchToTransactionPool();
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   request.forget(_retval);
   return NS_OK;
 }
 
-nsresult
-IDBObjectStore::EnsureKeyPathSerializationData(JSContext* aCx)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread");
-
-  if (!mKeyPathSerializationOffset) {
-    JSBool ok;
-
-    JSAutoStructuredCloneBuffer emptyObjectBuffer;
-    JSAutoStructuredCloneBuffer fakeObjectBuffer;
-
-    const jschar* keyPathChars =
-      reinterpret_cast<const jschar*>(mKeyPath.get());
-    const size_t keyPathLen = mKeyPath.Length();
-
-    JSObject* object = JS_NewObject(aCx, nsnull, nsnull, nsnull);
-    NS_ENSURE_TRUE(object, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
-
-    ok = emptyObjectBuffer.write(aCx, OBJECT_TO_JSVAL(object));
-    NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
-
-    jsval key;
-    // This is just to give us some random marker in the byte stream
-    ok = JS_NewNumberValue(aCx, kTotallyRandomNumber, &key);
-    NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
-
-    ok = JS_DefineUCProperty(aCx, object, keyPathChars, keyPathLen,
-                             key, nsnull, nsnull, JSPROP_ENUMERATE);
-    NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
-
-    ok = fakeObjectBuffer.write(aCx, OBJECT_TO_JSVAL(object));
-    NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
-
-    mKeyPathSerialization.swap(fakeObjectBuffer);
-    mKeyPathSerializationOffset = emptyObjectBuffer.nbytes();
-  }
-
-  return NS_OK;
-}
-
 NS_IMPL_CYCLE_COLLECTION_CLASS(IDBObjectStore)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBObjectStore)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mTransaction,
                                                        nsIDOMEventTarget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOwner)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptContext)
 
@@ -1845,17 +1843,18 @@ AddHelper::DoDatabaseWork(mozIStorageCon
       NS_ASSERTION(mKey.IntValue() == oldKey, "Something went haywire!");
     }
 #endif
 
     if (!keyPath.IsEmpty() && unsetKey) {
       // Special case where someone put an object into an autoIncrement'ing
       // objectStore with no key in its keyPath set. We needed to figure out
       // which row id we would get above before we could set that properly.
-      rv = mObjectStore->ModifyValueForNewKey(mCloneBuffer, mKey);
+      rv = mObjectStore->ModifyValueForNewKey(mCloneBuffer, mKey,
+                                              mOffsetToKeyProp);
       NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
       scoper.Abandon();
       rv = stmt->Reset();
       NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
       stmt = mTransaction->AddStatement(false, true, true);
       NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
--- a/dom/indexedDB/IDBObjectStore.h
+++ b/dom/indexedDB/IDBObjectStore.h
@@ -114,22 +114,26 @@ public:
                                       JSAutoStructuredCloneBuffer& aBuffer);
 
   static void
   ClearStructuredCloneBuffer(JSAutoStructuredCloneBuffer& aBuffer);
 
   static bool
   DeserializeValue(JSContext* aCx,
                    JSAutoStructuredCloneBuffer& aBuffer,
-                   jsval* aValue);
+                   jsval* aValue,
+                   JSStructuredCloneCallbacks* aCallbacks = nsnull,
+                   void* aClosure = nsnull);
 
   static bool
   SerializeValue(JSContext* aCx,
                  JSAutoStructuredCloneBuffer& aBuffer,
-                 jsval aValue);
+                 jsval aValue,
+                 JSStructuredCloneCallbacks* aCallbacks = nsnull,
+                 void* aClosure = nsnull);
 
   const nsString& Name() const
   {
     return mName;
   }
 
   bool IsAutoIncrement() const
   {
@@ -153,55 +157,49 @@ public:
   }
 
   IDBTransaction* Transaction()
   {
     return mTransaction;
   }
 
   nsresult ModifyValueForNewKey(JSAutoStructuredCloneBuffer& aBuffer,
-                                Key& aKey);
+                                Key& aKey,
+                                PRUint64 aOffsetToKeyProp);
 
 protected:
   IDBObjectStore();
   ~IDBObjectStore();
 
   nsresult GetAddInfo(JSContext* aCx,
                       jsval aValue,
                       jsval aKeyVal,
                       JSAutoStructuredCloneBuffer& aCloneBuffer,
                       Key& aKey,
-                      nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
+                      nsTArray<IndexUpdateInfo>& aUpdateInfoArray,
+                      PRUint64* aOffsetToKeyProp);
 
   nsresult AddOrPut(const jsval& aValue,
                     const jsval& aKey,
                     JSContext* aCx,
                     PRUint8 aOptionalArgCount,
                     nsIIDBRequest** _retval,
                     bool aOverwrite);
 
-  nsresult EnsureKeyPathSerializationData(JSContext* aCx);
-
 private:
   nsRefPtr<IDBTransaction> mTransaction;
 
   nsCOMPtr<nsIScriptContext> mScriptContext;
   nsCOMPtr<nsPIDOMWindow> mOwner;
 
   PRInt64 mId;
   nsString mName;
   nsString mKeyPath;
   PRBool mAutoIncrement;
   PRUint32 mDatabaseId;
   PRUint32 mStructuredCloneVersion;
 
-  // Used to store a serialized representation of the fake property
-  // entry used to handle autoincrement with keypaths.
-  JSAutoStructuredCloneBuffer mKeyPathSerialization;
-  PRUint32 mKeyPathSerializationOffset;
-
   nsTArray<nsRefPtr<IDBIndex> > mCreatedIndexes;
-
 };
 
 END_INDEXEDDB_NAMESPACE
 
 #endif // mozilla_dom_indexeddb_idbobjectstore_h__
--- a/js/src/jsclone.cpp
+++ b/js/src/jsclone.cpp
@@ -41,16 +41,23 @@
 #include "jsregexp.h"
 #include "jstypedarray.h"
 
 #include "jsregexpinlines.h"
 #include "jstypedarrayinlines.h"
 
 using namespace js;
 
+JS_FRIEND_API(uint64_t)
+js_GetSCOffset(JSStructuredCloneWriter* writer)
+{
+  JS_ASSERT(writer);
+  return writer->output().count() * sizeof(uint64_t);
+}
+
 namespace js
 {
 
 bool
 WriteStructuredClone(JSContext *cx, const Value &v, uint64 **bufp, size_t *nbytesp,
                      const JSStructuredCloneCallbacks *cb, void *cbClosure)
 {
     SCOutput out(cx);
--- a/js/src/jsclone.h
+++ b/js/src/jsclone.h
@@ -41,16 +41,19 @@
 
 #include "jsapi.h"
 #include "jscntxt.h"
 #include "jshashtable.h"
 #include "jsstdint.h"
 #include "jsvector.h"
 #include "jsvalue.h"
 
+JS_FRIEND_API(uint64_t)
+js_GetSCOffset(JSStructuredCloneWriter* writer);
+
 namespace js {
 
 bool
 WriteStructuredClone(JSContext *cx, const Value &v, uint64_t **bufp, size_t *nbytesp,
                      const JSStructuredCloneCallbacks *cb, void *cbClosure);
 
 bool
 ReadStructuredClone(JSContext *cx, const uint64_t *data, size_t nbytes, Value *vp,
@@ -68,16 +71,18 @@ struct SCOutput {
     bool writeBytes(const void *p, size_t nbytes);
     bool writeChars(const jschar *p, size_t nchars);
 
     template <class T>
     bool writeArray(const T *p, size_t nbytes);
 
     bool extractBuffer(uint64_t **datap, size_t *sizep);
 
+    uint64_t count() { return buf.length(); }
+
   private:
     JSContext *cx;
     js::Vector<uint64_t> buf;
 };
 
 struct SCInput {
   public:
     SCInput(JSContext *cx, const uint64_t *data, size_t nbytes);
--- a/toolkit/mozapps/installer/packager.mk
+++ b/toolkit/mozapps/installer/packager.mk
@@ -802,17 +802,17 @@ UPLOAD_FILES= \
   $(call QUOTED_WILDCARD,$(DIST)/$(PKG_PATH)$(TEST_PACKAGE)) \
   $(call QUOTED_WILDCARD,$(DIST)/$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip) \
   $(call QUOTED_WILDCARD,$(DIST)/$(SDK)) \
   $(call QUOTED_WILDCARD,$(MOZ_SOURCESTAMP_FILE)) \
   $(call QUOTED_WILDCARD,$(PKG_JSSHELL)) \
   $(if $(UPLOAD_EXTRA_FILES), $(foreach f, $(UPLOAD_EXTRA_FILES), $(wildcard $(DIST)/$(f))))
 
 checksum:
-	mkdir -p `dirname $CHECKSUM_FILE`
+	mkdir -p `dirname $(CHECKSUM_FILE)`
 	@$(PYTHON) $(MOZILLA_DIR)/build/checksums.py \
 		-o $(CHECKSUM_FILE) \
 		-d $(CHECKSUM_ALGORITHM) \
 		-s $(call QUOTED_WILDCARD,$(DIST)) \
 		$(UPLOAD_FILES)
 	@echo "CHECKSUM FILE START"
 	@cat $(CHECKSUM_FILE)
 	@echo "CHECKSUM FILE END"