RPM Package Manager, CVS Repository http://rpm5.org/cvs/ ____________________________________________________________________________
Server: rpm5.org Name: Jeff Johnson Root: /v/rpm/cvs Email: j...@rpm5.org Module: rpm Date: 03-Jul-2017 05:41:37 Branch: rpm-5_4 Handle: 2017070303413600 Modified files: (Branch: rpm-5_4) rpm/rpmio rpmjs45.cpp Log: - rpmjs45: WOP. Summary: Revision Changes Path 1.1.2.16 +1007 -63 rpm/rpmio/rpmjs45.cpp ____________________________________________________________________________ patch -p0 <<'@@ .' Index: rpm/rpmio/rpmjs45.cpp ============================================================================ $ cvs diff -u -r1.1.2.15 -r1.1.2.16 rpmjs45.cpp --- rpm/rpmio/rpmjs45.cpp 2 Jul 2017 13:58:09 -0000 1.1.2.15 +++ rpm/rpmio/rpmjs45.cpp 3 Jul 2017 03:41:36 -0000 1.1.2.16 @@ -8,6 +8,8 @@ #define JS_CODEGEN_X64 1 +#include <nspr.h> + #include "mozilla/ArrayUtils.h" #include "mozilla/Atomics.h" #include "mozilla/DebugOnly.h" @@ -319,21 +321,25 @@ return obj; } -#ifdef NOTYET +#if !defined(FIXME) +JSString* +FileAsString(JSContext* cx, const char* pathname); +#endif + static bool ReadFile(JSContext* cx, unsigned argc, Value* vp, bool scriptRelative) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() < 1 || args.length() > 2) { - JS_ReportErrorNumber(cx, js::shell::my_GetErrorMessage, nullptr, + JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, args.length() < 1 ? JSSMSG_NOT_ENOUGH_ARGS : JSSMSG_TOO_MANY_ARGS, "snarf"); return false; } if (!args[0].isString() || (args.length() == 2 && !args[1].isString())) { - JS_ReportErrorNumber(cx, js::shell::my_GetErrorMessage, nullptr, JSSMSG_INVALID_ARGS, "snarf"); + JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, JSSMSG_INVALID_ARGS, "snarf"); return false; } @@ -367,23 +373,18 @@ args.rval().setString(str); return true; } -#endif -#ifdef NOTYET static bool osfile_readFile(JSContext* cx, unsigned argc, Value* vp) { return ReadFile(cx, argc, vp, false); } -#endif -#ifdef NOTYET static bool osfile_readRelativeToScript(JSContext* cx, unsigned argc, Value* vp) { return ReadFile(cx, argc, vp, true); } -#endif static bool osfile_writeTypedArrayToFile(JSContext* cx, unsigned argc, Value* vp) @@ -498,7 +499,6 @@ return true; } -#ifdef NOTYET static const JSFunctionSpecWithHelp osfile_functions[] = { JS_FN_HELP("readFile", osfile_readFile, 1, 0, "readFile(filename, [\"binary\"])", @@ -512,7 +512,6 @@ JS_FS_HELP_END }; -#endif static const JSFunctionSpecWithHelp osfile_unsafe_functions[] = { JS_FN_HELP("writeTypedArrayToFile", osfile_writeTypedArrayToFile, 2, 0, @@ -650,20 +649,18 @@ // other one returns an integer status code, and always writes the result into // the provided buffer. -#ifdef NOTYET inline char* strerror_message(int result, char* buffer) { return result == 0 ? buffer : nullptr; } -#endif inline char* strerror_message(char* result, char* buffer) { return result; } -#endif +#endif /* !XP_WIN */ static void ReportSysError(JSContext* cx, const char* prefix) @@ -969,7 +966,6 @@ static const double MAX_TIMEOUT_INTERVAL = 1800.0; // Per-runtime shell state. -#ifdef NOTYET struct ShellRuntime { ShellRuntime(); @@ -996,7 +992,6 @@ bool quitting; bool gotError; }; -#endif // Shell state set once at startup. static bool enableCodeCoverage = false; @@ -1119,7 +1114,6 @@ } // extern "C" #endif -#ifdef NOTYET ShellRuntime::ShellRuntime() : isWorker(false), timeoutInterval(-1.0), @@ -1135,9 +1129,7 @@ quitting(false), gotError(false) {} -#endif -#ifdef NOTYET static ShellRuntime* GetShellRuntime(JSRuntime *rt) { @@ -1145,7 +1137,6 @@ MOZ_ASSERT(sr); return sr; } -#endif #ifdef NOTYET static ShellRuntime* @@ -3801,9 +3792,7 @@ } #endif -#ifdef NOTYET Vector<PRThread*, 0, SystemAllocPolicy> workerThreads; -#endif #ifdef NOTYET static bool @@ -3925,7 +3914,6 @@ } #endif -#ifdef NOTYET static bool InitWatchdog(JSRuntime* rt) { @@ -3944,9 +3932,7 @@ } return false; } -#endif -#ifdef NOTYET static void KillWatchdog(JSRuntime* rt) { @@ -3970,9 +3956,7 @@ PR_DestroyCondVar(sr->watchdogWakeup); PR_DestroyLock(sr->watchdogLock); } -#endif -#ifdef NOTYET static void WatchdogMain(void* arg) { @@ -4021,9 +4005,7 @@ } PR_Unlock(sr->watchdogLock); } -#endif -#ifdef NOTYET static bool ScheduleWatchdog(JSRuntime* rt, double t) { @@ -4036,10 +4018,11 @@ return true; } - int64_t interval = int64_t(ceil(t * PRMJ_USEC_PER_SEC)); #ifdef FIXME + int64_t interval = int64_t(ceil(t * PRMJ_USEC_PER_SEC)); int64_t timeout = PRMJ_Now() + interval; #else + int64_t interval = int64_t(ceil(t * (1000. * 1000.))); struct timeval tv; gettimeofday(&tv, NULL); int64_t timeout = 1000 * 1000 * tv.tv_sec + tv.tv_usec; @@ -4067,9 +4050,7 @@ PR_Unlock(sr->watchdogLock); return true; } -#endif -#ifdef NOTYET static void CancelExecution(JSRuntime* rt) { @@ -4082,7 +4063,6 @@ fputs(msg, stderr); } } -#endif #ifdef NOTYET static bool @@ -4282,7 +4262,7 @@ } #endif -#ifdef DEBUG +#ifdef NOTYET static bool StackDump(JSContext* cx, unsigned argc, Value* vp) { @@ -4781,7 +4761,6 @@ } #endif -#ifdef NOTYET struct MOZ_RAII FreeOnReturn { JSContext* cx; @@ -4804,12 +4783,10 @@ JS_free(cx, (void*)ptr); } }; -#endif static int sArgc; static char** sArgv; -#ifdef NOTYET class AutoCStringVector { Vector<char*> argv_; @@ -4847,7 +4824,6 @@ argv_.back() = arg; } }; -#endif #if defined(XP_WIN) static bool @@ -4890,19 +4866,14 @@ } #endif -#ifdef NOTYET static Vector<const char*, 4, js::SystemAllocPolicy> sPropagatedFlags; -#endif -#ifdef NOTYET static bool PropagateFlagToNestedShells(const char* flag) { return sPropagatedFlags.append(flag); } -#endif -#ifdef NOTYET static bool NestedShell(JSContext* cx, unsigned argc, Value* vp) { @@ -4977,7 +4948,6 @@ args.rval().setUndefined(); return true; } -#endif #ifdef NOTYET static bool @@ -5437,19 +5407,15 @@ // decrements will be on a garbage object. We could implement this // with atomics and a CAS loop but it's not worth the bother. -#ifdef NOTYET static PRLock* sharedArrayBufferMailboxLock; static SharedArrayRawBuffer* sharedArrayBufferMailbox; -#endif -#ifdef NOTYET static bool InitSharedArrayBufferMailbox() { sharedArrayBufferMailboxLock = PR_NewLock(); return sharedArrayBufferMailboxLock != nullptr; } -#endif #ifdef NOTYET static void @@ -6700,17 +6666,504 @@ JS_GlobalObjectTraceHook }; -/*==============================================================*/ +/* + * Define a FakeDOMObject constructor. It returns an object with a getter, + * setter and method with attached JitInfo. This object can be used to test + * IonMonkey DOM optimizations in the shell. + */ +static const uint32_t DOM_OBJECT_SLOT = 0; + +static bool +dom_genericGetter(JSContext* cx, unsigned argc, JS::Value* vp); + +static bool +dom_genericSetter(JSContext* cx, unsigned argc, JS::Value* vp); + +static bool +dom_genericMethod(JSContext* cx, unsigned argc, JS::Value* vp); + +#ifdef DEBUG +static const JSClass* GetDomClass(); +#endif + +static bool +dom_get_x(JSContext* cx, HandleObject obj, void* self, JSJitGetterCallArgs args) +{ + MOZ_ASSERT(JS_GetClass(obj) == GetDomClass()); + MOZ_ASSERT(self == (void*)0x1234); + args.rval().set(JS_NumberValue(double(3.14))); + return true; +} + +static bool +dom_set_x(JSContext* cx, HandleObject obj, void* self, JSJitSetterCallArgs args) +{ + MOZ_ASSERT(JS_GetClass(obj) == GetDomClass()); + MOZ_ASSERT(self == (void*)0x1234); + return true; +} + +static bool +dom_doFoo(JSContext* cx, HandleObject obj, void* self, const JSJitMethodCallArgs& args) +{ + MOZ_ASSERT(JS_GetClass(obj) == GetDomClass()); + MOZ_ASSERT(self == (void*)0x1234); + + /* Just return args.length(). */ + args.rval().setInt32(args.length()); + return true; +} + +static const JSJitInfo dom_x_getterinfo = { + { (JSJitGetterOp)dom_get_x }, + { 0 }, /* protoID */ + 0, /* depth */ + JSJitInfo::AliasNone, /* aliasSet */ + JSJitInfo::Getter, + JSVAL_TYPE_UNKNOWN, /* returnType */ + true, /* isInfallible. False in setters. */ + true, /* isMovable */ + true, /* isEliminatable */ + false, /* isAlwaysInSlot */ + false, /* isLazilyCachedInSlot */ + false, /* isTypedMethod */ + 0 /* slotIndex */ +}; + +static const JSJitInfo dom_x_setterinfo = { + { (JSJitGetterOp)dom_set_x }, + { 0 }, /* protoID */ + 0, /* depth */ + JSJitInfo::Setter, + JSJitInfo::AliasEverything, /* aliasSet */ + JSVAL_TYPE_UNKNOWN, /* returnType */ + false, /* isInfallible. False in setters. */ + false, /* isMovable. */ + false, /* isEliminatable. */ + false, /* isAlwaysInSlot */ + false, /* isLazilyCachedInSlot */ + false, /* isTypedMethod */ + 0 /* slotIndex */ +}; + +static const JSJitInfo doFoo_methodinfo = { + { (JSJitGetterOp)dom_doFoo }, + { 0 }, /* protoID */ + 0, /* depth */ + JSJitInfo::Method, + JSJitInfo::AliasEverything, /* aliasSet */ + JSVAL_TYPE_UNKNOWN, /* returnType */ + false, /* isInfallible. False in setters. */ + false, /* isMovable */ + false, /* isEliminatable */ + false, /* isAlwaysInSlot */ + false, /* isLazilyCachedInSlot */ + false, /* isTypedMethod */ + 0 /* slotIndex */ +}; + +static const JSPropertySpec dom_props[] = { + {"x", + JSPROP_SHARED | JSPROP_ENUMERATE, + { { dom_genericGetter, &dom_x_getterinfo } }, + { { dom_genericSetter, &dom_x_setterinfo } } + }, + JS_PS_END +}; + +static const JSFunctionSpec dom_methods[] = { + JS_FNINFO("doFoo", dom_genericMethod, &doFoo_methodinfo, 3, JSPROP_ENUMERATE), + JS_FS_END +}; + +static const JSClass dom_class = { + "FakeDOMObject", JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(2) +}; + +#ifdef DEBUG +static const JSClass* GetDomClass() { + return &dom_class; +} +#endif + +static bool +dom_genericGetter(JSContext* cx, unsigned argc, JS::Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + RootedObject obj(cx, JS_THIS_OBJECT(cx, vp)); + if (!obj) + return false; + + if (JS_GetClass(obj) != &dom_class) { + args.rval().set(UndefinedValue()); + return true; + } + + JS::Value val = js::GetReservedSlot(obj, DOM_OBJECT_SLOT); + + const JSJitInfo* info = FUNCTION_VALUE_TO_JITINFO(args.calleev()); + MOZ_ASSERT(info->type() == JSJitInfo::Getter); + JSJitGetterOp getter = info->getter; + return getter(cx, obj, val.toPrivate(), JSJitGetterCallArgs(args)); +} + +static bool +dom_genericSetter(JSContext* cx, unsigned argc, JS::Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + RootedObject obj(cx, JS_THIS_OBJECT(cx, vp)); + if (!obj) + return false; + + MOZ_ASSERT(args.length() == 1); + + if (JS_GetClass(obj) != &dom_class) { + args.rval().set(UndefinedValue()); + return true; + } + + JS::Value val = js::GetReservedSlot(obj, DOM_OBJECT_SLOT); + + const JSJitInfo* info = FUNCTION_VALUE_TO_JITINFO(args.calleev()); + MOZ_ASSERT(info->type() == JSJitInfo::Setter); + JSJitSetterOp setter = info->setter; + if (!setter(cx, obj, val.toPrivate(), JSJitSetterCallArgs(args))) + return false; + args.rval().set(UndefinedValue()); + return true; +} + +static bool +dom_genericMethod(JSContext* cx, unsigned argc, JS::Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + RootedObject obj(cx, JS_THIS_OBJECT(cx, vp)); + if (!obj) + return false; + + if (JS_GetClass(obj) != &dom_class) { + args.rval().set(UndefinedValue()); + return true; + } + + JS::Value val = js::GetReservedSlot(obj, DOM_OBJECT_SLOT); + + const JSJitInfo* info = FUNCTION_VALUE_TO_JITINFO(args.calleev()); + MOZ_ASSERT(info->type() == JSJitInfo::Method); + JSJitMethodOp method = info->method; + return method(cx, obj, val.toPrivate(), JSJitMethodCallArgs(args)); +} + +static void +InitDOMObject(HandleObject obj) +{ + /* Fow now just initialize to a constant we can check. */ + SetReservedSlot(obj, DOM_OBJECT_SLOT, PrivateValue((void*)0x1234)); +} + +#ifdef NOTYET +static bool +dom_constructor(JSContext* cx, unsigned argc, JS::Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + + RootedObject callee(cx, &args.callee()); + RootedValue protov(cx); + if (!GetProperty(cx, callee, callee, cx->names().prototype, &protov)) + return false; + + if (!protov.isObject()) { + JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_BAD_PROTOTYPE, "FakeDOMObject"); + return false; + } + + RootedObject proto(cx, &protov.toObject()); + RootedObject domObj(cx, JS_NewObjectWithGivenProto(cx, &dom_class, proto)); + if (!domObj) + return false; + + InitDOMObject(domObj); + + args.rval().setObject(*domObj); + return true; +} +#endif + +static bool +InstanceClassHasProtoAtDepth(const Class* clasp, uint32_t protoID, uint32_t depth) +{ + /* There's only a single (fake) DOM object in the shell, so just return true. */ + return true; +} + +class ScopedFileDesc +{ + intptr_t fd_; + public: + enum LockType { READ_LOCK, WRITE_LOCK }; + ScopedFileDesc(int fd, LockType lockType) + : fd_(fd) + { + if (fd == -1) + return; + if (!jsCacheOpened.compareExchange(false, true)) { + close(fd_); + fd_ = -1; + return; + } + } + ~ScopedFileDesc() { + if (fd_ == -1) + return; + MOZ_ASSERT(jsCacheOpened == true); + jsCacheOpened = false; + close(fd_); + } + operator intptr_t() const { + return fd_; + } + intptr_t forget() { + intptr_t ret = fd_; + fd_ = -1; + return ret; + } +}; + +// To guard against corrupted cache files generated by previous crashes, write +// asmJSCacheCookie to the first uint32_t of the file only after the file is +// fully serialized and flushed to disk. +static const uint32_t asmJSCacheCookie = 0xabbadaba; + +static bool +ShellOpenAsmJSCacheEntryForRead(HandleObject global, const char16_t* begin, const char16_t* limit, + size_t* serializedSizeOut, const uint8_t** memoryOut, + intptr_t* handleOut) +{ + if (!jsCachingEnabled || !jsCacheAsmJSPath) + return false; + + ScopedFileDesc fd(open(jsCacheAsmJSPath, O_RDWR), ScopedFileDesc::READ_LOCK); + if (fd == -1) + return false; + + // Get the size and make sure we can dereference at least one uint32_t. + off_t off = lseek(fd, 0, SEEK_END); + if (off == -1 || off < (off_t)sizeof(uint32_t)) + return false; + + // Map the file into memory. + void* memory; +#ifdef XP_WIN + HANDLE fdOsHandle = (HANDLE)_get_osfhandle(fd); + HANDLE fileMapping = CreateFileMapping(fdOsHandle, nullptr, PAGE_READWRITE, 0, 0, nullptr); + if (!fileMapping) + return false; + + memory = MapViewOfFile(fileMapping, FILE_MAP_READ, 0, 0, 0); + CloseHandle(fileMapping); + if (!memory) + return false; +#else + memory = mmap(nullptr, off, PROT_READ, MAP_SHARED, fd, 0); + if (memory == MAP_FAILED) + return false; +#endif + + // Perform check described by asmJSCacheCookie comment. + if (*(uint32_t*)memory != asmJSCacheCookie) { +#ifdef XP_WIN + UnmapViewOfFile(memory); +#else + munmap(memory, off); +#endif + return false; + } + + // The embedding added the cookie so strip it off of the buffer returned to + // the JS engine. + *serializedSizeOut = off - sizeof(uint32_t); + *memoryOut = (uint8_t*)memory + sizeof(uint32_t); + *handleOut = fd.forget(); + return true; +} + +static void +ShellCloseAsmJSCacheEntryForRead(size_t serializedSize, const uint8_t* memory, intptr_t handle) +{ + // Undo the cookie adjustment done when opening the file. + memory -= sizeof(uint32_t); + serializedSize += sizeof(uint32_t); + + // Release the memory mapping and file. +#ifdef XP_WIN + UnmapViewOfFile(const_cast<uint8_t*>(memory)); +#else + munmap(const_cast<uint8_t*>(memory), serializedSize); +#endif + + MOZ_ASSERT(jsCacheOpened == true); + jsCacheOpened = false; + close(handle); +} + +static JS::AsmJSCacheResult +ShellOpenAsmJSCacheEntryForWrite(HandleObject global, bool installed, + const char16_t* begin, const char16_t* end, + size_t serializedSize, uint8_t** memoryOut, intptr_t* handleOut) +{ + if (!jsCachingEnabled || !jsCacheAsmJSPath) + return JS::AsmJSCache_Disabled_ShellFlags; + + // Create the cache directory if it doesn't already exist. + struct stat dirStat; + if (stat(jsCacheDir, &dirStat) == 0) { + if (!(dirStat.st_mode & S_IFDIR)) + return JS::AsmJSCache_InternalError; + } else { +#ifdef XP_WIN + if (mkdir(jsCacheDir) != 0) + return JS::AsmJSCache_InternalError; +#else + if (mkdir(jsCacheDir, 0777) != 0) + return JS::AsmJSCache_InternalError; +#endif + } + + ScopedFileDesc fd(open(jsCacheAsmJSPath, O_CREAT|O_RDWR, 0660), ScopedFileDesc::WRITE_LOCK); + if (fd == -1) + return JS::AsmJSCache_InternalError; + + // Include extra space for the asmJSCacheCookie. + serializedSize += sizeof(uint32_t); + + // Resize the file to the appropriate size after zeroing their contents. +#ifdef XP_WIN + if (chsize(fd, 0)) + return JS::AsmJSCache_InternalError; + if (chsize(fd, serializedSize)) + return JS::AsmJSCache_InternalError; +#else + if (ftruncate(fd, 0)) + return JS::AsmJSCache_InternalError; + if (ftruncate(fd, serializedSize)) + return JS::AsmJSCache_InternalError; +#endif + + // Map the file into memory. + void* memory; +#ifdef XP_WIN + HANDLE fdOsHandle = (HANDLE)_get_osfhandle(fd); + HANDLE fileMapping = CreateFileMapping(fdOsHandle, nullptr, PAGE_READWRITE, 0, 0, nullptr); + if (!fileMapping) + return JS::AsmJSCache_InternalError; + + memory = MapViewOfFile(fileMapping, FILE_MAP_WRITE, 0, 0, 0); + CloseHandle(fileMapping); + if (!memory) + return JS::AsmJSCache_InternalError; +#else + memory = mmap(nullptr, serializedSize, PROT_WRITE, MAP_SHARED, fd, 0); + if (memory == MAP_FAILED) + return JS::AsmJSCache_InternalError; +#endif + + // The embedding added the cookie so strip it off of the buffer returned to + // the JS engine. The asmJSCacheCookie will be written on close, below. + MOZ_ASSERT(*(uint32_t*)memory == 0); + *memoryOut = (uint8_t*)memory + sizeof(uint32_t); + *handleOut = fd.forget(); + return JS::AsmJSCache_Success; +} + +static void +ShellCloseAsmJSCacheEntryForWrite(size_t serializedSize, uint8_t* memory, intptr_t handle) +{ + // Undo the cookie adjustment done when opening the file. + memory -= sizeof(uint32_t); + serializedSize += sizeof(uint32_t); + + // Write the magic cookie value after flushing the entire cache entry. +#ifdef XP_WIN + FlushViewOfFile(memory, serializedSize); + FlushFileBuffers(HANDLE(_get_osfhandle(handle))); +#else + msync(memory, serializedSize, MS_SYNC); +#endif + + MOZ_ASSERT(*(uint32_t*)memory == 0); + *(uint32_t*)memory = asmJSCacheCookie; + + // Free the memory mapping and file. +#ifdef XP_WIN + UnmapViewOfFile(const_cast<uint8_t*>(memory)); +#else + munmap(memory, serializedSize); +#endif + + MOZ_ASSERT(jsCacheOpened == true); + jsCacheOpened = false; + close(handle); +} + +static bool +ShellBuildId(JS::BuildIdCharVector* buildId) +{ + // The browser embeds the date into the buildid and the buildid is embedded + // in the binary, so every 'make' necessarily builds a new firefox binary. + // Fortunately, the actual firefox executable is tiny -- all the code is in + // libxul.so and other shared modules -- so this isn't a big deal. Not so + // for the statically-linked JS shell. To avoid recompmiling js.cpp and + // re-linking 'js' on every 'make', we use a constant buildid and rely on + // the shell user to manually clear the cache (deleting the dir passed to + // --js-cache) between cache-breaking updates. Note: jit_tests.py does this + // on every run). + const char buildid[] = "JS-shell"; + return buildId->append(buildid, sizeof(buildid)); +} + +static const JS::AsmJSCacheOps asmJSCacheOps = { + ShellOpenAsmJSCacheEntryForRead, + ShellCloseAsmJSCacheEntryForRead, + ShellOpenAsmJSCacheEntryForWrite, + ShellCloseAsmJSCacheEntryForWrite, + ShellBuildId +}; + +static JSContext* +NewContext(JSRuntime* rt) +{ + JSContext* cx = JS_NewContext(rt, gStackChunkSize); + if (!cx) + return nullptr; + + JSShellContextData* data = NewContextData(); + if (!data) { + DestroyContext(cx, false); + return nullptr; + } + + JS_SetContextPrivate(cx, data); + return cx; +} + +static void +DestroyContext(JSContext* cx, bool withGC) +{ + // Don't use GetContextData as |data| could be a nullptr in the case of + // destroying a context precisely because we couldn't create its private + // data. + JSShellContextData* data = (JSShellContextData*) JS_GetContextPrivate(cx); + JS_SetContextPrivate(cx, nullptr); + js_free(data); + withGC ? JS_DestroyContext(cx) : JS_DestroyContextNoGC(cx); +} + static JSObject* NewGlobalObject(JSContext* cx, JS::CompartmentOptions& options, JSPrincipals* principals) { - - JSClass * _clasp = (JSClass *)&global_class; - const JSFunctionSpec * _functions = global_functions; /* XXX shell_functions */ - - RootedObject glob(cx, - JS_NewGlobalObject(cx, _clasp, principals, JS::DontFireOnNewGlobalHook, options)); + RootedObject glob(cx, JS_NewGlobalObject(cx, &global_class, principals, + JS::DontFireOnNewGlobalHook, options)); if (!glob) return nullptr; @@ -6722,25 +7175,23 @@ return nullptr; #endif -#ifdef DYING bool succeeded; if (!JS_SetImmutablePrototype(cx, glob, &succeeded)) return nullptr; MOZ_ASSERT(succeeded, "a fresh, unexposed global object is always capable of " "having its [[Prototype]] be immutable"); -#endif #ifdef JS_HAS_CTYPES if (!JS_InitCTypesClass(cx, glob)) return nullptr; #endif - -#ifdef MOZILLA_DYING if (!JS_InitReflectParse(cx, glob)) return nullptr; if (!JS_DefineDebuggerObject(cx, glob)) return nullptr; + +#ifdef FIXME if (!JS::RegisterPerfMeasurement(cx, glob)) return nullptr; if (!JS_DefineFunctionsWithHelp(cx, glob, shell_functions) || @@ -6748,14 +7199,14 @@ { return nullptr; } -#else /* MOZILLA_DYING */ - if (!JS_DefineFunctions(cx, glob, _functions)) +#else + if (!JS_DefineFunctions(cx, glob, global_functions)) { return nullptr; } -#endif /* MOZILLA_DYING */ +#endif -#ifdef DYING +#ifdef FIXME if (!js::DefineTestingFunctions(cx, glob, fuzzingSafe, disableOOMFunctions)) return nullptr; @@ -6768,6 +7219,7 @@ if (!DefineOS(cx, glob, fuzzingSafe)) return nullptr; +#endif RootedObject performanceObj(cx, JS_NewObject(cx, nullptr)); if (!performanceObj) @@ -6786,11 +7238,14 @@ return nullptr; /* Initialize FakeDOMObject. */ +#ifdef FIXME static const js::DOMCallbacks DOMcallbacks = { InstanceClassHasProtoAtDepth }; SetDOMCallbacks(cx->runtime(), &DOMcallbacks); +#endif +#ifdef FIXME RootedObject domProto(cx, JS_InitClass(cx, glob, nullptr, &dom_class, dom_constructor, 0, dom_props, dom_methods, nullptr, nullptr)); if (!domProto) @@ -6798,10 +7253,12 @@ /* Initialize FakeDOMObject.prototype */ InitDOMObject(domProto); +#endif +#ifdef FIXME if (!js::InitModuleClasses(cx, glob)) return nullptr; -#endif /* DYING */ +#endif } JS_FireOnNewGlobalObject(cx, glob); @@ -6809,6 +7266,493 @@ return glob; } +#ifdef NOTYET +static bool +BindScriptArgs(JSContext* cx, OptionParser* op) +{ + MultiStringRange msr = op->getMultiStringArg("scriptArgs"); + RootedObject scriptArgs(cx); + scriptArgs = JS_NewArrayObject(cx, 0); + if (!scriptArgs) + return false; + + if (!JS_DefineProperty(cx, cx->global(), "scriptArgs", scriptArgs, 0)) + return false; + + for (size_t i = 0; !msr.empty(); msr.popFront(), ++i) { + const char* scriptArg = msr.front(); + JS::RootedString str(cx, JS_NewStringCopyZ(cx, scriptArg)); + if (!str || + !JS_DefineElement(cx, scriptArgs, i, str, JSPROP_ENUMERATE)) + { + return false; + } + } + + const char* scriptPath = op->getStringArg("script"); + RootedValue scriptPathValue(cx); + if (scriptPath) { + RootedString scriptPathString(cx, JS_NewStringCopyZ(cx, scriptPath)); + if (!scriptPathString) + return false; + scriptPathValue = StringValue(scriptPathString); + } else { + scriptPathValue = UndefinedValue(); + } + + if (!JS_DefineProperty(cx, cx->global(), "scriptPath", scriptPathValue, 0)) + return false; + + return true; +} +#endif + +static bool +OptionFailure(const char* option, const char* str) +{ + fprintf(stderr, "Unrecognized option for %s: %s\n", option, str); + return false; +} + +#ifdef NOTYET +static int +ProcessArgs(JSContext* cx, OptionParser* op) +{ + ShellRuntime* sr = GetShellRuntime(cx); + + if (op->getBoolOption('s')) + JS::RuntimeOptionsRef(cx).toggleExtraWarnings(); + + /* |scriptArgs| gets bound on the global before any code is run. */ + if (!BindScriptArgs(cx, op)) + return EXIT_FAILURE; + + MultiStringRange filePaths = op->getMultiStringOption('f'); + MultiStringRange codeChunks = op->getMultiStringOption('e'); + MultiStringRange modulePaths = op->getMultiStringOption('m'); + + if (filePaths.empty() && + codeChunks.empty() && + modulePaths.empty() && + !op->getStringArg("script")) + { + Process(cx, nullptr, true); /* Interactive. */ + return sr->exitCode; + } + + if (const char* path = op->getStringOption("module-load-path")) + moduleLoadPath = path; + + if (!modulePaths.empty() && !InitModuleLoader(cx)) + return EXIT_FAILURE; + + while (!filePaths.empty() || !codeChunks.empty() || !modulePaths.empty()) { + size_t fpArgno = filePaths.empty() ? SIZE_MAX : filePaths.argno(); + size_t ccArgno = codeChunks.empty() ? SIZE_MAX : codeChunks.argno(); + size_t mpArgno = modulePaths.empty() ? SIZE_MAX : modulePaths.argno(); + + if (fpArgno < ccArgno && fpArgno < mpArgno) { + char* path = filePaths.front(); + Process(cx, path, false, FileScript); + if (sr->exitCode) + return sr->exitCode; + filePaths.popFront(); + } else if (ccArgno < fpArgno && ccArgno < mpArgno) { + const char* code = codeChunks.front(); + RootedValue rval(cx); + JS::CompileOptions opts(cx); + opts.setFileAndLine("-e", 1); + if (!JS::Evaluate(cx, opts, code, strlen(code), &rval)) + return sr->exitCode ? sr->exitCode : EXITCODE_RUNTIME_ERROR; + codeChunks.popFront(); + if (sr->quitting) + break; + } else { + MOZ_ASSERT(mpArgno < fpArgno && mpArgno < ccArgno); + char* path = modulePaths.front(); + Process(cx, path, false, FileModule); + if (sr->exitCode) + return sr->exitCode; + modulePaths.popFront(); + } + } + + if (sr->quitting) + return sr->exitCode ? sr->exitCode : EXIT_SUCCESS; + + /* The |script| argument is processed after all options. */ + if (const char* path = op->getStringArg("script")) { + Process(cx, path, false); + if (sr->exitCode) + return sr->exitCode; + } + + if (op->getBoolOption('i')) + Process(cx, nullptr, true); + + return sr->exitCode ? sr->exitCode : EXIT_SUCCESS; +} +#endif + +#ifdef NOTYET +static bool +SetRuntimeOptions(JSRuntime* rt, const OptionParser& op) +{ + enableBaseline = !op.getBoolOption("no-baseline"); + enableIon = !op.getBoolOption("no-ion"); + enableAsmJS = !op.getBoolOption("no-asmjs"); + enableNativeRegExp = !op.getBoolOption("no-native-regexp"); + enableUnboxedArrays = op.getBoolOption("unboxed-arrays"); + + JS::RuntimeOptionsRef(rt).setBaseline(enableBaseline) + .setIon(enableIon) + .setAsmJS(enableAsmJS) + .setNativeRegExp(enableNativeRegExp) + .setUnboxedArrays(enableUnboxedArrays); + +#ifdef FIXME + if (op.getBoolOption("no-unboxed-objects")) + jit::JitOptions.disableUnboxedObjects = true; + + if (const char* str = op.getStringOption("ion-scalar-replacement")) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableScalarReplacement = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableScalarReplacement = true; + else + return OptionFailure("ion-scalar-replacement", str); + } + + if (const char* str = op.getStringOption("ion-shared-stubs")) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableSharedStubs = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableSharedStubs = true; + else + return OptionFailure("ion-shared-stubs", str); + } + + if (const char* str = op.getStringOption("ion-gvn")) { + if (strcmp(str, "off") == 0) { + jit::JitOptions.disableGvn = true; + } else if (strcmp(str, "on") != 0 && + strcmp(str, "optimistic") != 0 && + strcmp(str, "pessimistic") != 0) + { + // We accept "pessimistic" and "optimistic" as synonyms for "on" + // for backwards compatibility. + return OptionFailure("ion-gvn", str); + } + } + + if (const char* str = op.getStringOption("ion-licm")) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableLicm = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableLicm = true; + else + return OptionFailure("ion-licm", str); + } + + if (const char* str = op.getStringOption("ion-edgecase-analysis")) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableEdgeCaseAnalysis = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableEdgeCaseAnalysis = true; + else + return OptionFailure("ion-edgecase-analysis", str); + } + + if (const char* str = op.getStringOption("ion-pgo")) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disablePgo = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disablePgo = true; + else + return OptionFailure("ion-pgo", str); + } + + if (const char* str = op.getStringOption("ion-range-analysis")) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableRangeAnalysis = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableRangeAnalysis = true; + else + return OptionFailure("ion-range-analysis", str); + } + + if (const char *str = op.getStringOption("ion-sincos")) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableSincos = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableSincos = true; + else + return OptionFailure("ion-sincos", str); + } + + if (const char* str = op.getStringOption("ion-sink")) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableSink = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableSink = true; + else + return OptionFailure("ion-sink", str); + } + + if (const char* str = op.getStringOption("ion-loop-unrolling")) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableLoopUnrolling = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableLoopUnrolling = true; + else + return OptionFailure("ion-loop-unrolling", str); + } + + if (const char* str = op.getStringOption("ion-instruction-reordering")) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableInstructionReordering = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableInstructionReordering = true; + else + return OptionFailure("ion-instruction-reordering", str); + } + + if (op.getBoolOption("ion-check-range-analysis")) + jit::JitOptions.checkRangeAnalysis = true; + + if (op.getBoolOption("ion-extra-checks")) + jit::JitOptions.runExtraChecks = true; + + if (const char* str = op.getStringOption("ion-inlining")) { + if (strcmp(str, "on") == 0) + jit::JitOptions.disableInlining = false; + else if (strcmp(str, "off") == 0) + jit::JitOptions.disableInlining = true; + else + return OptionFailure("ion-inlining", str); + } + + if (const char* str = op.getStringOption("ion-osr")) { + if (strcmp(str, "on") == 0) + jit::JitOptions.osr = true; + else if (strcmp(str, "off") == 0) + jit::JitOptions.osr = false; + else + return OptionFailure("ion-osr", str); + } + + if (const char* str = op.getStringOption("ion-limit-script-size")) { + if (strcmp(str, "on") == 0) + jit::JitOptions.limitScriptSize = true; + else if (strcmp(str, "off") == 0) + jit::JitOptions.limitScriptSize = false; + else + return OptionFailure("ion-limit-script-size", str); + } + + int32_t warmUpThreshold = op.getIntOption("ion-warmup-threshold"); + if (warmUpThreshold >= 0) + jit::JitOptions.setCompilerWarmUpThreshold(warmUpThreshold); + + warmUpThreshold = op.getIntOption("baseline-warmup-threshold"); + if (warmUpThreshold >= 0) + jit::JitOptions.baselineWarmUpThreshold = warmUpThreshold; + + if (op.getBoolOption("baseline-eager")) + jit::JitOptions.baselineWarmUpThreshold = 0; + + if (const char* str = op.getStringOption("ion-regalloc")) { + jit::JitOptions.forcedRegisterAllocator = jit::LookupRegisterAllocator(str); + if (!jit::JitOptions.forcedRegisterAllocator.isSome()) + return OptionFailure("ion-regalloc", str); + } + + if (op.getBoolOption("ion-eager")) + jit::JitOptions.setEagerCompilation(); + + offthreadCompilation = true; + if (const char* str = op.getStringOption("ion-offthread-compile")) { + if (strcmp(str, "off") == 0) + offthreadCompilation = false; + else if (strcmp(str, "on") != 0) + return OptionFailure("ion-offthread-compile", str); + } + rt->setOffthreadIonCompilationEnabled(offthreadCompilation); + + if (op.getStringOption("ion-parallel-compile")) { + fprintf(stderr, "--ion-parallel-compile is deprecated. Please use --ion-offthread-compile instead.\n"); + return false; + } + +#if defined(JS_CODEGEN_ARM) + if (const char* str = op.getStringOption("arm-hwcap")) + jit::ParseARMHwCapFlags(str); + + int32_t fill = op.getIntOption("arm-asm-nop-fill"); + if (fill >= 0) + jit::Assembler::NopFill = fill; + + int32_t poolMaxOffset = op.getIntOption("asm-pool-max-offset"); + if (poolMaxOffset >= 5 && poolMaxOffset <= 1024) + jit::Assembler::AsmPoolMaxOffset = poolMaxOffset; +#endif + +#if defined(JS_SIMULATOR_ARM) + if (op.getBoolOption("arm-sim-icache-checks")) + jit::Simulator::ICacheCheckingEnabled = true; + + int32_t stopAt = op.getIntOption("arm-sim-stop-at"); + if (stopAt >= 0) + jit::Simulator::StopSimAt = stopAt; +#elif defined(JS_SIMULATOR_MIPS32) || defined(JS_SIMULATOR_MIPS64) + if (op.getBoolOption("mips-sim-icache-checks")) + jit::Simulator::ICacheCheckingEnabled = true; + + int32_t stopAt = op.getIntOption("mips-sim-stop-at"); + if (stopAt >= 0) + jit::Simulator::StopSimAt = stopAt; +#endif + +#endif /* FIXME */ + + reportWarnings = op.getBoolOption('w'); + compileOnly = op.getBoolOption('c'); + printTiming = op.getBoolOption('b'); + enableCodeCoverage = op.getBoolOption("code-coverage"); + enableDisassemblyDumps = op.getBoolOption('D'); + rt->profilingScripts = enableCodeCoverage || enableDisassemblyDumps; + + jsCacheDir = op.getStringOption("js-cache"); + if (jsCacheDir) { + if (!op.getBoolOption("no-js-cache-per-process")) + jsCacheDir = JS_smprintf("%s/%u", jsCacheDir, (unsigned)getpid()); + else + jsCacheDir = JS_strdup(rt, jsCacheDir); + jsCacheAsmJSPath = JS_smprintf("%s/asmjs.cache", jsCacheDir); + } + +#ifdef DEBUG + dumpEntrainedVariables = op.getBoolOption("dump-entrained-variables"); +#endif + +#ifdef JS_GC_ZEAL + const char* zealStr = op.getStringOption("gc-zeal"); + gZealStr[0] = 0; + if (zealStr) { + if (!rt->gc.parseAndSetZeal(zealStr)) + return false; + strncpy(gZealStr, zealStr, sizeof(gZealStr)); + gZealStr[sizeof(gZealStr)-1] = 0; + } +#endif + + return true; +} +#endif + +static void +SetWorkerRuntimeOptions(JSRuntime* rt) +{ + // Copy option values from the main thread. + JS::RuntimeOptionsRef(rt).setBaseline(enableBaseline) + .setIon(enableIon) + .setAsmJS(enableAsmJS) + .setNativeRegExp(enableNativeRegExp) + .setUnboxedArrays(enableUnboxedArrays); + rt->setOffthreadIonCompilationEnabled(offthreadCompilation); + rt->profilingScripts = enableCodeCoverage || enableDisassemblyDumps; + +#ifdef JS_GC_ZEAL + if (*gZealStr) + rt->gc.parseAndSetZeal(gZealStr); +#endif + + JS_SetNativeStackQuota(rt, gMaxStackSize); +} + +#ifdef NOTYET +static int +Shell(JSContext* cx, OptionParser* op, char** envp) +{ + Maybe<JS::AutoDisableGenerationalGC> noggc; + if (op->getBoolOption("no-ggc")) + noggc.emplace(cx->runtime()); + + Maybe<AutoDisableCompactingGC> nocgc; + if (op->getBoolOption("no-cgc")) + nocgc.emplace(cx->runtime()); + + JSAutoRequest ar(cx); + + if (op->getBoolOption("fuzzing-safe")) + fuzzingSafe = true; + else + fuzzingSafe = (getenv("MOZ_FUZZING_SAFE") && getenv("MOZ_FUZZING_SAFE")[0] != '0'); + + if (op->getBoolOption("disable-oom-functions")) + disableOOMFunctions = true; + + RootedObject glob(cx); + JS::CompartmentOptions options; + options.setVersion(JSVERSION_DEFAULT); + glob = NewGlobalObject(cx, options, nullptr); + if (!glob) + return 1; + + JSAutoCompartment ac(cx, glob); + + int result = ProcessArgs(cx, op); + + if (enableDisassemblyDumps) + js::DumpCompartmentPCCounts(cx); + + if (!op->getBoolOption("no-js-cache-per-process")) { + if (jsCacheAsmJSPath) { + unlink(jsCacheAsmJSPath); + JS_free(cx, const_cast<char*>(jsCacheAsmJSPath)); + } + if (jsCacheDir) { + rmdir(jsCacheDir); + JS_free(cx, const_cast<char*>(jsCacheDir)); + } + } + + return result; +} +#endif + +static void +MaybeOverrideOutFileFromEnv(const char* const envVar, + FILE* defaultOut, + FILE** outFile) +{ + const char* outPath = getenv(envVar); + if (!outPath || !*outPath || !(*outFile = fopen(outPath, "w"))) { + *outFile = defaultOut; + } +} + +/* Pretend we can always preserve wrappers for dummy DOM objects. */ +static bool +DummyPreserveWrapperCallback(JSContext* cx, JSObject* obj) +{ + return true; +} + +static void +PreInit() +{ +#ifdef XP_WIN + const char* crash_option = getenv("XRE_NO_WINDOWS_CRASH_DIALOG"); + if (crash_option && strncmp(crash_option, "1", 1)) { + // Disable the segfault dialog. We want to fail the tests immediately + // instead of hanging automation. + UINT newMode = SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX; + UINT prevMode = SetErrorMode(newMode); + SetErrorMode(prevMode | newMode); + } +#endif +} /*==============================================================*/ static void mozFini(rpmjss jss) { @@ . ______________________________________________________________________ RPM Package Manager http://rpm5.org CVS Sources Repository rpm-cvs@rpm5.org