diff options
author | Antoine Brodin <antoine@FreeBSD.org> | 2021-01-01 10:11:34 +0000 |
---|---|---|
committer | Antoine Brodin <antoine@FreeBSD.org> | 2021-01-01 10:11:34 +0000 |
commit | 26b4c8f71f91d22e081b27814782686edde0c90a (patch) | |
tree | 1c321c39372c25d8634e75b5c8e08edc676b296d /lang/spidermonkey185 | |
parent | 548f16bd1a2915f08878b716eed92ff3267e6de2 (diff) | |
download | ports-26b4c8f71f91d22e081b27814782686edde0c90a.tar.gz ports-26b4c8f71f91d22e081b27814782686edde0c90a.zip |
Revert r559792 to unbreak INDEX and bulk -a
It seems a lot of reverse dependencies were missed
With hat: portmgr
Notes
Notes:
svn path=/head/; revision=559822
Diffstat (limited to 'lang/spidermonkey185')
-rw-r--r-- | lang/spidermonkey185/Makefile | 127 | ||||
-rw-r--r-- | lang/spidermonkey185/distinfo | 2 | ||||
-rw-r--r-- | lang/spidermonkey185/files/patch-assembler_jit_ExecutableAllocator.h | 14 | ||||
-rw-r--r-- | lang/spidermonkey185/files/patch-assembler_wtf_Platform.h | 18 | ||||
-rw-r--r-- | lang/spidermonkey185/files/patch-bug771281 | 1839 | ||||
-rw-r--r-- | lang/spidermonkey185/files/patch-c++11 | 247 | ||||
-rw-r--r-- | lang/spidermonkey185/files/patch-configure.in | 36 | ||||
-rw-r--r-- | lang/spidermonkey185/files/patch-jsscript.h | 48 | ||||
-rw-r--r-- | lang/spidermonkey185/files/patch-jsstr.cpp | 36 | ||||
-rw-r--r-- | lang/spidermonkey185/files/patch-nanojit_CodeAlloc.cpp | 10 | ||||
-rw-r--r-- | lang/spidermonkey185/files/patch-nanojit_njcpudetect.h | 11 | ||||
-rw-r--r-- | lang/spidermonkey185/pkg-descr | 3 | ||||
-rw-r--r-- | lang/spidermonkey185/pkg-plist | 106 |
13 files changed, 2497 insertions, 0 deletions
diff --git a/lang/spidermonkey185/Makefile b/lang/spidermonkey185/Makefile new file mode 100644 index 000000000000..263096f3e96d --- /dev/null +++ b/lang/spidermonkey185/Makefile @@ -0,0 +1,127 @@ +# Created by: Kubilay Kocak <koobs@FreeBSD.org> +# $FreeBSD$ + +PORTNAME= spidermonkey185 +PORTVERSION= 1.8.5 +PORTREVISION= 5 +CATEGORIES= lang +MASTER_SITES= MOZILLA/js +DISTNAME= js185-1.0.0 + +MAINTAINER= koobs@FreeBSD.org +COMMENT= Standalone JavaScript (1.8.5) interpreter from Mozilla + +BUILD_DEPENDS= zip:archivers/zip \ + autoconf-2.13:devel/autoconf213 +LIB_DEPENDS= libnspr4.so:devel/nspr + +USES= gmake pathfix perl5 pkgconfig python:2.7,build +GNU_CONFIGURE= yes +USE_LDCONFIG= yes +USE_PERL5= build + +WRKSRC= ${WRKDIR}/js-${PORTVERSION}/js/src + +BROKEN_aarch64= Does not compile: error: cacheFlush support is missing on this platform +BROKEN_mips64= Does not compile: error: const union jsval_layout has no member named word +BROKEN_sparc64= Does not build: fails to link + +NOT_FOR_ARCHS= powerpc powerpc64 +NOT_FOR_ARCHS_REASON= PowerPC is not supported + +CONFIGURE_ARGS= --with-pthreads \ + --with-system-nspr + +# This comes from bsd.gecko.mk, fixes linking issues on 9.0 and higher. +post-configure: + ${ECHO_CMD} "fenv.h" >> ${WRKSRC}/config/system-headers + ${ECHO_CMD} "pthread_np.h" >> ${WRKSRC}/config/system-headers + +OPTIONS_DEFINE= DEBUG GCZEAL JEMALLOC METHODJIT OPTIMIZE READLINE \ + THREADSAFE TRACEJIT UTF8 \ + +OPTIONS_DEFAULT= METHODJIT OPTIMIZE READLINE THREADSAFE TRACEJIT + +GCZEAL_DESC= Enable Zealous garbage collecting +JEMALLOC_DESC= Use jemalloc as memory allocator +METHODJIT_DESC= Enable method JIT support +OPTIMIZE_DESC= Enable compiler optimizations +READLINE_DESC= Link js shell to system readline library +THREADSAFE_DESC= Enable multiple thread support +TRACEJIT_DESC= Enable tracing JIT support +UTF8_DESC= Treat strings as UTF8 instead of ISO-8859-1 + +DEBUG_CONFIGURE_ENABLE= debug +DEBUG_CONFIGURE_ON= --enable-debug-sumbols +GCZEAL_CONFIGURE_ENABLE= gczeal +JEMALLOC_CONFIGURE_ENABLE= jemalloc +METHODJIT_CONFIGURE_ENABLE= methodjit +OPTIMIZE_CONFIGURE_ENABLE= optimize +READLINE_CONFIGURE_ENABLE= readline +READLINE_USES= readline +THREADSAFE_CONFIGURE_ENABLE= threadsafe +TRACEJIT_CONFIGURE_ENABLE= tracejit +UTF8_CFLAGS= -DJS_C_STRINGS_ARE_UTF8 + +.include <bsd.port.options.mk> + +.if ${ARCH} == amd64 +CONFIGURE_TARGET= x86_64-portbld-freebsd${OSREL} +.endif + +.if ${ARCH} == "amd64" +PLIST_SUB+= AMD64="" +.else +PLIST_SUB+= AMD64="@comment " +.endif + +.if ${ARCH} == "i386" +PLIST_SUB+= I386="" +.else +PLIST_SUB+= I386="@comment " +.endif + +.if ${ARCH} == "arm" +PLIST_SUB+= ARM="" +.else +PLIST_SUB+= ARM="@comment " +.endif + +.if ${ARCH} == "mips" +PLIST_SUB+= MIPS="" +.else +PLIST_SUB+= MIPS="@comment " +.endif + +.if ${ARCH} == "powerpc" || ${ARCH} == "powerpc64" +PLIST_SUB+= PPC="" +.else +PLIST_SUB+= PPC="@comment " +.endif + +.if ${ARCH} == "sparc64" +PLIST_SUB+= SPARC="" +.else +PLIST_SUB+= SPARC="@comment " +.endif + +pre-configure: + (cd ${WRKSRC} && ${LOCALBASE}/bin/autoconf-2.13) + +do-test: + @${ECHO_MSG} -n "===> Running jstests.py: " + @cd ${WRKSRC} && ${SETENV} TZ=PST8PDT ${PYTHON_CMD} tests/jstests.py \ + --no-progress --worker-count=${MAKE_JOBS_NUMBER} ./js +.if ${PORT_OPTIONS:MMETHODJIT} || ${PORT_OPTIONS:MTRACEJIT} + @${ECHO_MSG} -n "===> Running jit_test.py: " + @cd ${WRKSRC} && ${SETENV} TZ=PST8PDT ${PYTHON_CMD} jit-test/jit_test.py \ + --no-progress --jitflags=,m,j,mj,mjp,am,amj,amjp,amd ./js +.endif + +post-install: + ${LN} -sf libmozjs185.so.1.0.0 ${STAGEDIR}${PREFIX}/lib/libmozjs185.so + ${LN} -sf libmozjs185.so.1.0.0 ${STAGEDIR}${PREFIX}/lib/libmozjs185.so.1 + ${LN} -sf libmozjs185.so.1.0.0 ${STAGEDIR}${PREFIX}/lib/libmozjs185.so.1.0 + @${STRIP_CMD} ${STAGEDIR}${PREFIX}/lib/libmozjs185.so.1.0.0 + +.include <bsd.port.mk> diff --git a/lang/spidermonkey185/distinfo b/lang/spidermonkey185/distinfo new file mode 100644 index 000000000000..ac820e9f43a3 --- /dev/null +++ b/lang/spidermonkey185/distinfo @@ -0,0 +1,2 @@ +SHA256 (js185-1.0.0.tar.gz) = 5d12f7e1f5b4a99436685d97b9b7b75f094d33580227aa998c406bbae6f2a687 +SIZE (js185-1.0.0.tar.gz) = 6164605 diff --git a/lang/spidermonkey185/files/patch-assembler_jit_ExecutableAllocator.h b/lang/spidermonkey185/files/patch-assembler_jit_ExecutableAllocator.h new file mode 100644 index 000000000000..94770e435051 --- /dev/null +++ b/lang/spidermonkey185/files/patch-assembler_jit_ExecutableAllocator.h @@ -0,0 +1,14 @@ +--- assembler/jit/ExecutableAllocator.h.orig 2016-09-07 UTC ++++ assembler/jit/ExecutableAllocator.h +@@ -391,6 +391,11 @@ public: + { + CacheRangeFlush(code, size, CACHE_SYNC_ALL); + } ++#elif WTF_CPU_ARM_TRADITIONAL && WTF_PLATFORM_FREEBSD ++ static void cacheFlush(void* code, size_t size) ++ { ++ __clear_cache(code, reinterpret_cast<char*>(code) + size); ++ } + #else + #error "The cacheFlush support is missing on this platform." + #endif diff --git a/lang/spidermonkey185/files/patch-assembler_wtf_Platform.h b/lang/spidermonkey185/files/patch-assembler_wtf_Platform.h new file mode 100644 index 000000000000..9556c0f7e638 --- /dev/null +++ b/lang/spidermonkey185/files/patch-assembler_wtf_Platform.h @@ -0,0 +1,18 @@ +--- ./assembler/wtf/Platform.h.orig 2016-09-07 UTC ++++ ./assembler/wtf/Platform.h +@@ -213,6 +213,7 @@ + #elif defined(__ARM_ARCH_6__) \ + || defined(__ARM_ARCH_6J__) \ + || defined(__ARM_ARCH_6K__) \ ++ || defined(__ARM_ARCH_6KZ__) \ + || defined(__ARM_ARCH_6Z__) \ + || defined(__ARM_ARCH_6ZK__) \ + || defined(__ARM_ARCH_6T2__) \ +@@ -243,6 +244,7 @@ + + #elif defined(__ARM_ARCH_6J__) \ + || defined(__ARM_ARCH_6K__) \ ++ || defined(__ARM_ARCH_6KZ__) \ + || defined(__ARM_ARCH_6Z__) \ + || defined(__ARM_ARCH_6ZK__) \ + || defined(__ARM_ARCH_6M__) diff --git a/lang/spidermonkey185/files/patch-bug771281 b/lang/spidermonkey185/files/patch-bug771281 new file mode 100644 index 000000000000..1b59e5dfeafb --- /dev/null +++ b/lang/spidermonkey185/files/patch-bug771281 @@ -0,0 +1,1839 @@ +diff -ruN src/shell/Makefile.in src.new/shell/Makefile.in +--- shell/Makefile.in 2011-04-01 06:08:36.000000000 +1100 ++++ shell/Makefile.in 2013-03-23 22:01:26.876752286 +1100 +@@ -47,7 +47,6 @@ + PROGRAM = js$(BIN_SUFFIX) + CPPSRCS = \ + js.cpp \ +- jsworkers.cpp \ + $(NULL) + + DEFINES += -DEXPORT_JS_API +diff -ruN src/shell/js.cpp src.new/shell/js.cpp +--- shell/js.cpp 2011-04-01 06:08:36.000000000 +1100 ++++ shell/js.cpp 2013-03-23 22:02:46.436700725 +1100 +@@ -91,8 +91,6 @@ + #endif /* JSDEBUGGER_C_UI */ + #endif /* JSDEBUGGER */ + +-#include "jsworkers.h" +- + #include "jsinterpinlines.h" + #include "jsobjinlines.h" + #include "jsscriptinlines.h" +@@ -194,10 +192,6 @@ + JSBool gQuitting = JS_FALSE; + FILE *gErrFile = NULL; + FILE *gOutFile = NULL; +-#ifdef JS_THREADSAFE +-JSObject *gWorkers = NULL; +-js::workers::ThreadPool *gWorkerThreadPool = NULL; +-#endif + + static JSBool reportWarnings = JS_TRUE; + static JSBool compileOnly = JS_FALSE; +@@ -1315,10 +1309,6 @@ + JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "/ i", &gExitCode); + + gQuitting = JS_TRUE; +-#ifdef JS_THREADSAFE +- if (gWorkerThreadPool) +- js::workers::terminateAll(JS_GetRuntime(cx), gWorkerThreadPool); +-#endif + return JS_FALSE; + } + +@@ -4150,10 +4140,6 @@ + gCanceled = true; + if (gExitCode == 0) + gExitCode = EXITCODE_TIMEOUT; +-#ifdef JS_THREADSAFE +- if (gWorkerThreadPool) +- js::workers::terminateAll(rt, gWorkerThreadPool); +-#endif + JS_TriggerAllOperationCallbacks(rt); + + static const char msg[] = "Script runs for too long, terminating.\n"; +@@ -5681,29 +5667,8 @@ + #endif /* JSDEBUGGER_C_UI */ + #endif /* JSDEBUGGER */ + +-#ifdef JS_THREADSAFE +- class ShellWorkerHooks : public js::workers::WorkerHooks { +- public: +- JSObject *newGlobalObject(JSContext *cx) { +- return NewGlobalObject(cx, NEW_COMPARTMENT); +- } +- }; +- ShellWorkerHooks hooks; +- if (!JS_AddNamedObjectRoot(cx, &gWorkers, "Workers") || +- (gWorkerThreadPool = js::workers::init(cx, &hooks, glob, &gWorkers)) == NULL) { +- return 1; +- } +-#endif +- + int result = ProcessArgs(cx, glob, argv, argc); + +-#ifdef JS_THREADSAFE +- js::workers::finish(cx, gWorkerThreadPool); +- JS_RemoveObjectRoot(cx, &gWorkers); +- if (result == 0) +- result = gExitCode; +-#endif +- + #ifdef JSDEBUGGER + if (jsdc) { + #ifdef JSDEBUGGER_C_UI +diff -ruN src/shell/jsworkers.cpp src.new/shell/jsworkers.cpp +--- shell/jsworkers.cpp 2011-04-01 06:08:36.000000000 +1100 ++++ shell/jsworkers.cpp 1970-01-01 10:00:00.000000000 +1000 +@@ -1,1280 +0,0 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- +- * vim: set ts=8 sw=4 et tw=99: +- * +- * ***** BEGIN LICENSE BLOCK ***** +- * Version: MPL 1.1/GPL 2.0/LGPL 2.1 +- * +- * The contents of this file are subject to the Mozilla Public License Version +- * 1.1 (the "License"); you may not use this file except in compliance with +- * the License. You may obtain a copy of the License at +- * http://www.mozilla.org/MPL/ +- * +- * Software distributed under the License is distributed on an "AS IS" basis, +- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +- * for the specific language governing rights and limitations under the +- * License. +- * +- * The Original Code is JavaScript shell workers. +- * +- * The Initial Developer of the Original Code is +- * Mozilla Corporation. +- * Portions created by the Initial Developer are Copyright (C) 2010 +- * the Initial Developer. All Rights Reserved. +- * +- * Contributor(s): +- * Jason Orendorff <jorendorff@mozilla.com> +- * +- * Alternatively, the contents of this file may be used under the terms of +- * either of the GNU General Public License Version 2 or later (the "GPL"), +- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +- * in which case the provisions of the GPL or the LGPL are applicable instead +- * of those above. If you wish to allow use of your version of this file only +- * under the terms of either the GPL or the LGPL, and not to allow others to +- * use your version of this file under the terms of the MPL, indicate your +- * decision by deleting the provisions above and replace them with the notice +- * and other provisions required by the GPL or the LGPL. If you do not delete +- * the provisions above, a recipient may use your version of this file under +- * the terms of any one of the MPL, the GPL or the LGPL. +- * +- * ***** END LICENSE BLOCK ***** */ +- +-#ifdef JS_THREADSAFE +- +-#include <algorithm> +-#include <string.h> +-#include "prthread.h" +-#include "prlock.h" +-#include "prcvar.h" +-#include "jsapi.h" +-#include "jscntxt.h" +-#include "jshashtable.h" +-#include "jsstdint.h" +-#include "jslock.h" +-#include "jsvector.h" +-#include "jsworkers.h" +- +-extern size_t gMaxStackSize; +- +-/* +- * JavaScript shell workers. +- * +- * == Object lifetime rules == +- * +- * - The ThreadPool lasts from init() to finish(). +- * +- * - The ThreadPool owns the MainQueue and the WorkerQueue. Those live from +- * the time the first Worker is created until finish(). +- * +- * - Each JS Worker object has the same lifetime as the corresponding C++ +- * Worker object. A Worker is live if (a) the Worker JSObject is still +- * live; (b) the Worker has an incoming event pending or running; (c) it +- * has sent an outgoing event to its parent that is still pending; or (d) +- * it has any live child Workers. +- * +- * - finish() continues to wait for events until all threads are idle. +- * +- * Event objects, however, are basically C++-only. The JS Event objects are +- * just plain old JSObjects. They don't keep anything alive. +- * +- * == Locking scheme == +- * +- * When mixing mutexes and the JSAPI request model, there are two choices: +- * +- * - Always nest the mutexes in requests. Since threads in requests are not +- * supposed to block, this means the mutexes must be only briefly held. +- * +- * - Never nest the mutexes in requests. Since this allows threads to race +- * with the GC, trace() methods must go through the mutexes just like +- * everyone else. +- * +- * This code uses the latter approach for all locks. +- * +- * In one case, a thread holding a Worker's mutex can acquire the mutex of one +- * of its child Workers. See Worker::terminateSelf. (This can't deadlock because +- * the parent-child relationship is a partial order.) +- */ +- +-namespace js { +-namespace workers { +- +-template <class T, class AllocPolicy> +-class Queue { +- private: +- typedef Vector<T, 4, AllocPolicy> Vec; +- Vec v1; +- Vec v2; +- Vec *front; +- Vec *back; +- +- // Queue is not copyable. +- Queue(const Queue &); +- Queue & operator=(const Queue &); +- +- public: +- Queue() : front(&v1), back(&v2) {} +- bool push(T t) { return back->append(t); } +- bool empty() { return front->empty() && back->empty(); } +- +- T pop() { +- if (front->empty()) { +- std::reverse(back->begin(), back->end()); +- Vec *tmp = front; +- front = back; +- back = tmp; +- } +- T item = front->back(); +- front->popBack(); +- return item; +- } +- +- void clear() { +- v1.clear(); +- v2.clear(); +- } +- +- void trace(JSTracer *trc) { +- for (T *p = v1.begin(); p != v1.end(); p++) +- (*p)->trace(trc); +- for (T *p = v2.begin(); p != v2.end(); p++) +- (*p)->trace(trc); +- } +-}; +- +-class Event; +-class ThreadPool; +-class Worker; +- +-class WorkerParent { +- protected: +- typedef HashSet<Worker *, DefaultHasher<Worker *>, SystemAllocPolicy> ChildSet; +- ChildSet children; +- +- bool initWorkerParent() { return children.init(8); } +- +- public: +- virtual JSLock *getLock() = 0; +- virtual ThreadPool *getThreadPool() = 0; +- virtual bool post(Event *item) = 0; // false on OOM or queue closed +- virtual void trace(JSTracer *trc) = 0; +- +- bool addChild(Worker *w) { +- AutoLock hold(getLock()); +- return children.put(w) != NULL; +- } +- +- // This must be called only from GC or when all threads are shut down. It +- // does not bother with locking. +- void removeChild(Worker *w) { +- ChildSet::Ptr p = children.lookup(w); +- JS_ASSERT(p); +- children.remove(p); +- } +- +- void disposeChildren(); +-}; +- +-template <class T> +-class ThreadSafeQueue +-{ +- protected: +- Queue<T, SystemAllocPolicy> queue; +- JSLock *lock; +- PRCondVar *condvar; +- bool closed; +- +- private: +- Vector<T, 8, SystemAllocPolicy> busy; +- +- protected: +- ThreadSafeQueue() : lock(NULL), condvar(NULL), closed(false) {} +- +- ~ThreadSafeQueue() { +- if (condvar) +- JS_DESTROY_CONDVAR(condvar); +- if (lock) +- JS_DESTROY_LOCK(lock); +- } +- +- // Called by take() with the lock held. +- virtual bool shouldStop() { return closed; } +- +- public: +- bool initThreadSafeQueue() { +- JS_ASSERT(!lock); +- JS_ASSERT(!condvar); +- return (lock = JS_NEW_LOCK()) && (condvar = JS_NEW_CONDVAR(lock)); +- } +- +- bool post(T t) { +- AutoLock hold(lock); +- if (closed) +- return false; +- if (queue.empty()) +- JS_NOTIFY_ALL_CONDVAR(condvar); +- return queue.push(t); +- } +- +- void close() { +- AutoLock hold(lock); +- closed = true; +- queue.clear(); +- JS_NOTIFY_ALL_CONDVAR(condvar); +- } +- +- // The caller must hold the lock. +- bool take(T *t) { +- while (queue.empty()) { +- if (shouldStop()) +- return false; +- JS_WAIT_CONDVAR(condvar, JS_NO_TIMEOUT); +- } +- *t = queue.pop(); +- busy.append(*t); +- return true; +- } +- +- // The caller must hold the lock. +- void drop(T item) { +- for (T *p = busy.begin(); p != busy.end(); p++) { +- if (*p == item) { +- *p = busy.back(); +- busy.popBack(); +- return; +- } +- } +- JS_NOT_REACHED("removeBusy"); +- } +- +- bool lockedIsIdle() { return busy.empty() && queue.empty(); } +- +- bool isIdle() { +- AutoLock hold(lock); +- return lockedIsIdle(); +- } +- +- void wake() { +- AutoLock hold(lock); +- JS_NOTIFY_ALL_CONDVAR(condvar); +- } +- +- void trace(JSTracer *trc) { +- AutoLock hold(lock); +- for (T *p = busy.begin(); p != busy.end(); p++) +- (*p)->trace(trc); +- queue.trace(trc); +- } +-}; +- +-class MainQueue; +- +-class Event +-{ +- protected: +- virtual ~Event() { JS_ASSERT(!data); } +- +- WorkerParent *recipient; +- Worker *child; +- uint64 *data; +- size_t nbytes; +- +- public: +- enum Result { fail = JS_FALSE, ok = JS_TRUE, forwardToParent }; +- +- virtual void destroy(JSContext *cx) { +- JS_free(cx, data); +-#ifdef DEBUG +- data = NULL; +-#endif +- delete this; +- } +- +- void setChildAndRecipient(Worker *aChild, WorkerParent *aRecipient) { +- child = aChild; +- recipient = aRecipient; +- } +- +- bool deserializeData(JSContext *cx, jsval *vp) { +- return !!JS_ReadStructuredClone(cx, data, nbytes, JS_STRUCTURED_CLONE_VERSION, vp, +- NULL, NULL); +- } +- +- virtual Result process(JSContext *cx) = 0; +- +- inline void trace(JSTracer *trc); +- +- template <class EventType> +- static EventType *createEvent(JSContext *cx, WorkerParent *recipient, Worker *child, +- jsval v) +- { +- uint64 *data; +- size_t nbytes; +- if (!JS_WriteStructuredClone(cx, v, &data, &nbytes, NULL, NULL)) +- return NULL; +- +- EventType *event = new EventType; +- if (!event) { +- JS_ReportOutOfMemory(cx); +- return NULL; +- } +- event->recipient = recipient; +- event->child = child; +- event->data = data; +- event->nbytes = nbytes; +- return event; +- } +- +- Result dispatch(JSContext *cx, JSObject *thisobj, const char *dataPropName, +- const char *methodName, Result noHandler) +- { +- if (!data) +- return fail; +- +- JSBool found; +- if (!JS_HasProperty(cx, thisobj, methodName, &found)) +- return fail; +- if (!found) +- return noHandler; +- +- // Create event object. +- jsval v; +- if (!deserializeData(cx, &v)) +- return fail; +- JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL); +- if (!obj || !JS_DefineProperty(cx, obj, dataPropName, v, NULL, NULL, 0)) +- return fail; +- +- // Call event handler. +- jsval argv[1] = { OBJECT_TO_JSVAL(obj) }; +- jsval rval = JSVAL_VOID; +- return Result(JS_CallFunctionName(cx, thisobj, methodName, 1, argv, &rval)); +- } +-}; +- +-typedef ThreadSafeQueue<Event *> EventQueue; +- +-class MainQueue : public EventQueue, public WorkerParent +-{ +- private: +- ThreadPool *threadPool; +- +- public: +- explicit MainQueue(ThreadPool *tp) : threadPool(tp) {} +- +- ~MainQueue() { +- JS_ASSERT(queue.empty()); +- } +- +- bool init() { return initThreadSafeQueue() && initWorkerParent(); } +- +- void destroy(JSContext *cx) { +- while (!queue.empty()) +- queue.pop()->destroy(cx); +- delete this; +- } +- +- virtual JSLock *getLock() { return lock; } +- virtual ThreadPool *getThreadPool() { return threadPool; } +- +- protected: +- virtual bool shouldStop(); +- +- public: +- virtual bool post(Event *event) { return EventQueue::post(event); } +- +- virtual void trace(JSTracer *trc); +- +- void traceChildren(JSTracer *trc) { EventQueue::trace(trc); } +- +- JSBool mainThreadWork(JSContext *cx, bool continueOnError) { +- JSAutoSuspendRequest suspend(cx); +- AutoLock hold(lock); +- +- Event *event; +- while (take(&event)) { +- JS_RELEASE_LOCK(lock); +- Event::Result result; +- { +- JSAutoRequest req(cx); +- result = event->process(cx); +- if (result == Event::forwardToParent) { +- // FIXME - pointlessly truncates the string to 8 bits +- jsval data; +- JSAutoByteString bytes; +- if (event->deserializeData(cx, &data) && +- JSVAL_IS_STRING(data) && +- bytes.encode(cx, JSVAL_TO_STRING(data))) { +- JS_ReportError(cx, "%s", bytes.ptr()); +- } else { +- JS_ReportOutOfMemory(cx); +- } +- result = Event::fail; +- } +- if (result == Event::fail && continueOnError) { +- if (JS_IsExceptionPending(cx) && !JS_ReportPendingException(cx)) +- JS_ClearPendingException(cx); +- result = Event::ok; +- } +- } +- JS_ACQUIRE_LOCK(lock); +- drop(event); +- event->destroy(cx); +- if (result != Event::ok) +- return false; +- } +- return true; +- } +-}; +- +-/* +- * A queue of workers. +- * +- * We keep a queue of workers with pending events, rather than a queue of +- * events, so that two threads won't try to run a Worker at the same time. +- */ +-class WorkerQueue : public ThreadSafeQueue<Worker *> +-{ +- private: +- MainQueue *main; +- +- public: +- explicit WorkerQueue(MainQueue *main) : main(main) {} +- +- void work(); +-}; +- +-/* The top-level object that owns everything else. */ +-class ThreadPool +-{ +- private: +- enum { threadCount = 6 }; +- +- JSObject *obj; +- WorkerHooks *hooks; +- MainQueue *mq; +- WorkerQueue *wq; +- PRThread *threads[threadCount]; +- int32_t terminating; +- +- static JSClass jsClass; +- +- static void start(void* arg) { +- ((WorkerQueue *) arg)->work(); +- } +- +- explicit ThreadPool(WorkerHooks *hooks) : hooks(hooks), mq(NULL), wq(NULL), terminating(0) { +- for (int i = 0; i < threadCount; i++) +- threads[i] = NULL; +- } +- +- public: +- ~ThreadPool() { +- JS_ASSERT(!mq); +- JS_ASSERT(!wq); +- JS_ASSERT(!threads[0]); +- } +- +- static ThreadPool *create(JSContext *cx, WorkerHooks *hooks) { +- ThreadPool *tp = new ThreadPool(hooks); +- if (!tp) { +- JS_ReportOutOfMemory(cx); +- return NULL; +- } +- +- JSObject *obj = JS_NewObject(cx, &jsClass, NULL, NULL); +- if (!obj || !JS_SetPrivate(cx, obj, tp)) { +- delete tp; +- return NULL; +- } +- tp->obj = obj; +- return tp; +- } +- +- JSObject *asObject() { return obj; } +- WorkerHooks *getHooks() { return hooks; } +- WorkerQueue *getWorkerQueue() { return wq; } +- MainQueue *getMainQueue() { return mq; } +- bool isTerminating() { return terminating != 0; } +- +- /* +- * Main thread only. Requires request (to prevent GC, which could see the +- * object in an inconsistent state). +- */ +- bool start(JSContext *cx) { +- JS_ASSERT(!mq && !wq); +- mq = new MainQueue(this); +- if (!mq || !mq->init()) { +- mq->destroy(cx); +- mq = NULL; +- return false; +- } +- wq = new WorkerQueue(mq); +- if (!wq || !wq->initThreadSafeQueue()) { +- delete wq; +- wq = NULL; +- mq->destroy(cx); +- mq = NULL; +- return false; +- } +- JSAutoSuspendRequest suspend(cx); +- bool ok = true; +- for (int i = 0; i < threadCount; i++) { +- threads[i] = PR_CreateThread(PR_USER_THREAD, start, wq, PR_PRIORITY_NORMAL, +- PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); +- if (!threads[i]) { +- shutdown(cx); +- ok = false; +- break; +- } +- } +- return ok; +- } +- +- void terminateAll(JSRuntime *rt) { +- // See comment about JS_ATOMIC_SET in the implementation of +- // JS_TriggerOperationCallback. +- JS_ATOMIC_SET(&terminating, 1); +- JS_TriggerAllOperationCallbacks(rt); +- } +- +- /* This context is used only to free memory. */ +- void shutdown(JSContext *cx) { +- wq->close(); +- for (int i = 0; i < threadCount; i++) { +- if (threads[i]) { +- PR_JoinThread(threads[i]); +- threads[i] = NULL; +- } +- } +- +- delete wq; +- wq = NULL; +- +- mq->disposeChildren(); +- mq->destroy(cx); +- mq = NULL; +- terminating = 0; +- } +- +- private: +- static void jsTraceThreadPool(JSTracer *trc, JSObject *obj) { +- ThreadPool *tp = unwrap(trc->context, obj); +- if (tp->mq) { +- tp->mq->traceChildren(trc); +- tp->wq->trace(trc); +- } +- } +- +- +- static void jsFinalize(JSContext *cx, JSObject *obj) { +- if (ThreadPool *tp = unwrap(cx, obj)) +- delete tp; +- } +- +- public: +- static ThreadPool *unwrap(JSContext *cx, JSObject *obj) { +- JS_ASSERT(JS_GET_CLASS(cx, obj) == &jsClass); +- return (ThreadPool *) JS_GetPrivate(cx, obj); +- } +-}; +- +-/* +- * A Worker is always in one of 4 states, except when it is being initialized +- * or destroyed, or its lock is held: +- * - idle (!terminated && current == NULL && events.empty()) +- * - enqueued (!terminated && current == NULL && !events.empty()) +- * - busy (!terminated && current != NULL) +- * - terminated (terminated && current == NULL && events.empty()) +- * +- * Separately, there is a terminateFlag that other threads can set +- * asynchronously to tell the Worker to terminate. +- */ +-class Worker : public WorkerParent +-{ +- private: +- ThreadPool *threadPool; +- WorkerParent *parent; +- JSObject *object; // Worker object exposed to parent +- JSContext *context; +- JSLock *lock; +- Queue<Event *, SystemAllocPolicy> events; // owning pointers to pending events +- Event *current; +- bool terminated; +- int32_t terminateFlag; +- +- static JSClass jsWorkerClass; +- +- Worker() +- : threadPool(NULL), parent(NULL), object(NULL), +- context(NULL), lock(NULL), current(NULL), terminated(false), terminateFlag(0) {} +- +- bool init(JSContext *parentcx, WorkerParent *parent, JSObject *obj) { +- JS_ASSERT(!threadPool && !this->parent && !object && !lock); +- +- if (!initWorkerParent() || !parent->addChild(this)) +- return false; +- threadPool = parent->getThreadPool(); +- this->parent = parent; +- this->object = obj; +- lock = JS_NEW_LOCK(); +- return lock && +- createContext(parentcx, parent) && +- JS_SetPrivate(parentcx, obj, this); +- } +- +- bool createContext(JSContext *parentcx, WorkerParent *parent) { +- JSRuntime *rt = JS_GetRuntime(parentcx); +- context = JS_NewContext(rt, 8192); +- if (!context) +- return false; +- +- // The Worker has a strong reference to the global; see jsTraceWorker. +- // JSOPTION_UNROOTED_GLOBAL ensures that when the worker becomes +- // unreachable, it and its global object can be collected. Otherwise +- // the cx->globalObject root would keep them both alive forever. +- JS_SetOptions(context, JS_GetOptions(parentcx) | JSOPTION_UNROOTED_GLOBAL | +- JSOPTION_DONT_REPORT_UNCAUGHT); +- JS_SetVersion(context, JS_GetVersion(parentcx)); +- JS_SetContextPrivate(context, this); +- JS_SetOperationCallback(context, jsOperationCallback); +- JS_BeginRequest(context); +- +- JSObject *global = threadPool->getHooks()->newGlobalObject(context); +- JSObject *post, *proto, *ctor; +- if (!global) +- goto bad; +- JS_SetGlobalObject(context, global); +- +- // Because the Worker is completely isolated from the rest of the +- // runtime, and because any pending events on a Worker keep the Worker +- // alive, this postMessage function cannot be called after the Worker +- // is collected. Therefore it's safe to stash a pointer (a weak +- // reference) to the C++ Worker object in the reserved slot. +- post = JS_GetFunctionObject(JS_DefineFunction(context, global, "postMessage", +- (JSNative) jsPostMessageToParent, 1, 0)); +- if (!post || !JS_SetReservedSlot(context, post, 0, PRIVATE_TO_JSVAL(this))) +- goto bad; +- +- proto = JS_InitClass(context, global, NULL, &jsWorkerClass, jsConstruct, 1, +- NULL, jsMethods, NULL, NULL); +- if (!proto) +- goto bad; +- +- ctor = JS_GetConstructor(context, proto); +- if (!ctor || !JS_SetReservedSlot(context, ctor, 0, PRIVATE_TO_JSVAL(this))) +- goto bad; +- +- JS_EndRequest(context); +- JS_ClearContextThread(context); +- return true; +- +- bad: +- JS_EndRequest(context); +- JS_DestroyContext(context); +- context = NULL; +- return false; +- } +- +- static void jsTraceWorker(JSTracer *trc, JSObject *obj) { +- JS_ASSERT(JS_GET_CLASS(trc->context, obj) == &jsWorkerClass); +- if (Worker *w = (Worker *) JS_GetPrivate(trc->context, obj)) { +- w->parent->trace(trc); +- w->events.trace(trc); +- if (w->current) +- w->current->trace(trc); +- JS_CALL_OBJECT_TRACER(trc, JS_GetGlobalObject(w->context), "Worker global"); +- } +- } +- +- static void jsFinalize(JSContext *cx, JSObject *obj) { +- JS_ASSERT(JS_GET_CLASS(cx, obj) == &jsWorkerClass); +- if (Worker *w = (Worker *) JS_GetPrivate(cx, obj)) +- delete w; +- } +- +- static JSBool jsOperationCallback(JSContext *cx) { +- Worker *w = (Worker *) JS_GetContextPrivate(cx); +- JSAutoSuspendRequest suspend(cx); // avoid nesting w->lock in a request +- return !w->checkTermination(); +- } +- +- static JSBool jsResolveGlobal(JSContext *cx, JSObject *obj, jsid id, uintN flags, +- JSObject **objp) +- { +- JSBool resolved; +- +- if (!JS_ResolveStandardClass(cx, obj, id, &resolved)) +- return false; +- if (resolved) +- *objp = obj; +- +- return true; +- } +- +- static JSBool jsPostMessageToParent(JSContext *cx, uintN argc, jsval *vp); +- static JSBool jsPostMessageToChild(JSContext *cx, uintN argc, jsval *vp); +- static JSBool jsTerminate(JSContext *cx, uintN argc, jsval *vp); +- +- bool checkTermination() { +- AutoLock hold(lock); +- return lockedCheckTermination(); +- } +- +- bool lockedCheckTermination() { +- if (terminateFlag || threadPool->isTerminating()) { +- terminateSelf(); +- terminateFlag = 0; +- } +- return terminated; +- } +- +- // Caller must hold the lock. +- void terminateSelf() { +- terminated = true; +- while (!events.empty()) +- events.pop()->destroy(context); +- +- // Tell the children to shut down too. An arbitrarily silly amount of +- // processing could happen before the whole tree is terminated; but +- // this way we don't have to worry about blowing the C stack. +- for (ChildSet::Enum e(children); !e.empty(); e.popFront()) +- e.front()->setTerminateFlag(); // note: nesting locks here +- } +- +- public: +- ~Worker() { +- if (parent) +- parent->removeChild(this); +- dispose(); +- } +- +- void dispose() { +- JS_ASSERT(!current); +- while (!events.empty()) +- events.pop()->destroy(context); +- if (lock) { +- JS_DESTROY_LOCK(lock); +- lock = NULL; +- } +- if (context) { +- JS_SetContextThread(context); +- JS_DestroyContextNoGC(context); +- context = NULL; +- } +- object = NULL; +- +- // Do not call parent->removeChild(). This is called either from +- // ~Worker, which calls it for us; or from parent->disposeChildren or +- // Worker::create, which require that it not be called. +- parent = NULL; +- disposeChildren(); +- } +- +- static Worker *create(JSContext *parentcx, WorkerParent *parent, +- JSString *scriptName, JSObject *obj); +- +- JSObject *asObject() { return object; } +- +- JSObject *getGlobal() { return JS_GetGlobalObject(context); } +- +- WorkerParent *getParent() { return parent; } +- +- virtual JSLock *getLock() { return lock; } +- +- virtual ThreadPool *getThreadPool() { return threadPool; } +- +- bool post(Event *event) { +- AutoLock hold(lock); +- if (terminated) +- return false; +- if (!current && events.empty() && !threadPool->getWorkerQueue()->post(this)) +- return false; +- return events.push(event); +- } +- +- void setTerminateFlag() { +- AutoLock hold(lock); +- terminateFlag = true; +- if (current) +- JS_TriggerOperationCallback(context); +- } +- +- void processOneEvent(); +- +- /* Trace method to be called from C++. */ +- void trace(JSTracer *trc) { +- // Just mark the JSObject. If we haven't already been marked, +- // jsTraceWorker will be called, at which point we'll trace referents. +- JS_CALL_OBJECT_TRACER(trc, object, "queued Worker"); +- } +- +- static bool getWorkerParentFromConstructor(JSContext *cx, JSObject *ctor, WorkerParent **p) { +- jsval v; +- if (!JS_GetReservedSlot(cx, ctor, 0, &v)) +- return false; +- if (JSVAL_IS_VOID(v)) { +- // This means ctor is the root Worker constructor (created in +- // Worker::initWorkers as opposed to Worker::createContext, which sets up +- // Worker sandboxes) and nothing is initialized yet. +- if (!JS_GetReservedSlot(cx, ctor, 1, &v)) +- return false; +- ThreadPool *threadPool = (ThreadPool *) JSVAL_TO_PRIVATE(v); +- if (!threadPool->start(cx)) +- return false; +- WorkerParent *parent = threadPool->getMainQueue(); +- if (!JS_SetReservedSlot(cx, ctor, 0, PRIVATE_TO_JSVAL(parent))) { +- threadPool->shutdown(cx); +- return false; +- } +- *p = parent; +- return true; +- } +- *p = (WorkerParent *) JSVAL_TO_PRIVATE(v); +- return true; +- } +- +- static JSBool jsConstruct(JSContext *cx, uintN argc, jsval *vp) { +- WorkerParent *parent; +- if (!getWorkerParentFromConstructor(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)), &parent)) +- return false; +- +- +- JSString *scriptName = JS_ValueToString(cx, argc ? JS_ARGV(cx, vp)[0] : JSVAL_VOID); +- if (!scriptName) +- return false; +- +- JSObject *obj = JS_NewObject(cx, &jsWorkerClass, NULL, NULL); +- if (!obj || !create(cx, parent, scriptName, obj)) +- return false; +- JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj)); +- return true; +- } +- +- static JSFunctionSpec jsMethods[3]; +- static JSFunctionSpec jsStaticMethod[2]; +- +- static ThreadPool *initWorkers(JSContext *cx, WorkerHooks *hooks, JSObject *global, +- JSObject **objp) { +- // Create the ThreadPool object and its JSObject wrapper. +- ThreadPool *threadPool = ThreadPool::create(cx, hooks); +- if (!threadPool) +- return NULL; +- +- // Root the ThreadPool JSObject early. +- *objp = threadPool->asObject(); +- +- // Create the Worker constructor. +- JSObject *proto = JS_InitClass(cx, global, NULL, &jsWorkerClass, +- jsConstruct, 1, +- NULL, jsMethods, NULL, NULL); +- if (!proto) +- return NULL; +- +- // Stash a pointer to the ThreadPool in constructor reserved slot 1. +- // It will be used later when lazily creating the MainQueue. +- JSObject *ctor = JS_GetConstructor(cx, proto); +- if (!JS_SetReservedSlot(cx, ctor, 1, PRIVATE_TO_JSVAL(threadPool))) +- return NULL; +- +- return threadPool; +- } +-}; +- +-class InitEvent : public Event +-{ +- public: +- static InitEvent *create(JSContext *cx, Worker *worker, JSString *scriptName) { +- return createEvent<InitEvent>(cx, worker, worker, STRING_TO_JSVAL(scriptName)); +- } +- +- Result process(JSContext *cx) { +- jsval s; +- if (!deserializeData(cx, &s)) +- return fail; +- JS_ASSERT(JSVAL_IS_STRING(s)); +- JSAutoByteString filename(cx, JSVAL_TO_STRING(s)); +- if (!filename) +- return fail; +- +- JSObject *scriptObj = JS_CompileFile(cx, child->getGlobal(), filename.ptr()); +- if (!scriptObj) +- return fail; +- +- AutoValueRooter rval(cx); +- JSBool ok = JS_ExecuteScript(cx, child->getGlobal(), scriptObj, Jsvalify(rval.addr())); +- return Result(ok); +- } +-}; +- +-class DownMessageEvent : public Event +-{ +- public: +- static DownMessageEvent *create(JSContext *cx, Worker *child, jsval data) { +- return createEvent<DownMessageEvent>(cx, child, child, data); +- } +- +- Result process(JSContext *cx) { +- return dispatch(cx, child->getGlobal(), "data", "onmessage", ok); +- } +-}; +- +-class UpMessageEvent : public Event +-{ +- public: +- static UpMessageEvent *create(JSContext *cx, Worker *child, jsval data) { +- return createEvent<UpMessageEvent>(cx, child->getParent(), child, data); +- } +- +- Result process(JSContext *cx) { +- return dispatch(cx, child->asObject(), "data", "onmessage", ok); +- } +-}; +- +-class ErrorEvent : public Event +-{ +- public: +- static ErrorEvent *create(JSContext *cx, Worker *child) { +- JSString *data = NULL; +- jsval exc; +- if (JS_GetPendingException(cx, &exc)) { +- AutoValueRooter tvr(cx, Valueify(exc)); +- JS_ClearPendingException(cx); +- +- // Determine what error message to put in the error event. +- // If exc.message is a string, use that; otherwise use String(exc). +- // (This is a little different from what web workers do.) +- if (JSVAL_IS_OBJECT(exc)) { +- jsval msg; +- if (!JS_GetProperty(cx, JSVAL_TO_OBJECT(exc), "message", &msg)) +- JS_ClearPendingException(cx); +- else if (JSVAL_IS_STRING(msg)) +- data = JSVAL_TO_STRING(msg); +- } +- if (!data) { +- data = JS_ValueToString(cx, exc); +- if (!data) +- return NULL; +- } +- } +- return createEvent<ErrorEvent>(cx, child->getParent(), child, +- data ? STRING_TO_JSVAL(data) : JSVAL_VOID); +- } +- +- Result process(JSContext *cx) { +- return dispatch(cx, child->asObject(), "message", "onerror", forwardToParent); +- } +-}; +- +-} /* namespace workers */ +-} /* namespace js */ +- +-using namespace js::workers; +- +-void +-WorkerParent::disposeChildren() +-{ +- for (ChildSet::Enum e(children); !e.empty(); e.popFront()) { +- e.front()->dispose(); +- e.removeFront(); +- } +-} +- +-bool +-MainQueue::shouldStop() +-{ +- // Note: This deliberately nests WorkerQueue::lock in MainQueue::lock. +- // Releasing MainQueue::lock would risk a race -- isIdle() could return +- // false, but the workers could become idle before we reacquire +- // MainQueue::lock and go to sleep, and we would wait on the condvar +- // forever. +- return closed || threadPool->getWorkerQueue()->isIdle(); +-} +- +-void +-MainQueue::trace(JSTracer *trc) +-{ +- JS_CALL_OBJECT_TRACER(trc, threadPool->asObject(), "MainQueue"); +-} +- +-void +-WorkerQueue::work() { +- AutoLock hold(lock); +- +- Worker *w; +- while (take(&w)) { // can block outside the mutex +- JS_RELEASE_LOCK(lock); +- w->processOneEvent(); // enters request on w->context +- JS_ACQUIRE_LOCK(lock); +- drop(w); +- +- if (lockedIsIdle()) { +- JS_RELEASE_LOCK(lock); +- main->wake(); +- JS_ACQUIRE_LOCK(lock); +- } +- } +-} +- +-const bool mswin = +-#ifdef XP_WIN +- true +-#else +- false +-#endif +- ; +- +-template <class Ch> bool +-IsAbsolute(const Ch *filename) +-{ +- return filename[0] == '/' || +- (mswin && (filename[0] == '\\' || (filename[0] != '\0' && filename[1] == ':'))); +-} +- +-// Note: base is a filename, not a directory name. +-static JSString * +-ResolveRelativePath(JSContext *cx, const char *base, JSString *filename) +-{ +- size_t fileLen = JS_GetStringLength(filename); +- const jschar *fileChars = JS_GetStringCharsZ(cx, filename); +- if (!fileChars) +- return NULL; +- +- if (IsAbsolute(fileChars)) +- return filename; +- +- // Strip off the filename part of base. +- size_t dirLen = -1; +- for (size_t i = 0; base[i]; i++) { +- if (base[i] == '/' || (mswin && base[i] == '\\')) +- dirLen = i; +- } +- +- // If base is relative and contains no directories, use filename unchanged. +- if (!IsAbsolute(base) && dirLen == (size_t) -1) +- return filename; +- +- // Otherwise return base[:dirLen + 1] + filename. +- js::Vector<jschar, 0, js::ContextAllocPolicy> result(cx); +- size_t nchars; +- if (!JS_DecodeBytes(cx, base, dirLen + 1, NULL, &nchars)) +- return NULL; +- if (!result.reserve(dirLen + 1 + fileLen)) { +- JS_ReportOutOfMemory(cx); +- return NULL; +- } +- JS_ALWAYS_TRUE(result.resize(dirLen + 1)); +- if (!JS_DecodeBytes(cx, base, dirLen + 1, result.begin(), &nchars)) +- return NULL; +- JS_ALWAYS_TRUE(result.append(fileChars, fileLen)); +- return JS_NewUCStringCopyN(cx, result.begin(), result.length()); +-} +- +-Worker * +-Worker::create(JSContext *parentcx, WorkerParent *parent, JSString *scriptName, JSObject *obj) +-{ +- Worker *w = new Worker(); +- if (!w || !w->init(parentcx, parent, obj)) { +- delete w; +- return NULL; +- } +- +- JSStackFrame *frame = JS_GetScriptedCaller(parentcx, NULL); +- const char *base = JS_GetScriptFilename(parentcx, JS_GetFrameScript(parentcx, frame)); +- JSString *scriptPath = ResolveRelativePath(parentcx, base, scriptName); +- if (!scriptPath) +- return NULL; +- +- // Post an InitEvent to run the initialization script. +- Event *event = InitEvent::create(parentcx, w, scriptPath); +- if (!event) +- return NULL; +- if (!w->events.push(event) || !w->threadPool->getWorkerQueue()->post(w)) { +- event->destroy(parentcx); +- JS_ReportOutOfMemory(parentcx); +- w->dispose(); +- return NULL; +- } +- return w; +-} +- +-void +-Worker::processOneEvent() +-{ +- Event *event; +- { +- AutoLock hold1(lock); +- if (lockedCheckTermination() || events.empty()) +- return; +- +- event = current = events.pop(); +- } +- +- JS_SetContextThread(context); +- JS_SetNativeStackQuota(context, gMaxStackSize); +- +- Event::Result result; +- { +- JSAutoRequest req(context); +- result = event->process(context); +- } +- +- // Note: we have to leave the above request before calling parent->post or +- // checkTermination, both of which acquire locks. +- if (result == Event::forwardToParent) { +- event->setChildAndRecipient(this, parent); +- if (parent->post(event)) { +- event = NULL; // to prevent it from being deleted below +- } else { +- JS_ReportOutOfMemory(context); +- result = Event::fail; +- } +- } +- if (result == Event::fail && !checkTermination()) { +- JSAutoRequest req(context); +- Event *err = ErrorEvent::create(context, this); +- if (err && !parent->post(err)) { +- JS_ReportOutOfMemory(context); +- err->destroy(context); +- err = NULL; +- } +- if (!err) { +- // FIXME - out of memory, probably should panic +- } +- } +- +- if (event) +- event->destroy(context); +- JS_ClearContextThread(context); +- +- { +- AutoLock hold2(lock); +- current = NULL; +- if (!lockedCheckTermination() && !events.empty()) { +- // Re-enqueue this worker. OOM here effectively kills the worker. +- if (!threadPool->getWorkerQueue()->post(this)) +- JS_ReportOutOfMemory(context); +- } +- } +-} +- +-JSBool +-Worker::jsPostMessageToParent(JSContext *cx, uintN argc, jsval *vp) +-{ +- jsval workerval; +- if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)), 0, &workerval)) +- return false; +- Worker *w = (Worker *) JSVAL_TO_PRIVATE(workerval); +- +- { +- JSAutoSuspendRequest suspend(cx); // avoid nesting w->lock in a request +- if (w->checkTermination()) +- return false; +- } +- +- jsval data = argc > 0 ? JS_ARGV(cx, vp)[0] : JSVAL_VOID; +- Event *event = UpMessageEvent::create(cx, w, data); +- if (!event) +- return false; +- if (!w->parent->post(event)) { +- event->destroy(cx); +- JS_ReportOutOfMemory(cx); +- return false; +- } +- JS_SET_RVAL(cx, vp, JSVAL_VOID); +- return true; +-} +- +-JSBool +-Worker::jsPostMessageToChild(JSContext *cx, uintN argc, jsval *vp) +-{ +- JSObject *workerobj = JS_THIS_OBJECT(cx, vp); +- if (!workerobj) +- return false; +- Worker *w = (Worker *) JS_GetInstancePrivate(cx, workerobj, &jsWorkerClass, JS_ARGV(cx, vp)); +- if (!w) { +- if (!JS_IsExceptionPending(cx)) +- JS_ReportError(cx, "Worker was shut down"); +- return false; +- } +- +- jsval data = argc > 0 ? JS_ARGV(cx, vp)[0] : JSVAL_VOID; +- Event *event = DownMessageEvent::create(cx, w, data); +- if (!event) +- return false; +- if (!w->post(event)) { +- JS_ReportOutOfMemory(cx); +- return false; +- } +- JS_SET_RVAL(cx, vp, JSVAL_VOID); +- return true; +-} +- +-JSBool +-Worker::jsTerminate(JSContext *cx, uintN argc, jsval *vp) +-{ +- JS_SET_RVAL(cx, vp, JSVAL_VOID); +- +- JSObject *workerobj = JS_THIS_OBJECT(cx, vp); +- if (!workerobj) +- return false; +- Worker *w = (Worker *) JS_GetInstancePrivate(cx, workerobj, &jsWorkerClass, JS_ARGV(cx, vp)); +- if (!w) +- return !JS_IsExceptionPending(cx); // ok to terminate twice +- +- JSAutoSuspendRequest suspend(cx); +- w->setTerminateFlag(); +- return true; +-} +- +-void +-Event::trace(JSTracer *trc) +-{ +- if (recipient) +- recipient->trace(trc); +- if (child) +- JS_CALL_OBJECT_TRACER(trc, child->asObject(), "worker"); +-} +- +-JSClass ThreadPool::jsClass = { +- "ThreadPool", JSCLASS_HAS_PRIVATE | JSCLASS_MARK_IS_TRACE, +- JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub, +- JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, jsFinalize, +- NULL, NULL, NULL, NULL, +- NULL, NULL, JS_CLASS_TRACE(jsTraceThreadPool), NULL +-}; +- +-JSClass Worker::jsWorkerClass = { +- "Worker", JSCLASS_HAS_PRIVATE | JSCLASS_MARK_IS_TRACE, +- JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub, +- JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, jsFinalize, +- NULL, NULL, NULL, NULL, +- NULL, NULL, JS_CLASS_TRACE(jsTraceWorker), NULL +-}; +- +-JSFunctionSpec Worker::jsMethods[3] = { +- JS_FN("postMessage", Worker::jsPostMessageToChild, 1, 0), +- JS_FN("terminate", Worker::jsTerminate, 0, 0), +- JS_FS_END +-}; +- +-ThreadPool * +-js::workers::init(JSContext *cx, WorkerHooks *hooks, JSObject *global, JSObject **rootp) +-{ +- return Worker::initWorkers(cx, hooks, global, rootp); +-} +- +-void +-js::workers::terminateAll(JSRuntime *rt, ThreadPool *tp) +-{ +- tp->terminateAll(rt); +-} +- +-void +-js::workers::finish(JSContext *cx, ThreadPool *tp) +-{ +- if (MainQueue *mq = tp->getMainQueue()) { +- JS_ALWAYS_TRUE(mq->mainThreadWork(cx, true)); +- tp->shutdown(cx); +- } +-} +- +-#endif /* JS_THREADSAFE */ +diff -ruN src/shell/jsworkers.h src.new/shell/jsworkers.h +--- shell/jsworkers.h 2011-04-01 06:08:36.000000000 +1100 ++++ shell/jsworkers.h 1970-01-01 10:00:00.000000000 +1000 +@@ -1,93 +0,0 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- +- * vim: set ts=8 sw=4 et tw=99: +- * +- * ***** BEGIN LICENSE BLOCK ***** +- * Version: MPL 1.1/GPL 2.0/LGPL 2.1 +- * +- * The contents of this file are subject to the Mozilla Public License Version +- * 1.1 (the "License"); you may not use this file except in compliance with +- * the License. You may obtain a copy of the License at +- * http://www.mozilla.org/MPL/ +- * +- * Software distributed under the License is distributed on an "AS IS" basis, +- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +- * for the specific language governing rights and limitations under the +- * License. +- * +- * The Original Code is JavaScript shell workers. +- * +- * The Initial Developer of the Original Code is +- * Mozilla Corporation. +- * Portions created by the Initial Developer are Copyright (C) 2010 +- * the Initial Developer. All Rights Reserved. +- * +- * Contributor(s): +- * Jason Orendorff <jorendorff@mozilla.com> +- * +- * Alternatively, the contents of this file may be used under the terms of +- * either of the GNU General Public License Version 2 or later (the "GPL"), +- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +- * in which case the provisions of the GPL or the LGPL are applicable instead +- * of those above. If you wish to allow use of your version of this file only +- * under the terms of either the GPL or the LGPL, and not to allow others to +- * use your version of this file under the terms of the MPL, indicate your +- * decision by deleting the provisions above and replace them with the notice +- * and other provisions required by the GPL or the LGPL. If you do not delete +- * the provisions above, a recipient may use your version of this file under +- * the terms of any one of the MPL, the GPL or the LGPL. +- * +- * ***** END LICENSE BLOCK ***** */ +- +-#ifndef jsworkers_h___ +-#define jsworkers_h___ +- +-#ifdef JS_THREADSAFE +- +-#include "jsapi.h" +- +-/* +- * Workers for the JS shell. +- * +- * Note: The real implementation of DOM Workers is in dom/src/threads. +- */ +-namespace js { +- namespace workers { +- class ThreadPool; +- +- class WorkerHooks { +- public: +- virtual JSObject *newGlobalObject(JSContext *cx) = 0; +- virtual ~WorkerHooks() {} +- }; +- +- /* +- * Initialize workers. This defines the Worker constructor on global. +- * Requires request. rootp must point to a GC root. +- * +- * On success, *rootp receives a pointer to an object, and init returns +- * a non-null value. The caller must keep the object rooted and must +- * pass it to js::workers::finish later. +- */ +- ThreadPool *init(JSContext *cx, WorkerHooks *hooks, JSObject *global, JSObject **rootp); +- +- /* Asynchronously signal for all workers to terminate. +- * +- * Call this before calling finish() to shut down without waiting for +- * all messages to be proceesed. +- */ +- void terminateAll(JSRuntime *rt, ThreadPool *tp); +- +- /* +- * Finish running any workers, shut down the thread pool, and free all +- * resources associated with workers. The application must call this +- * before shutting down the runtime, and not during GC. +- * +- * Requires request. +- */ +- void finish(JSContext *cx, ThreadPool *tp); +- } +-} +- +-#endif /* JS_THREADSAFE */ +- +-#endif /* jsworkers_h___ */ +diff -ruN src/tests/browser.js src.new/tests/browser.js +--- tests/browser.js 2011-04-01 06:08:36.000000000 +1100 ++++ tests/browser.js 2013-03-23 22:03:56.716635673 +1100 +@@ -767,17 +767,6 @@ + document.write(s); + } + +-var JSTest = { +- waitForExplicitFinish: function () { +- gDelayTestDriverEnd = true; +- }, +- +- testFinished: function () { +- gDelayTestDriverEnd = false; +- jsTestDriverEnd(); +- } +-}; +- + function jsTestDriverEnd() + { + // gDelayTestDriverEnd is used to +diff -ruN src/tests/js1_8_5/extensions/jstests.list src.new/tests/js1_8_5/extensions/jstests.list +--- tests/js1_8_5/extensions/jstests.list 2011-04-01 06:08:36.000000000 +1100 ++++ tests/js1_8_5/extensions/jstests.list 2013-03-23 22:29:16.973264001 +1100 +@@ -1,13 +1,6 @@ + url-prefix ../../jsreftest.html?test=js1_8_5/extensions/ + script typedarray.js + script typedarray-prototype.js +-skip-if(!xulRuntime.shell) script worker-error.js # these tests sometimes hang in browser, bug 559954, bug 562333 +-skip-if(!xulRuntime.shell) script worker-error-propagation.js +-skip-if(!xulRuntime.shell) script worker-fib.js +-skip-if(!xulRuntime.shell) script worker-init.js +-skip-if(!xulRuntime.shell) script worker-simple.js +-skip-if(!xulRuntime.shell) script worker-terminate.js +-skip-if(!xulRuntime.shell) script worker-timeout.js + script scripted-proxies.js + script array-length-protochange.js + script parseInt-octal.js +diff -ruN src/tests/js1_8_5/extensions/worker-error-child.js src.new/tests/js1_8_5/extensions/worker-error-child.js +--- tests/js1_8_5/extensions/worker-error-child.js 2011-04-01 06:08:36.000000000 +1100 ++++ tests/js1_8_5/extensions/worker-error-child.js 1970-01-01 10:00:00.000000000 +1000 +@@ -1,9 +0,0 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +-/* +- * Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/licenses/publicdomain/ +- * Contributor: Jason Orendorff <jorendorff@mozilla.com> +- */ +-function onmessage(event) { +- throw new Error("fail"); +-} +diff -ruN src/tests/js1_8_5/extensions/worker-error-propagation-child.js src.new/tests/js1_8_5/extensions/worker-error-propagation-child.js +--- tests/js1_8_5/extensions/worker-error-propagation-child.js 2011-04-01 06:08:36.000000000 +1100 ++++ tests/js1_8_5/extensions/worker-error-propagation-child.js 1970-01-01 10:00:00.000000000 +1000 +@@ -1,16 +0,0 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +-/* +- * Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/licenses/publicdomain/ +- * Contributor: Jason Orendorff <jorendorff@mozilla.com> +- */ +- +-function onmessage(event) { +- var n = +event.data; +- if (n == 0) +- throw new Error("boom"); +- var w = new Worker(workerDir + "worker-error-propagation-child.js"); +- w.onmessage = function (event) { postMessage(event.data); }; +- // No w.onerror here. We are testing error propagation when it is absent. +- w.postMessage(n - 1 + ""); +-} +diff -ruN src/tests/js1_8_5/extensions/worker-error-propagation.js src.new/tests/js1_8_5/extensions/worker-error-propagation.js +--- tests/js1_8_5/extensions/worker-error-propagation.js 2011-04-01 06:08:36.000000000 +1100 ++++ tests/js1_8_5/extensions/worker-error-propagation.js 1970-01-01 10:00:00.000000000 +1000 +@@ -1,20 +0,0 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +-/* +- * Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/licenses/publicdomain/ +- * Contributor: Jason Orendorff <jorendorff@mozilla.com> +- */ +- +-if (typeof Worker != 'undefined') { +- JSTest.waitForExplicitFinish(); +- var w = Worker(workerDir + "worker-error-propagation-child.js"); +- var errors = 0; +- w.onmessage = function () { throw new Error("no reply expected"); }; +- w.onerror = function (event) { +- reportCompare("string", typeof event.message, "typeof event.message"); +- JSTest.testFinished(); +- }; +- w.postMessage("5"); +-} else { +- reportCompare(0, 0, " PASSED! Test skipped. Shell workers required."); +-} +diff -ruN src/tests/js1_8_5/extensions/worker-error.js src.new/tests/js1_8_5/extensions/worker-error.js +--- tests/js1_8_5/extensions/worker-error.js 2011-04-01 06:08:36.000000000 +1100 ++++ tests/js1_8_5/extensions/worker-error.js 1970-01-01 10:00:00.000000000 +1000 +@@ -1,21 +0,0 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +-/* +- * Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/licenses/publicdomain/ +- * Contributor: Jason Orendorff <jorendorff@mozilla.com> +- */ +- +-if (typeof Worker != 'undefined') { +- JSTest.waitForExplicitFinish(); +- +- // The script throws new Error("fail") on first message. +- var w = Worker(workerDir + "worker-error-child.js"); +- var a = []; +- w.onerror = function (event) { +- reportCompare("fail", event.message, "worker-error"); +- JSTest.testFinished(); +- }; +- w.postMessage("hello"); +-} else { +- reportCompare(0, 0, "Test skipped. Shell workers required."); +-} +diff -ruN src/tests/js1_8_5/extensions/worker-fib-child.js src.new/tests/js1_8_5/extensions/worker-fib-child.js +--- tests/js1_8_5/extensions/worker-fib-child.js 2011-04-01 06:08:36.000000000 +1100 ++++ tests/js1_8_5/extensions/worker-fib-child.js 1970-01-01 10:00:00.000000000 +1000 +@@ -1,27 +0,0 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +-/* +- * Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/licenses/publicdomain/ +- * Contributor: Jason Orendorff <jorendorff@mozilla.com> +- */ +- +-function onmessage(event) { +- var a = event.data.split(/\t/); +- var n = Number(a[0]); +- var workerDir = a[1]; +- +- if (n <= 1) { +- postMessage("" + n); +- } else { +- var w1 = new Worker(workerDir + "worker-fib-child.js"), +- w2 = new Worker(workerDir + "worker-fib-child.js"); +- var a = []; +- w1.onmessage = w2.onmessage = function(event) { +- a.push(+event.data); +- if (a.length == 2) +- postMessage(a[0] + a[1] + ""); +- }; +- w1.postMessage(n - 1 + "\t" + workerDir); +- w2.postMessage(n - 2 + "\t" + workerDir); +- } +-} +diff -ruN src/tests/js1_8_5/extensions/worker-fib.js src.new/tests/js1_8_5/extensions/worker-fib.js +--- tests/js1_8_5/extensions/worker-fib.js 2011-04-01 06:08:36.000000000 +1100 ++++ tests/js1_8_5/extensions/worker-fib.js 1970-01-01 10:00:00.000000000 +1000 +@@ -1,18 +0,0 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +-/* +- * Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/licenses/publicdomain/ +- * Contributor: Jason Orendorff <jorendorff@mozilla.com> +- */ +- +-if (typeof Worker != 'undefined') { +- JSTest.waitForExplicitFinish(); +- var w = Worker(workerDir + "worker-fib-child.js"); +- w.onmessage = function (event) { +- reportCompare("55", event.data, "worker-fib"); +- JSTest.testFinished(); +- }; +- w.postMessage("10\t" + workerDir); // 0 1 1 2 3 5 8 13 21 34 55 +-} else { +- reportCompare(0, 0, "Test skipped. Shell workers required."); +-} +diff -ruN src/tests/js1_8_5/extensions/worker-init-child.js src.new/tests/js1_8_5/extensions/worker-init-child.js +--- tests/js1_8_5/extensions/worker-init-child.js 2011-04-01 06:08:36.000000000 +1100 ++++ tests/js1_8_5/extensions/worker-init-child.js 1970-01-01 10:00:00.000000000 +1000 +@@ -1,8 +0,0 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +-/* +- * Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/licenses/publicdomain/ +- * Contributor: Jason Orendorff <jorendorff@mozilla.com> +- */ +-postMessage('do your worst'); +-for (;;) ; +diff -ruN src/tests/js1_8_5/extensions/worker-init.js src.new/tests/js1_8_5/extensions/worker-init.js +--- tests/js1_8_5/extensions/worker-init.js 2011-04-01 06:08:36.000000000 +1100 ++++ tests/js1_8_5/extensions/worker-init.js 1970-01-01 10:00:00.000000000 +1000 +@@ -1,19 +0,0 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +-/* +- * Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/licenses/publicdomain/ +- * Contributor: Jason Orendorff <jorendorff@mozilla.com> +- */ +- +-if (typeof Worker != 'undefined') { +- JSTest.waitForExplicitFinish(); +- // Messages sent during initialization are a corner case, but in any case +- // they should be delivered (no waiting until initialization is complete). +- var w = new Worker(workerDir + "worker-init-child.js"); // posts a message, then loops forever +- w.onmessage = function (event) { +- reportCompare(0, 0, "worker-init"); +- JSTest.testFinished(); +- }; +-} else { +- reportCompare(0, 0, "Test skipped. Shell workers required."); +-} +diff -ruN src/tests/js1_8_5/extensions/worker-simple-child.js src.new/tests/js1_8_5/extensions/worker-simple-child.js +--- tests/js1_8_5/extensions/worker-simple-child.js 2011-04-01 06:08:36.000000000 +1100 ++++ tests/js1_8_5/extensions/worker-simple-child.js 1970-01-01 10:00:00.000000000 +1000 +@@ -1,8 +0,0 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +-/* +- * Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/licenses/publicdomain/ +- * Contributor: Jason Orendorff <jorendorff@mozilla.com> +- */ +- +-onmessage = function (event) { postMessage(event.data); }; +diff -ruN src/tests/js1_8_5/extensions/worker-simple.js src.new/tests/js1_8_5/extensions/worker-simple.js +--- tests/js1_8_5/extensions/worker-simple.js 2011-04-01 06:08:36.000000000 +1100 ++++ tests/js1_8_5/extensions/worker-simple.js 1970-01-01 10:00:00.000000000 +1000 +@@ -1,20 +0,0 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +-/* +- * Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/licenses/publicdomain/ +- * Contributor: Jason Orendorff <jorendorff@mozilla.com> +- */ +- +-if (typeof Worker != 'undefined') { +- JSTest.waitForExplicitFinish(); +- var w = new Worker(workerDir + "worker-simple-child.js"); +- var a = []; +- w.onmessage = function (event) { +- a.push(event.data); +- reportCompare(0, 0, "worker-simple"); +- JSTest.testFinished(); +- }; +- w.postMessage("hello"); +-} else { +- reportCompare(0, 0, "Test skipped. Shell workers required."); +-} +diff -ruN src/tests/js1_8_5/extensions/worker-terminate-child.js src.new/tests/js1_8_5/extensions/worker-terminate-child.js +--- tests/js1_8_5/extensions/worker-terminate-child.js 2011-04-01 06:08:36.000000000 +1100 ++++ tests/js1_8_5/extensions/worker-terminate-child.js 1970-01-01 10:00:00.000000000 +1000 +@@ -1,13 +0,0 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +-/* +- * Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/licenses/publicdomain/ +- * Contributor: Jason Orendorff <jorendorff@mozilla.com> +- */ +- +-onmessage = function (event) { +- var workerDir = event.message; +- var child = new Worker(workerDir + 'worker-terminate-iloop.js'); // loops forever +- child.terminate(); +- postMessage("killed"); +-}; +diff -ruN src/tests/js1_8_5/extensions/worker-terminate-iloop.js src.new/tests/js1_8_5/extensions/worker-terminate-iloop.js +--- tests/js1_8_5/extensions/worker-terminate-iloop.js 2011-04-01 06:08:36.000000000 +1100 ++++ tests/js1_8_5/extensions/worker-terminate-iloop.js 1970-01-01 10:00:00.000000000 +1000 +@@ -1,9 +0,0 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +-/* +- * Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/licenses/publicdomain/ +- * Contributor: Jason Orendorff <jorendorff@mozilla.com> +- */ +- +-for (;;) +- ; +diff -ruN src/tests/js1_8_5/extensions/worker-terminate.js src.new/tests/js1_8_5/extensions/worker-terminate.js +--- tests/js1_8_5/extensions/worker-terminate.js 2011-04-01 06:08:36.000000000 +1100 ++++ tests/js1_8_5/extensions/worker-terminate.js 1970-01-01 10:00:00.000000000 +1000 +@@ -1,37 +0,0 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +-/* +- * Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/licenses/publicdomain/ +- * Contributor: Jason Orendorff <jorendorff@mozilla.com> +- */ +- +-if (typeof Worker != 'undefined') { +- JSTest.waitForExplicitFinish(); +- +- // This tests that a parent worker can terminate a child. We run the test +- // several times serially. If terminate() doesn't work, the runaway Workers +- // will soon outnumber the number of threads in the thread pool, and we +- // will deadlock. +- var i = 0; +- +- function next() { +- if (++i == 10) { +- reportCompare(0, 0, "worker-terminate"); +- JSTest.testFinished(); +- return; +- } +- +- var w = new Worker(workerDir + "worker-terminate-child.js"); +- w.onmessage = function (event) { +- reportCompare("killed", event.data, "killed runaway worker #" + i); +- next(); +- }; +- w.onerror = function (event) { +- reportCompare(0, 1, "Got error: " + event.message); +- }; +- w.postMessage(workerDir); +- } +- next(); +-} else { +- reportCompare(0, 0, "Test skipped. Shell workers required."); +-} +diff -ruN src/tests/js1_8_5/extensions/worker-timeout-child.js src.new/tests/js1_8_5/extensions/worker-timeout-child.js +--- tests/js1_8_5/extensions/worker-timeout-child.js 2011-04-01 06:08:36.000000000 +1100 ++++ tests/js1_8_5/extensions/worker-timeout-child.js 1970-01-01 10:00:00.000000000 +1000 +@@ -1,9 +0,0 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +-/* +- * Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/licenses/publicdomain/ +- * Contributor: Jason Orendorff +- */ +- +-for (;;) +- ; +diff -ruN src/tests/js1_8_5/extensions/worker-timeout.js src.new/tests/js1_8_5/extensions/worker-timeout.js +--- tests/js1_8_5/extensions/worker-timeout.js 2011-04-01 06:08:36.000000000 +1100 ++++ tests/js1_8_5/extensions/worker-timeout.js 1970-01-01 10:00:00.000000000 +1000 +@@ -1,18 +0,0 @@ +-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +-/* +- * Any copyright is dedicated to the Public Domain. +- * http://creativecommons.org/licenses/publicdomain/ +- * Contributor: Jason Orendorff +- */ +- +-if (typeof timeout == 'function' && typeof Worker != 'undefined') { +- // We don't actually ever call JSTest.testFinished(); instead we +- // time out and exit the shell with exit code 6. +- JSTest.waitForExplicitFinish(); +- expectExitCode(6); +- timeout(1.0); +- for (var i = 0; i < 5; i++) +- new Worker(workerDir + "worker-timeout-child.js"); // just loops forever +-} else { +- reportCompare(0, 0, "Test skipped. Shell workers and timeout required."); +-} +diff -ruN src/tests/shell.js src.new/tests/shell.js +--- tests/shell.js 2011-04-01 06:08:36.000000000 +1100 ++++ tests/shell.js 2013-03-23 22:07:41.387249919 +1100 +@@ -833,18 +833,6 @@ + } + } + +-var JSTest = { +- waitForExplicitFinish: function () { +- gDelayTestDriverEnd = true; +- }, +- +- testFinished: function () { +- gDelayTestDriverEnd = false; +- jsTestDriverEnd(); +- quit(); +- } +-}; +- + function jsTestDriverEnd() + { + // gDelayTestDriverEnd is used to diff --git a/lang/spidermonkey185/files/patch-c++11 b/lang/spidermonkey185/files/patch-c++11 new file mode 100644 index 000000000000..95a68426f5de --- /dev/null +++ b/lang/spidermonkey185/files/patch-c++11 @@ -0,0 +1,247 @@ +jsapi.cpp:3988:16: error: cannot initialize return object of type 'JSIdArray *' with an rvalue of type 'bool' + return false; + ^~~~~ +jsarray.cpp:497:1: error: non-constant-expression cannot be narrowed from type 'intptr_t' (aka 'long') to 'uintptr_t' (aka 'unsigned long') in initializer list [-Wc++11-narrowing] +JS_DEFINE_CALLINFO_3(extern, BOOL, js_EnsureDenseArrayCapacity, CONTEXT, OBJECT, INT32, +^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +./jsbuiltins.h:350:5: note: expanded from macro 'JS_DEFINE_CALLINFO_3' + _JS_DEFINE_CALLINFO(linkage, op, \ + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +./jsbuiltins.h:294:11: note: expanded from macro '_JS_DEFINE_CALLINFO' + { (intptr_t) &name, argtypes, nanojit::ABI_FASTCALL, isPure, storeAccSet _JS_CI_NAME(name) }; \ + ^~~~~~~~~~~~~~~~ +jsfun.cpp:2054:16: error: cannot initialize return object of type 'JSString *' with an rvalue of type 'bool' + return false; + ^~~~~ +jsfun.cpp:2660:20: error: cannot initialize return object of type 'const js::Shape *' with an rvalue of type 'bool' + return false; + ^~~~~ +jsiter.cpp:428:20: error: cannot initialize return object of type 'JSObject *' with an rvalue of type 'bool' + return false; + ^~~~~ +jsparse.cpp:3355:20: error: cannot initialize return object of type 'JSParseNode *' with an rvalue of type 'bool' + return false; + ^~~~~ +jsstr.cpp:1737:24: error: cannot initialize return object of type 'const RegExpPair *' with an rvalue of type 'bool' + return false; + ^~~~~ +jsstr.cpp:3403:16: error: cannot initialize return object of type 'JSObject *' with an rvalue of type 'JSIntn' (aka 'int') + return JS_FALSE; + ^~~~~~~~ +./jstypes.h:395:18: note: expanded from macro 'JS_FALSE' +#define JS_FALSE (JSIntn)0 + ^~~~~~~~~ +jstypedarray.cpp:1337:20: error: cannot initialize return object of type 'JSObject *' with an rvalue of type 'bool' + return false; + ^~~~~ +jstypedarray.cpp:1671:16: error: cannot initialize return object of type 'JSObject *' with an rvalue of type 'bool' + return false; + ^~~~~ +jsxml.cpp:285:16: error: cannot initialize return object of type 'JSObject *' with an rvalue of type 'JSIntn' (aka 'int') + return JS_FALSE; + ^~~~~~~~ +jsxml.cpp:434:20: error: cannot initialize return object of type 'JSString *' with an rvalue of type 'JSIntn' (aka 'int') + return JS_FALSE; + ^~~~~~~~ +./jstypes.h:395:18: note: expanded from macro 'JS_FALSE' +#define JS_FALSE (JSIntn)0 + ^~~~~~~~~ +./methodjit/InvokeHelpers.cpp:731:16: error: cannot initialize return object of type 'void *' with an rvalue of type 'bool' + return false; + ^~~~~ +./nanojit/NativeX64.cpp:1902:59: error: constant expression evaluates to 9223372036854775808 which cannot be narrowed to type 'int64_t' (aka 'long') [-Wc++11-narrowing] + static const AVMPLUS_ALIGN16(int64_t) negateMask[] = {0x8000000000000000LL,0}; + ^~~~~~~~~~~~~~~~~~~~ +./nanojit/NativeX64.cpp:1902:59: note: insert an explicit cast to silence this issue + static const AVMPLUS_ALIGN16(int64_t) negateMask[] = {0x8000000000000000LL,0}; + ^~~~~~~~~~~~~~~~~~~~ + static_cast<int64_t>( ) +./nanojit/RegAlloc.h:189:24: error: non-constant-expression cannot be narrowed from type 'int' to 'nanojit::Register' (aka 'unsigned int') in initializer list [-Wc++11-narrowing] + Register r = { (sizeof(RegisterMask) == 4) ? lsbSet32(mask) : lsbSet64(mask) }; + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +./nanojit/RegAlloc.h:189:24: note: insert an explicit cast to silence this issue + Register r = { (sizeof(RegisterMask) == 4) ? lsbSet32(mask) : lsbSet64(mask) }; + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + static_cast<Register>( ) +./nanojit/RegAlloc.h:197:24: error: non-constant-expression cannot be narrowed from type 'int' to 'nanojit::Register' (aka 'unsigned int') in initializer list [-Wc++11-narrowing] + Register r = { (sizeof(RegisterMask) == 4) ? msbSet32(mask) : msbSet64(mask) }; + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +./nanojit/RegAlloc.h:197:24: note: insert an explicit cast to silence this issue + Register r = { (sizeof(RegisterMask) == 4) ? msbSet32(mask) : msbSet64(mask) }; + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + static_cast<Register>( ) + +--- jsapi.cpp.orig 2011-03-31 19:08:36 UTC ++++ jsapi.cpp +@@ -3985,7 +3985,7 @@ JS_Enumerate(JSContext *cx, JSObject *obj) + AutoIdVector props(cx); + JSIdArray *ida; + if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &props) || !VectorToIdArray(cx, props, &ida)) +- return false; ++ return NULL; + for (size_t n = 0; n < size_t(ida->length); ++n) + JS_ASSERT(js_CheckForStringIndex(ida->vector[n]) == ida->vector[n]); + return ida; +--- jsbuiltins.h.orig 2011-03-31 19:08:36 UTC ++++ jsbuiltins.h +@@ -284,14 +284,14 @@ struct ClosureVarInfo; + #define _JS_DEFINE_CALLINFO(linkage, name, crtype, cargtypes, argtypes, isPure, storeAccSet) \ + _JS_TN_LINKAGE(linkage, crtype) name cargtypes; \ + _JS_CI_LINKAGE(linkage) const nanojit::CallInfo _JS_CALLINFO(name) = \ +- { (intptr_t) &name, argtypes, nanojit::ABI_CDECL, isPure, storeAccSet _JS_CI_NAME(name) };\ ++ { (uintptr_t) &name, argtypes, nanojit::ABI_CDECL, isPure, storeAccSet _JS_CI_NAME(name) };\ + JS_STATIC_ASSERT_IF(isPure, (storeAccSet) == nanojit::ACCSET_NONE); + + #else + #define _JS_DEFINE_CALLINFO(linkage, name, crtype, cargtypes, argtypes, isPure, storeAccSet) \ + _JS_TN_LINKAGE(linkage, crtype) FASTCALL name cargtypes; \ + _JS_CI_LINKAGE(linkage) const nanojit::CallInfo _JS_CALLINFO(name) = \ +- { (intptr_t) &name, argtypes, nanojit::ABI_FASTCALL, isPure, storeAccSet _JS_CI_NAME(name) }; \ ++ { (uintptr_t) &name, argtypes, nanojit::ABI_FASTCALL, isPure, storeAccSet _JS_CI_NAME(name) }; \ + JS_STATIC_ASSERT_IF(isPure, (storeAccSet) == nanojit::ACCSET_NONE); + #endif + +--- jsfun.cpp.orig 2011-03-31 19:08:36 UTC ++++ jsfun.cpp +@@ -2051,7 +2051,7 @@ fun_toStringHelper(JSContext *cx, JSObject *obj, uintN + + JSString *str = JS_DecompileFunction(cx, fun, indent); + if (!str) +- return false; ++ return NULL; + + if (!indent) + cx->compartment->toSourceCache.put(fun, str); +@@ -2657,7 +2657,7 @@ LookupInterpretedFunctionPrototype(JSContext *cx, JSOb + const Shape *shape = funobj->nativeLookup(id); + if (!shape) { + if (!ResolveInterpretedFunctionPrototype(cx, funobj)) +- return false; ++ return NULL; + shape = funobj->nativeLookup(id); + } + JS_ASSERT(!shape->configurable()); +--- jsiter.cpp.orig 2011-03-31 19:08:36 UTC ++++ jsiter.cpp +@@ -425,7 +425,7 @@ NewIteratorObject(JSContext *cx, uintN flags) + */ + JSObject *obj = js_NewGCObject(cx, FINALIZE_OBJECT0); + if (!obj) +- return false; ++ return NULL; + obj->init(cx, &js_IteratorClass, NULL, NULL, NULL, false); + obj->setMap(cx->compartment->emptyEnumeratorShape); + return obj; +--- jsparse.cpp.orig 2011-03-31 19:08:36 UTC ++++ jsparse.cpp +@@ -3352,7 +3352,7 @@ Parser::functionDef(JSAtom *funAtom, FunctionType type + if (!outertc->inFunction() && bodyLevel && funAtom && !lambda && outertc->compiling()) { + JS_ASSERT(pn->pn_cookie.isFree()); + if (!DefineGlobal(pn, outertc->asCodeGenerator(), funAtom)) +- return false; ++ return NULL; + } + + pn->pn_blockid = outertc->blockid(); +--- jsstr.cpp.orig 2011-03-31 19:08:36 UTC ++++ jsstr.cpp +@@ -1734,7 +1734,7 @@ class RegExpGuard + if (flat) { + patstr = flattenPattern(cx, fm.patstr); + if (!patstr) +- return false; ++ return NULL; + } else { + patstr = fm.patstr; + } +@@ -3400,7 +3400,7 @@ js_InitStringClass(JSContext *cx, JSObject *obj) + UndefinedValue(), NULL, NULL, + JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0, + NULL)) { +- return JS_FALSE; ++ return NULL; + } + + return proto; +--- jstypedarray.cpp.orig 2011-03-31 19:08:36 UTC ++++ jstypedarray.cpp +@@ -1334,7 +1334,7 @@ class TypedArrayTemplate + if (size != 0 && count >= INT32_MAX / size) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, + JSMSG_NEED_DIET, "size and count"); +- return false; ++ return NULL; + } + + int32 bytelen = size * count; +@@ -1668,7 +1668,7 @@ TypedArrayConstruct(JSContext *cx, jsint atype, uintN + + default: + JS_NOT_REACHED("shouldn't have gotten here"); +- return false; ++ return NULL; + } + } + +--- jsxml.cpp.orig 2011-03-31 19:08:36 UTC ++++ jsxml.cpp +@@ -282,7 +282,7 @@ NewXMLNamespace(JSContext *cx, JSLinearString *prefix, + + obj = NewBuiltinClassInstanceXML(cx, &js_NamespaceClass); + if (!obj) +- return JS_FALSE; ++ return NULL; + JS_ASSERT(JSVAL_IS_VOID(obj->getNamePrefixVal())); + JS_ASSERT(JSVAL_IS_VOID(obj->getNameURIVal())); + JS_ASSERT(JSVAL_IS_VOID(obj->getNamespaceDeclared())); +@@ -431,7 +431,7 @@ ConvertQNameToString(JSContext *cx, JSObject *obj) + size_t length = str->length(); + jschar *chars = (jschar *) cx->malloc((length + 2) * sizeof(jschar)); + if (!chars) +- return JS_FALSE; ++ return NULL; + *chars = '@'; + const jschar *strChars = str->getChars(cx); + if (!strChars) { +--- methodjit/InvokeHelpers.cpp.orig 2011-03-31 19:08:36 UTC ++++ methodjit/InvokeHelpers.cpp +@@ -728,7 +728,7 @@ AtSafePoint(JSContext *cx) + { + JSStackFrame *fp = cx->fp(); + if (fp->hasImacropc()) +- return false; ++ return NULL; + + JSScript *script = fp->script(); + return script->maybeNativeCodeForPC(fp->isConstructing(), cx->regs->pc); +--- nanojit/NativeX64.cpp.orig 2011-03-31 19:08:36 UTC ++++ nanojit/NativeX64.cpp +@@ -1899,7 +1899,7 @@ namespace nanojit + } + } + +- static const AVMPLUS_ALIGN16(int64_t) negateMask[] = {0x8000000000000000LL,0}; ++ static const AVMPLUS_ALIGN16(int64_t) negateMask[] = {(int64_t)0x8000000000000000LL,0}; + + void Assembler::asm_fneg(LIns *ins) { + Register rr, ra; +--- nanojit/RegAlloc.h.orig 2011-03-31 19:08:36 UTC ++++ nanojit/RegAlloc.h +@@ -186,7 +186,7 @@ namespace nanojit + inline Register lsReg(RegisterMask mask) { + // This is faster than it looks; we rely on the C++ optimizer + // to strip the dead branch and inline just one alternative. +- Register r = { (sizeof(RegisterMask) == 4) ? lsbSet32(mask) : lsbSet64(mask) }; ++ Register r = { (sizeof(RegisterMask) == 4) ? (Register)lsbSet32(mask) : (Register)lsbSet64(mask) }; + return r; + } + +@@ -194,7 +194,7 @@ namespace nanojit + inline Register msReg(RegisterMask mask) { + // This is faster than it looks; we rely on the C++ optimizer + // to strip the dead branch and inline just one alternative. +- Register r = { (sizeof(RegisterMask) == 4) ? msbSet32(mask) : msbSet64(mask) }; ++ Register r = { (sizeof(RegisterMask) == 4) ? (Register)msbSet32(mask) : (Register)msbSet64(mask) }; + return r; + } + diff --git a/lang/spidermonkey185/files/patch-configure.in b/lang/spidermonkey185/files/patch-configure.in new file mode 100644 index 000000000000..c8910057a423 --- /dev/null +++ b/lang/spidermonkey185/files/patch-configure.in @@ -0,0 +1,36 @@ +--- ./configure.in.orig 2011-04-01 06:08:36.000000000 +1100 ++++ ./configure.in 2013-05-26 00:19:28.032315432 +1000 +@@ -3378,7 +3378,8 @@ + rm -f conftest.{c,S} + ]) + if test "$ac_cv_have_visibility_builtin_bug" = "no" -a \ +- "$ac_cv_have_visibility_class_bug" = "no"; then ++ "$ac_cv_have_visibility_class_bug" = "no" -a \ ++ "$OS_ARCH" != "FreeBSD" ; then + VISIBILITY_FLAGS='-I$(DIST)/system_wrappers_js -include $(topsrcdir)/config/gcc_hidden.h' + WRAP_SYSTEM_INCLUDES=1 + STL_FLAGS='-I$(DIST)/stl_wrappers' +@@ -4656,6 +4657,9 @@ MOZ_ARG_HEADER(Individual module options + + dnl Setup default CPU arch for arm target + case "$target_cpu" in ++ armv6*) ++ MOZ_ARM_ARCH=armv6 ++ ;; + arm*) + MOZ_ARM_ARCH=armv7 + ;; +@@ -4716,6 +4720,13 @@ elif test "$MOZ_ARM_ARCH" = "armv7"; the + esac + else + case "$target_cpu" in ++ armv6*) ++ if test "$GNU_CC"; then ++ CFLAGS="$CFLAGS" ++ CXXFLAGS="$CXXFLAGS" ++ ASFLAGS="$ASFLAGS" ++ fi ++ ;; + arm*) + if test "$GNU_CC"; then + CFLAGS="$CFLAGS -march=armv5te -mthumb-interwork -msoft-float" diff --git a/lang/spidermonkey185/files/patch-jsscript.h b/lang/spidermonkey185/files/patch-jsscript.h new file mode 100644 index 000000000000..a642b31a8642 --- /dev/null +++ b/lang/spidermonkey185/files/patch-jsscript.h @@ -0,0 +1,48 @@ +# HG changeset patch +# User Ehsan Akhgari <ehsan@mozilla.com> +# Date 1308340787 14400 +# Node ID c0e8643e8e60d1c98bff30c78e034f991f75c191 +# Parent 284ebc48b2cb8e35dc04482ede700e717d8d214f +Bug 662962 - Silence the clang warnings issued because of alignment requirements increase when compiling jsscript.h; r=Waldo + +--- ./jsscript.h.orig 2011-04-01 06:08:36.000000000 +1100 ++++ ./jsscript.h 2013-05-26 00:23:16.202260566 +1000 +@@ -496,32 +496,32 @@ + + JSObjectArray *objects() { + JS_ASSERT(isValidOffset(objectsOffset)); +- return (JSObjectArray *)((uint8 *) (this + 1) + objectsOffset); ++ return reinterpret_cast<JSObjectArray *>(uintptr_t(this + 1) + objectsOffset); + } + + JSUpvarArray *upvars() { + JS_ASSERT(isValidOffset(upvarsOffset)); +- return (JSUpvarArray *) ((uint8 *) (this + 1) + upvarsOffset); ++ return reinterpret_cast<JSUpvarArray *>(uintptr_t(this + 1) + upvarsOffset); + } + + JSObjectArray *regexps() { + JS_ASSERT(isValidOffset(regexpsOffset)); +- return (JSObjectArray *) ((uint8 *) (this + 1) + regexpsOffset); ++ return reinterpret_cast<JSObjectArray *>(uintptr_t(this + 1) + regexpsOffset); + } + + JSTryNoteArray *trynotes() { + JS_ASSERT(isValidOffset(trynotesOffset)); +- return (JSTryNoteArray *) ((uint8 *) (this + 1) + trynotesOffset); ++ return reinterpret_cast<JSTryNoteArray *>(uintptr_t(this + 1) + trynotesOffset); + } + + js::GlobalSlotArray *globals() { + JS_ASSERT(isValidOffset(globalsOffset)); +- return (js::GlobalSlotArray *) ((uint8 *) (this + 1) + globalsOffset); ++ return reinterpret_cast<js::GlobalSlotArray *>(uintptr_t(this + 1) + globalsOffset); + } + + JSConstArray *consts() { + JS_ASSERT(isValidOffset(constOffset)); +- return (JSConstArray *) ((uint8 *) (this + 1) + constOffset); ++ return reinterpret_cast<JSConstArray *>(uintptr_t(this + 1) + constOffset); + } + + JSAtom *getAtom(size_t index) { diff --git a/lang/spidermonkey185/files/patch-jsstr.cpp b/lang/spidermonkey185/files/patch-jsstr.cpp new file mode 100644 index 000000000000..13ab1ee9f3d4 --- /dev/null +++ b/lang/spidermonkey185/files/patch-jsstr.cpp @@ -0,0 +1,36 @@ +# HG changeset patch +# User Ehsan Akhgari <ehsan@mozilla.com> +# Date 1308517488 14400 +# Node ID 284ebc48b2cb8e35dc04482ede700e717d8d214f +# Parent cecc5adfc44068fb6f11b9baa78cb5fddc100b27 +Bug 662961 - Silence the clang warnings issued because of alignment requirements increase when compiling jsstr.cpp; r=Waldo + +--- ./jsstr.cpp.orig 2013-05-26 00:44:33.383765764 +1000 ++++ ./jsstr.cpp 2013-05-26 00:46:35.842211859 +1000 +@@ -3147,7 +3147,7 @@ + */ + #define R(c) { \ + BUILD_LENGTH_AND_FLAGS(1, JSString::FLAT | JSString::ATOMIZED), \ +- { (jschar *)(((char *)(unitStringTable + (c))) + \ ++ { (jschar *)(uintptr_t(unitStringTable + (c)) + \ + offsetof(JSString, inlineStorage)) }, \ + { {(c), 0x00} } } + +@@ -3207,7 +3207,7 @@ + */ + #define R(c) { \ + BUILD_LENGTH_AND_FLAGS(2, JSString::FLAT | JSString::ATOMIZED), \ +- { (jschar *)(((char *)(length2StringTable + (c))) + \ ++ { (jschar *)(uintptr_t(length2StringTable + (c)) + \ + offsetof(JSString, inlineStorage)) }, \ + { {FROM_SMALL_CHAR((c) >> 6), FROM_SMALL_CHAR((c) & 0x3F), 0x00} } } + +@@ -3240,7 +3240,7 @@ + */ + #define R(c) { \ + BUILD_LENGTH_AND_FLAGS(3, JSString::FLAT | JSString::ATOMIZED), \ +- { (jschar *)(((char *)(hundredStringTable + ((c) - 100))) + \ ++ { (jschar *)(uintptr_t(hundredStringTable + ((c) - 100)) + \ + offsetof(JSString, inlineStorage)) }, \ + { {((c) / 100) + '0', ((c) / 10 % 10) + '0', ((c) % 10) + '0', 0x00} } } + diff --git a/lang/spidermonkey185/files/patch-nanojit_CodeAlloc.cpp b/lang/spidermonkey185/files/patch-nanojit_CodeAlloc.cpp new file mode 100644 index 000000000000..52c65c0e9624 --- /dev/null +++ b/lang/spidermonkey185/files/patch-nanojit_CodeAlloc.cpp @@ -0,0 +1,10 @@ +--- nanojit/CodeAlloc.cpp.orig 2016-09-07 UTC ++++ nanojit/CodeAlloc.cpp +@@ -261,7 +261,6 @@ namespace nanojit + #endif + + #if defined(AVMPLUS_UNIX) && defined(NANOJIT_ARM) +-#include <asm/unistd.h> + extern "C" void __clear_cache(char *BEG, char *END); + #endif + diff --git a/lang/spidermonkey185/files/patch-nanojit_njcpudetect.h b/lang/spidermonkey185/files/patch-nanojit_njcpudetect.h new file mode 100644 index 000000000000..4a26a07ab688 --- /dev/null +++ b/lang/spidermonkey185/files/patch-nanojit_njcpudetect.h @@ -0,0 +1,11 @@ +--- nanojit/njcpudetect.h.orig 2016-09-07 UTC ++++ nanojit/njcpudetect.h +@@ -77,6 +77,8 @@ + #elif defined(__ARM_ARCH_6__) || \ + defined(__ARM_ARCH_6J__) || \ + defined(__ARM_ARCH_6T2__) || \ ++ defined(__ARM_ARCH_6K__) || \ ++ defined(__ARM_ARCH_6KZ__) || \ + defined(__ARM_ARCH_6Z__) || \ + defined(__ARM_ARCH_6ZK__) || \ + defined(__ARM_ARCH_6M__) || \ diff --git a/lang/spidermonkey185/pkg-descr b/lang/spidermonkey185/pkg-descr new file mode 100644 index 000000000000..db4318240eed --- /dev/null +++ b/lang/spidermonkey185/pkg-descr @@ -0,0 +1,3 @@ +Spidermonkey is the JavaScript interpreter from the Mozilla project. + +WWW: http://www.mozilla.org/js/spidermonkey/ diff --git a/lang/spidermonkey185/pkg-plist b/lang/spidermonkey185/pkg-plist new file mode 100644 index 000000000000..f7735572dd26 --- /dev/null +++ b/lang/spidermonkey185/pkg-plist @@ -0,0 +1,106 @@ +bin/js-config +include/js/Allocator.h +include/js/Assembler.h +include/js/CodeAlloc.h +include/js/Containers.h +include/js/Fragmento.h +include/js/LIR.h +include/js/LIRopcode.tbl +include/js/Native.h +include/js/NativeCommon.h +%%ARM%%/include/js/NativeARM.h +%%MIPS%%/include/js/NativeMIPS.h +%%PPC%%/include/js/NativePPC.h +%%SPARC%%/include/js/NativeSparc.h +%%AMD64%%include/js/NativeX64.h +%%I386%%include/js/Nativei386.h +include/js/RegAlloc.h +include/js/VMPI.h +include/js/Writer.h +include/js/avmplus.h +include/js/js-config.h +include/js/js.msg +include/js/jsanalyze.h +include/js/jsapi.h +include/js/jsarena.h +include/js/jsarray.h +include/js/jsatom.h +include/js/jsautocfg.h +include/js/jsautokw.h +include/js/jsbit.h +include/js/jsbool.h +include/js/jsbuiltins.h +include/js/jscell.h +include/js/jsclist.h +include/js/jsclone.h +include/js/jscntxt.h +include/js/jscompartment.h +include/js/jscompat.h +include/js/jsdate.h +include/js/jsdbgapi.h +include/js/jsdhash.h +include/js/jsdtoa.h +include/js/jsemit.h +include/js/jsfriendapi.h +include/js/jsfun.h +include/js/jsgc.h +include/js/jsgcchunk.h +include/js/jsgcstats.h +include/js/jshash.h +include/js/jshashtable.h +include/js/jshotloop.h +include/js/jsinterp.h +include/js/jsinttypes.h +include/js/jsiter.h +include/js/jslock.h +include/js/jslong.h +include/js/jsmath.h +include/js/jsobj.h +include/js/jsobjinlines.h +include/js/json.h +include/js/jsopcode.h +include/js/jsopcode.tbl +include/js/jsopcodeinlines.h +include/js/jsotypes.h +include/js/jsparse.h +include/js/jsperf.h +include/js/jsprf.h +include/js/jsprobes.h +include/js/jspropertycache.h +include/js/jspropertycacheinlines.h +include/js/jspropertytree.h +include/js/jsproto.tbl +include/js/jsproxy.h +include/js/jsprvtd.h +include/js/jspubtd.h +include/js/jsreflect.h +include/js/jsregexp.h +include/js/jsscan.h +include/js/jsscope.h +include/js/jsscript.h +include/js/jsscriptinlines.h +include/js/jsstaticcheck.h +include/js/jsstdint.h +include/js/jsstr.h +include/js/jstl.h +include/js/jstracer.h +include/js/jstypedarray.h +include/js/jstypes.h +include/js/jsutil.h +include/js/jsval.h +include/js/jsvalue.h +include/js/jsvector.h +include/js/jsversion.h +include/js/jswrapper.h +include/js/jsxdrapi.h +include/js/jsxml.h +include/js/nanojit.h +include/js/njconfig.h +include/js/njcpudetect.h +include/js/prmjtime.h +lib/libmozjs185.so +lib/libmozjs185-1.0.a +lib/libmozjs185.so.1.0.0 +lib/libmozjs185.so.1.0 +lib/libmozjs185.so.1 +libdata/pkgconfig/mozjs185.pc |