Bug 1054638 - Move WorkerThread into its own file, r=khuey.

This commit is contained in:
Ben Turner 2014-11-14 18:47:30 -08:00
Родитель 793516eb34
Коммит c8b921018d
5 изменённых файлов: 352 добавлений и 289 удалений

Просмотреть файл

@ -26,6 +26,7 @@
#include "jsfriendapi.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/CycleCollectedJSRuntime.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/dom/asmjscache/AsmJSCache.h"
#include "mozilla/dom/AtomList.h"
#include "mozilla/dom/BindingUtils.h"
@ -45,7 +46,6 @@
#include "nsLayoutStatics.h"
#include "nsNetUtil.h"
#include "nsServiceManagerUtils.h"
#include "nsThread.h"
#include "nsThreadUtils.h"
#include "nsXPCOM.h"
#include "nsXPCOMPrivate.h"
@ -56,15 +56,12 @@
#include "ipc/Nuwa.h"
#endif
#ifdef DEBUG
#include "nsThreadManager.h"
#endif
#include "Principal.h"
#include "ServiceWorker.h"
#include "SharedWorker.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
#include "WorkerThread.h"
#ifdef ENABLE_TESTS
#include "BackgroundChildImpl.h"
@ -90,10 +87,6 @@ using mozilla::Preferences;
// The size of the worker JS allocation threshold in MB. May be changed via pref.
#define WORKER_DEFAULT_ALLOCATION_THRESHOLD 30
// The C stack size. We use the same stack size on all platforms for
// consistency.
#define WORKER_STACK_SIZE 256 * sizeof(size_t) * 1024
// Half the size of the actual C stack, to be safe.
#define WORKER_CONTEXT_NATIVE_STACK_LIMIT 128 * sizeof(size_t) * 1024
@ -907,6 +900,58 @@ private:
WorkerPrivate* mWorkerPrivate;
};
#ifdef ENABLE_TESTS
class TestPBackgroundCreateCallback MOZ_FINAL :
public nsIIPCBackgroundChildCreateCallback
{
public:
NS_DECL_ISUPPORTS
virtual void
ActorCreated(PBackgroundChild* aActor) MOZ_OVERRIDE
{
MOZ_RELEASE_ASSERT(aActor);
}
virtual void
ActorFailed() MOZ_OVERRIDE
{
MOZ_CRASH("TestPBackground() should not fail "
"GetOrCreateForCurrentThread()");
}
private:
~TestPBackgroundCreateCallback()
{ }
};
NS_IMPL_ISUPPORTS(TestPBackgroundCreateCallback,
nsIIPCBackgroundChildCreateCallback);
void
TestPBackground()
{
using namespace mozilla::ipc;
if (gTestPBackground) {
// Randomize value to validate workers are not cross-posting messages.
uint32_t testValue;
size_t randomSize = PR_GetRandomNoise(&testValue, sizeof(testValue));
MOZ_RELEASE_ASSERT(randomSize == sizeof(testValue));
nsCString testStr;
testStr.AppendInt(testValue);
testStr.AppendInt(reinterpret_cast<int64_t>(PR_GetCurrentThread()));
PBackgroundChild* existingBackgroundChild =
BackgroundChild::GetForCurrentThread();
MOZ_RELEASE_ASSERT(existingBackgroundChild);
bool ok = existingBackgroundChild->SendPBackgroundTestConstructor(testStr);
MOZ_RELEASE_ASSERT(ok);
}
}
#endif // ENABLE_TESTS
class WorkerBackgroundChildCallback MOZ_FINAL :
public nsIIPCBackgroundChildCreateCallback
{
@ -942,15 +987,15 @@ private:
class WorkerThreadPrimaryRunnable MOZ_FINAL : public nsRunnable
{
WorkerPrivate* mWorkerPrivate;
nsRefPtr<RuntimeService::WorkerThread> mThread;
nsRefPtr<WorkerThread> mThread;
JSRuntime* mParentRuntime;
class FinishedRunnable MOZ_FINAL : public nsRunnable
{
nsRefPtr<RuntimeService::WorkerThread> mThread;
nsRefPtr<WorkerThread> mThread;
public:
explicit FinishedRunnable(already_AddRefed<RuntimeService::WorkerThread> aThread)
explicit FinishedRunnable(already_AddRefed<WorkerThread> aThread)
: mThread(aThread)
{
MOZ_ASSERT(mThread);
@ -967,7 +1012,7 @@ class WorkerThreadPrimaryRunnable MOZ_FINAL : public nsRunnable
public:
WorkerThreadPrimaryRunnable(WorkerPrivate* aWorkerPrivate,
RuntimeService::WorkerThread* aThread,
WorkerThread* aThread,
JSRuntime* aParentRuntime)
: mWorkerPrivate(aWorkerPrivate), mThread(aThread), mParentRuntime(aParentRuntime)
{
@ -1078,129 +1123,6 @@ PlatformOverrideChanged(const char* /* aPrefName */, void* /* aClosure */)
} /* anonymous namespace */
class RuntimeService::WorkerThread MOZ_FINAL : public nsThread
{
class Observer MOZ_FINAL : public nsIThreadObserver
{
WorkerPrivate* mWorkerPrivate;
public:
explicit Observer(WorkerPrivate* aWorkerPrivate)
: mWorkerPrivate(aWorkerPrivate)
{
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
}
NS_DECL_THREADSAFE_ISUPPORTS
private:
~Observer()
{
mWorkerPrivate->AssertIsOnWorkerThread();
}
NS_DECL_NSITHREADOBSERVER
};
WorkerPrivate* mWorkerPrivate;
nsRefPtr<Observer> mObserver;
#ifdef DEBUG
// Protected by nsThread::mLock.
bool mAcceptingNonWorkerRunnables;
#endif
public:
static already_AddRefed<WorkerThread>
Create();
void
SetWorker(WorkerPrivate* aWorkerPrivate);
NS_DECL_ISUPPORTS_INHERITED
NS_IMETHOD
Dispatch(nsIRunnable* aRunnable, uint32_t aFlags) MOZ_OVERRIDE;
#ifdef DEBUG
bool
IsAcceptingNonWorkerRunnables()
{
MutexAutoLock lock(mLock);
return mAcceptingNonWorkerRunnables;
}
void
SetAcceptingNonWorkerRunnables(bool aAcceptingNonWorkerRunnables)
{
MutexAutoLock lock(mLock);
mAcceptingNonWorkerRunnables = aAcceptingNonWorkerRunnables;
}
#endif
#ifdef ENABLE_TESTS
class TestPBackgroundCreateCallback MOZ_FINAL :
public nsIIPCBackgroundChildCreateCallback
{
public:
virtual void ActorCreated(PBackgroundChild* actor) MOZ_OVERRIDE
{
MOZ_RELEASE_ASSERT(actor);
}
virtual void ActorFailed() MOZ_OVERRIDE
{
MOZ_CRASH("TestPBackground() should not fail GetOrCreateForCurrentThread()");
}
private:
~TestPBackgroundCreateCallback()
{ }
public:
NS_DECL_ISUPPORTS;
};
void
TestPBackground()
{
using namespace mozilla::ipc;
if (gTestPBackground) {
// Randomize value to validate workers are not cross-posting messages.
uint32_t testValue;
size_t randomSize = PR_GetRandomNoise(&testValue, sizeof(testValue));
MOZ_RELEASE_ASSERT(randomSize == sizeof(testValue));
nsCString testStr;
testStr.AppendInt(testValue);
testStr.AppendInt(reinterpret_cast<int64_t>(PR_GetCurrentThread()));
PBackgroundChild* existingBackgroundChild =
BackgroundChild::GetForCurrentThread();
MOZ_RELEASE_ASSERT(existingBackgroundChild);
bool ok = existingBackgroundChild->SendPBackgroundTestConstructor(testStr);
MOZ_RELEASE_ASSERT(ok);
}
}
#endif // #ENABLE_TESTS
private:
WorkerThread()
: nsThread(nsThread::NOT_MAIN_THREAD, WORKER_STACK_SIZE),
mWorkerPrivate(nullptr)
#ifdef DEBUG
, mAcceptingNonWorkerRunnables(true)
#endif
{ }
~WorkerThread()
{ }
};
#ifdef ENABLE_TESTS
NS_IMPL_ISUPPORTS(RuntimeService::WorkerThread::TestPBackgroundCreateCallback,
nsIIPCBackgroundChildCreateCallback);
#endif
BEGIN_WORKERS_NAMESPACE
void
@ -1307,6 +1229,12 @@ GetCurrentThreadJSContext()
END_WORKERS_NAMESPACE
struct RuntimeService::IdleThreadInfo
{
nsRefPtr<WorkerThread> mThread;
mozilla::TimeStamp mExpirationTime;
};
// This is only touched on the main thread. Initialized in Init() below.
JSSettings RuntimeService::sDefaultJSSettings;
bool RuntimeService::sDefaultPreferences[WORKERPREF_COUNT] = { false };
@ -2592,145 +2520,6 @@ RuntimeService::JSVersionChanged(const char* /* aPrefName */, void* /* aClosure
options.setVersion(useLatest ? JSVERSION_LATEST : JSVERSION_DEFAULT);
}
// static
already_AddRefed<RuntimeService::WorkerThread>
RuntimeService::WorkerThread::Create()
{
MOZ_ASSERT(nsThreadManager::get());
nsRefPtr<WorkerThread> thread = new WorkerThread();
if (NS_FAILED(thread->Init())) {
NS_WARNING("Failed to create new thread!");
return nullptr;
}
NS_SetThreadName(thread, "DOM Worker");
return thread.forget();
}
void
RuntimeService::WorkerThread::SetWorker(WorkerPrivate* aWorkerPrivate)
{
MOZ_ASSERT(PR_GetCurrentThread() == mThread);
MOZ_ASSERT_IF(aWorkerPrivate, !mWorkerPrivate);
MOZ_ASSERT_IF(!aWorkerPrivate, mWorkerPrivate);
// No need to lock here because mWorkerPrivate is only modified on mThread.
if (mWorkerPrivate) {
MOZ_ASSERT(mObserver);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(RemoveObserver(mObserver)));
mObserver = nullptr;
mWorkerPrivate->SetThread(nullptr);
}
mWorkerPrivate = aWorkerPrivate;
if (mWorkerPrivate) {
mWorkerPrivate->SetThread(this);
nsRefPtr<Observer> observer = new Observer(mWorkerPrivate);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(AddObserver(observer)));
mObserver.swap(observer);
}
}
NS_IMPL_ISUPPORTS_INHERITED0(RuntimeService::WorkerThread, nsThread)
NS_IMETHODIMP
RuntimeService::WorkerThread::Dispatch(nsIRunnable* aRunnable, uint32_t aFlags)
{
// May be called on any thread!
#ifdef DEBUG
if (PR_GetCurrentThread() == mThread) {
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
}
else if (aRunnable && !IsAcceptingNonWorkerRunnables()) {
// Only enforce cancelable runnables after we've started the worker loop.
nsCOMPtr<nsICancelableRunnable> cancelable = do_QueryInterface(aRunnable);
MOZ_ASSERT(cancelable,
"Should have been wrapped by the worker's event target!");
}
#endif
// Workers only support asynchronous dispatch for now.
if (NS_WARN_IF(aFlags != NS_DISPATCH_NORMAL)) {
return NS_ERROR_UNEXPECTED;
}
nsIRunnable* runnableToDispatch;
nsRefPtr<WorkerRunnable> workerRunnable;
if (aRunnable && PR_GetCurrentThread() == mThread) {
// No need to lock here because mWorkerPrivate is only modified on mThread.
workerRunnable = mWorkerPrivate->MaybeWrapAsWorkerRunnable(aRunnable);
runnableToDispatch = workerRunnable;
}
else {
runnableToDispatch = aRunnable;
}
nsresult rv = nsThread::Dispatch(runnableToDispatch, NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
NS_IMPL_ISUPPORTS(RuntimeService::WorkerThread::Observer, nsIThreadObserver)
NS_IMETHODIMP
RuntimeService::WorkerThread::Observer::OnDispatchedEvent(
nsIThreadInternal* /*aThread */)
{
MOZ_CRASH("OnDispatchedEvent() should never be called!");
}
NS_IMETHODIMP
RuntimeService::WorkerThread::Observer::OnProcessNextEvent(
nsIThreadInternal* /* aThread */,
bool aMayWait,
uint32_t aRecursionDepth)
{
using mozilla::ipc::BackgroundChild;
mWorkerPrivate->AssertIsOnWorkerThread();
// If the PBackground child is not created yet, then we must permit
// blocking event processing to support SynchronouslyCreatePBackground().
// If this occurs then we are spinning on the event queue at the start of
// PrimaryWorkerRunnable::Run() and don't want to process the event in
// mWorkerPrivate yet.
if (aMayWait) {
MOZ_ASSERT(aRecursionDepth == 2);
MOZ_ASSERT(!BackgroundChild::GetForCurrentThread());
return NS_OK;
}
mWorkerPrivate->OnProcessNextEvent(aRecursionDepth);
return NS_OK;
}
NS_IMETHODIMP
RuntimeService::WorkerThread::Observer::AfterProcessNextEvent(
nsIThreadInternal* /* aThread */,
uint32_t aRecursionDepth,
bool /* aEventWasProcessed */)
{
mWorkerPrivate->AssertIsOnWorkerThread();
mWorkerPrivate->AfterProcessNextEvent(aRecursionDepth);
return NS_OK;
}
NS_IMPL_ISUPPORTS_INHERITED0(LogViolationDetailsRunnable, nsRunnable)
NS_IMETHODIMP
@ -2796,7 +2585,7 @@ WorkerThreadPrimaryRunnable::Run()
mThread->SetWorker(mWorkerPrivate);
#ifdef ENABLE_TESTS
mThread->TestPBackground();
TestPBackground();
#endif
mWorkerPrivate->AssertIsOnWorkerThread();
@ -2831,7 +2620,7 @@ WorkerThreadPrimaryRunnable::Run()
}
#ifdef ENABLE_TESTS
mThread->TestPBackground();
TestPBackground();
#endif
BackgroundChild::CloseForCurrentThread();
@ -2914,7 +2703,7 @@ WorkerThreadPrimaryRunnable::FinishedRunnable::Run()
{
AssertIsOnMainThread();
nsRefPtr<RuntimeService::WorkerThread> thread;
nsRefPtr<WorkerThread> thread;
mThread.swap(thread);
RuntimeService* rts = RuntimeService::GetService();

Просмотреть файл

@ -12,7 +12,6 @@
#include "nsIObserver.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "nsClassHashtable.h"
#include "nsHashKeys.h"
@ -20,7 +19,6 @@
#include "WorkerPrivate.h"
class nsIRunnable;
class nsIThread;
class nsITimer;
class nsPIDOMWindow;
@ -28,13 +26,10 @@ BEGIN_WORKERS_NAMESPACE
class ServiceWorker;
class SharedWorker;
class WorkerThread;
class RuntimeService MOZ_FINAL : public nsIObserver
{
public:
class WorkerThread;
private:
struct SharedWorkerInfo
{
WorkerPrivate* mWorkerPrivate;
@ -67,11 +62,7 @@ private:
}
};
struct IdleThreadInfo
{
nsRefPtr<WorkerThread> mThread;
mozilla::TimeStamp mExpirationTime;
};
struct IdleThreadInfo;
struct MatchSharedWorkerInfo
{

Просмотреть файл

@ -0,0 +1,206 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
#include "WorkerThread.h"
#include "mozilla/Assertions.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "nsIThreadInternal.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
#ifdef DEBUG
#include "nsThreadManager.h"
#endif
namespace mozilla {
namespace dom {
namespace workers {
using namespace mozilla::ipc;
namespace {
// The C stack size. We use the same stack size on all platforms for
// consistency.
const uint32_t kWorkerStackSize = 256 * sizeof(size_t) * 1024;
} // anonymous namespace
class WorkerThread::Observer MOZ_FINAL
: public nsIThreadObserver
{
WorkerPrivate* mWorkerPrivate;
public:
explicit Observer(WorkerPrivate* aWorkerPrivate)
: mWorkerPrivate(aWorkerPrivate)
{
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
}
NS_DECL_THREADSAFE_ISUPPORTS
private:
~Observer()
{
mWorkerPrivate->AssertIsOnWorkerThread();
}
NS_DECL_NSITHREADOBSERVER
};
WorkerThread::WorkerThread()
: nsThread(nsThread::NOT_MAIN_THREAD, kWorkerStackSize),
mWorkerPrivate(nullptr)
#ifdef DEBUG
, mAcceptingNonWorkerRunnables(true)
#endif
{
}
WorkerThread::~WorkerThread()
{
}
// static
already_AddRefed<WorkerThread>
WorkerThread::Create()
{
MOZ_ASSERT(nsThreadManager::get());
nsRefPtr<WorkerThread> thread = new WorkerThread();
if (NS_FAILED(thread->Init())) {
NS_WARNING("Failed to create new thread!");
return nullptr;
}
NS_SetThreadName(thread, "DOM Worker");
return thread.forget();
}
void
WorkerThread::SetWorker(WorkerPrivate* aWorkerPrivate)
{
MOZ_ASSERT(PR_GetCurrentThread() == mThread);
MOZ_ASSERT_IF(aWorkerPrivate, !mWorkerPrivate);
MOZ_ASSERT_IF(!aWorkerPrivate, mWorkerPrivate);
// No need to lock here because mWorkerPrivate is only modified on mThread.
if (mWorkerPrivate) {
MOZ_ASSERT(mObserver);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(RemoveObserver(mObserver)));
mObserver = nullptr;
mWorkerPrivate->SetThread(nullptr);
}
mWorkerPrivate = aWorkerPrivate;
if (mWorkerPrivate) {
mWorkerPrivate->SetThread(this);
nsRefPtr<Observer> observer = new Observer(mWorkerPrivate);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(AddObserver(observer)));
mObserver.swap(observer);
}
}
NS_IMPL_ISUPPORTS_INHERITED0(WorkerThread, nsThread)
NS_IMETHODIMP
WorkerThread::Dispatch(nsIRunnable* aRunnable, uint32_t aFlags)
{
// May be called on any thread!
#ifdef DEBUG
if (PR_GetCurrentThread() == mThread) {
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
}
else if (aRunnable && !IsAcceptingNonWorkerRunnables()) {
// Only enforce cancelable runnables after we've started the worker loop.
nsCOMPtr<nsICancelableRunnable> cancelable = do_QueryInterface(aRunnable);
MOZ_ASSERT(cancelable,
"Should have been wrapped by the worker's event target!");
}
#endif
// Workers only support asynchronous dispatch for now.
if (NS_WARN_IF(aFlags != NS_DISPATCH_NORMAL)) {
return NS_ERROR_UNEXPECTED;
}
nsIRunnable* runnableToDispatch;
nsRefPtr<WorkerRunnable> workerRunnable;
if (aRunnable && PR_GetCurrentThread() == mThread) {
// No need to lock here because mWorkerPrivate is only modified on mThread.
workerRunnable = mWorkerPrivate->MaybeWrapAsWorkerRunnable(aRunnable);
runnableToDispatch = workerRunnable;
}
else {
runnableToDispatch = aRunnable;
}
nsresult rv = nsThread::Dispatch(runnableToDispatch, NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
NS_IMPL_ISUPPORTS(WorkerThread::Observer, nsIThreadObserver)
NS_IMETHODIMP
WorkerThread::Observer::OnDispatchedEvent(nsIThreadInternal* /* aThread */)
{
MOZ_CRASH("OnDispatchedEvent() should never be called!");
}
NS_IMETHODIMP
WorkerThread::Observer::OnProcessNextEvent(nsIThreadInternal* /* aThread */,
bool aMayWait,
uint32_t aRecursionDepth)
{
mWorkerPrivate->AssertIsOnWorkerThread();
// If the PBackground child is not created yet, then we must permit
// blocking event processing to support SynchronouslyCreatePBackground().
// If this occurs then we are spinning on the event queue at the start of
// PrimaryWorkerRunnable::Run() and don't want to process the event in
// mWorkerPrivate yet.
if (aMayWait) {
MOZ_ASSERT(aRecursionDepth == 2);
MOZ_ASSERT(!BackgroundChild::GetForCurrentThread());
return NS_OK;
}
mWorkerPrivate->OnProcessNextEvent(aRecursionDepth);
return NS_OK;
}
NS_IMETHODIMP
WorkerThread::Observer::AfterProcessNextEvent(nsIThreadInternal* /* aThread */,
uint32_t aRecursionDepth,
bool /* aEventWasProcessed */)
{
mWorkerPrivate->AssertIsOnWorkerThread();
mWorkerPrivate->AfterProcessNextEvent(aRecursionDepth);
return NS_OK;
}
} // namespace workers
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,76 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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 mozilla_dom_workers_WorkerThread_h__
#define mozilla_dom_workers_WorkerThread_h__
#include "mozilla/Attributes.h"
#include "mozilla/DebugOnly.h"
#include "nsISupportsImpl.h"
#include "nsRefPtr.h"
#include "nsThread.h"
class nsIRunnable;
namespace mozilla {
namespace dom {
namespace workers {
class WorkerPrivate;
class WorkerRunnable;
class WorkerThread MOZ_FINAL
: public nsThread
{
class Observer;
WorkerPrivate* mWorkerPrivate;
nsRefPtr<Observer> mObserver;
#ifdef DEBUG
// Protected by nsThread::mLock.
bool mAcceptingNonWorkerRunnables;
#endif
public:
static already_AddRefed<WorkerThread>
Create();
void
SetWorker(WorkerPrivate* aWorkerPrivate);
NS_DECL_ISUPPORTS_INHERITED
NS_IMETHOD
Dispatch(nsIRunnable* aRunnable, uint32_t aFlags) MOZ_OVERRIDE;
#ifdef DEBUG
bool
IsAcceptingNonWorkerRunnables()
{
MutexAutoLock lock(mLock);
return mAcceptingNonWorkerRunnables;
}
void
SetAcceptingNonWorkerRunnables(bool aAcceptingNonWorkerRunnables)
{
MutexAutoLock lock(mLock);
mAcceptingNonWorkerRunnables = aAcceptingNonWorkerRunnables;
}
#endif
private:
WorkerThread();
~WorkerThread();
};
} // namespace workers
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_workers_WorkerThread_h__

Просмотреть файл

@ -72,6 +72,7 @@ UNIFIED_SOURCES += [
'WorkerPrivate.cpp',
'WorkerRunnable.cpp',
'WorkerScope.cpp',
'WorkerThread.cpp',
'XMLHttpRequest.cpp',
'XMLHttpRequestUpload.cpp',
]